Copy disabled (too large)
Download .txt
Showing preview only (13,596K chars total). Download the full file to get everything.
Repository: o8oo8o/GoWebSSH
Branch: main
Commit: 2784fa78fb3e
Files: 997
Total size: 12.8 MB
Directory structure:
gitextract_q8k6q315/
├── .github/
│ └── workflows/
│ └── build-and-release.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── gossh/
│ ├── Makefile
│ ├── app/
│ │ ├── config/
│ │ │ └── config.go
│ │ ├── middleware/
│ │ │ ├── db_check.go
│ │ │ ├── jwt_auth.go
│ │ │ ├── net_filter.go
│ │ │ ├── perm_check.go
│ │ │ └── sys_init.go
│ │ ├── model/
│ │ │ ├── cmd_note.go
│ │ │ ├── datetime.go
│ │ │ ├── db_init.go
│ │ │ ├── login_audit.go
│ │ │ ├── net_filter.go
│ │ │ ├── policy_conf.go
│ │ │ ├── ssh_conf.go
│ │ │ ├── sshd_cert.go
│ │ │ ├── sshd_conf.go
│ │ │ ├── sshd_user.go
│ │ │ └── web_user.go
│ │ ├── service/
│ │ │ ├── cmd_note.go
│ │ │ ├── db_conn.go
│ │ │ ├── login_audit.go
│ │ │ ├── net_filter.go
│ │ │ ├── policy_conf.go
│ │ │ ├── service_init.go
│ │ │ ├── ssh_conf.go
│ │ │ ├── ssh_conn.go
│ │ │ ├── ssh_sftp.go
│ │ │ ├── ssh_status.go
│ │ │ ├── sshd_cert.go
│ │ │ ├── sshd_server.go
│ │ │ ├── sshd_user.go
│ │ │ ├── sys_init.go
│ │ │ └── web_user.go
│ │ └── utils/
│ │ ├── crypto.go
│ │ └── utils.go
│ ├── crypto/
│ │ ├── blowfish/
│ │ │ ├── block.go
│ │ │ ├── cipher.go
│ │ │ └── const.go
│ │ ├── chacha20/
│ │ │ ├── chacha_arm64.go
│ │ │ ├── chacha_arm64.s
│ │ │ ├── chacha_generic.go
│ │ │ ├── chacha_noasm.go
│ │ │ ├── chacha_ppc64le.go
│ │ │ ├── chacha_ppc64le.s
│ │ │ ├── chacha_s390x.go
│ │ │ ├── chacha_s390x.s
│ │ │ └── xor.go
│ │ ├── chacha20poly1305/
│ │ │ ├── chacha20poly1305.go
│ │ │ ├── chacha20poly1305_amd64.go
│ │ │ ├── chacha20poly1305_amd64.s
│ │ │ ├── chacha20poly1305_generic.go
│ │ │ ├── chacha20poly1305_noasm.go
│ │ │ └── xchacha20poly1305.go
│ │ ├── curve25519/
│ │ │ ├── curve25519.go
│ │ │ ├── curve25519_compat.go
│ │ │ ├── curve25519_go120.go
│ │ │ └── internal/
│ │ │ └── field/
│ │ │ ├── fe.go
│ │ │ ├── fe_amd64.go
│ │ │ ├── fe_amd64.s
│ │ │ ├── fe_amd64_noasm.go
│ │ │ ├── fe_arm64.go
│ │ │ ├── fe_arm64.s
│ │ │ ├── fe_arm64_noasm.go
│ │ │ ├── fe_generic.go
│ │ │ ├── sync.checkpoint
│ │ │ └── sync.sh
│ │ ├── internal/
│ │ │ ├── alias/
│ │ │ │ ├── alias.go
│ │ │ │ └── alias_purego.go
│ │ │ ├── poly1305/
│ │ │ │ ├── mac_noasm.go
│ │ │ │ ├── poly1305.go
│ │ │ │ ├── sum_amd64.go
│ │ │ │ ├── sum_amd64.s
│ │ │ │ ├── sum_generic.go
│ │ │ │ ├── sum_ppc64le.go
│ │ │ │ ├── sum_ppc64le.s
│ │ │ │ ├── sum_s390x.go
│ │ │ │ └── sum_s390x.s
│ │ │ └── testenv/
│ │ │ ├── exec.go
│ │ │ ├── testenv_notunix.go
│ │ │ └── testenv_unix.go
│ │ └── ssh/
│ │ ├── agent/
│ │ │ ├── client.go
│ │ │ ├── forward.go
│ │ │ ├── keyring.go
│ │ │ └── server.go
│ │ ├── buffer.go
│ │ ├── certs.go
│ │ ├── channel.go
│ │ ├── cipher.go
│ │ ├── client.go
│ │ ├── client_auth.go
│ │ ├── common.go
│ │ ├── connection.go
│ │ ├── doc.go
│ │ ├── handshake.go
│ │ ├── internal/
│ │ │ └── bcrypt_pbkdf/
│ │ │ └── bcrypt_pbkdf.go
│ │ ├── kex.go
│ │ ├── keys.go
│ │ ├── knownhosts/
│ │ │ └── knownhosts.go
│ │ ├── mac.go
│ │ ├── messages.go
│ │ ├── mux.go
│ │ ├── server.go
│ │ ├── session.go
│ │ ├── ssh_gss.go
│ │ ├── streamlocal.go
│ │ ├── tcpip.go
│ │ ├── terminal/
│ │ │ └── terminal.go
│ │ └── transport.go
│ ├── gin/
│ │ ├── auth.go
│ │ ├── binding/
│ │ │ ├── binding.go
│ │ │ ├── default_validator.go
│ │ │ ├── form.go
│ │ │ ├── form_mapping.go
│ │ │ ├── header.go
│ │ │ ├── json.go
│ │ │ ├── multipart_form_mapping.go
│ │ │ ├── query.go
│ │ │ ├── uri.go
│ │ │ └── xml.go
│ │ ├── context.go
│ │ ├── debug.go
│ │ ├── errors.go
│ │ ├── fs.go
│ │ ├── gin.go
│ │ ├── ginS/
│ │ │ ├── README.md
│ │ │ └── gins.go
│ │ ├── internal/
│ │ │ ├── bytesconv/
│ │ │ │ └── bytesconv.go
│ │ │ └── json/
│ │ │ └── json.go
│ │ ├── jwt/
│ │ │ ├── README.md
│ │ │ ├── claims.go
│ │ │ ├── cmd/
│ │ │ │ └── jwt/
│ │ │ │ ├── README.md
│ │ │ │ └── main.go
│ │ │ ├── ecdsa.go
│ │ │ ├── ecdsa_utils.go
│ │ │ ├── ed25519.go
│ │ │ ├── ed25519_utils.go
│ │ │ ├── errors.go
│ │ │ ├── errors_go1_20.go
│ │ │ ├── errors_go_other.go
│ │ │ ├── hmac.go
│ │ │ ├── map_claims.go
│ │ │ ├── none.go
│ │ │ ├── parser.go
│ │ │ ├── parser_option.go
│ │ │ ├── registered_claims.go
│ │ │ ├── request/
│ │ │ │ ├── doc.go
│ │ │ │ ├── extractor.go
│ │ │ │ ├── oauth2.go
│ │ │ │ └── request.go
│ │ │ ├── rsa.go
│ │ │ ├── rsa_pss.go
│ │ │ ├── rsa_utils.go
│ │ │ ├── signing_method.go
│ │ │ ├── token.go
│ │ │ ├── token_option.go
│ │ │ ├── types.go
│ │ │ └── validator.go
│ │ ├── logger.go
│ │ ├── mode.go
│ │ ├── path.go
│ │ ├── recovery.go
│ │ ├── render/
│ │ │ ├── data.go
│ │ │ ├── html.go
│ │ │ ├── json.go
│ │ │ ├── reader.go
│ │ │ ├── redirect.go
│ │ │ ├── render.go
│ │ │ ├── text.go
│ │ │ └── xml.go
│ │ ├── response_writer.go
│ │ ├── routergroup.go
│ │ ├── sessions/
│ │ │ ├── context/
│ │ │ │ └── context.go
│ │ │ ├── cookie/
│ │ │ │ └── cookie.go
│ │ │ ├── memstore/
│ │ │ │ ├── cache.go
│ │ │ │ ├── memstore.go
│ │ │ │ └── store.go
│ │ │ ├── securecookie/
│ │ │ │ └── securecookie.go
│ │ │ ├── session_options_go1.10.go
│ │ │ ├── session_options_go1.11.go
│ │ │ ├── sessions/
│ │ │ │ ├── cookie.go
│ │ │ │ ├── cookie_go111.go
│ │ │ │ ├── doc.go
│ │ │ │ ├── lex.go
│ │ │ │ ├── options.go
│ │ │ │ ├── options_go111.go
│ │ │ │ ├── sessions.go
│ │ │ │ └── store.go
│ │ │ └── sessions.go
│ │ ├── sse/
│ │ │ ├── sse-decoder.go
│ │ │ ├── sse-encoder.go
│ │ │ └── writer.go
│ │ ├── tree.go
│ │ ├── utils.go
│ │ ├── validator/
│ │ │ ├── baked_in.go
│ │ │ ├── cache.go
│ │ │ ├── country_codes.go
│ │ │ ├── currency_codes.go
│ │ │ ├── errors.go
│ │ │ ├── field_level.go
│ │ │ ├── options.go
│ │ │ ├── postcode_regexes.go
│ │ │ ├── regexes.go
│ │ │ ├── struct_level.go
│ │ │ ├── util.go
│ │ │ ├── validator.go
│ │ │ └── validator_instance.go
│ │ └── version.go
│ ├── go.mod
│ ├── gorm/
│ │ ├── association.go
│ │ ├── callbacks/
│ │ │ ├── associations.go
│ │ │ ├── callbacks.go
│ │ │ ├── callmethod.go
│ │ │ ├── create.go
│ │ │ ├── delete.go
│ │ │ ├── helper.go
│ │ │ ├── interfaces.go
│ │ │ ├── preload.go
│ │ │ ├── query.go
│ │ │ ├── raw.go
│ │ │ ├── row.go
│ │ │ ├── transaction.go
│ │ │ └── update.go
│ │ ├── callbacks.go
│ │ ├── chainable_api.go
│ │ ├── clause/
│ │ │ ├── clause.go
│ │ │ ├── delete.go
│ │ │ ├── expression.go
│ │ │ ├── from.go
│ │ │ ├── group_by.go
│ │ │ ├── insert.go
│ │ │ ├── joins.go
│ │ │ ├── limit.go
│ │ │ ├── locking.go
│ │ │ ├── on_conflict.go
│ │ │ ├── order_by.go
│ │ │ ├── returning.go
│ │ │ ├── select.go
│ │ │ ├── set.go
│ │ │ ├── update.go
│ │ │ ├── values.go
│ │ │ ├── where.go
│ │ │ └── with.go
│ │ ├── driver/
│ │ │ ├── mysql/
│ │ │ │ ├── error_translator.go
│ │ │ │ ├── migrator.go
│ │ │ │ └── mysql.go
│ │ │ └── pgsql/
│ │ │ ├── error_translator.go
│ │ │ ├── migrator.go
│ │ │ └── postgres.go
│ │ ├── errors.go
│ │ ├── finisher_api.go
│ │ ├── gorm.go
│ │ ├── inflection/
│ │ │ └── inflections.go
│ │ ├── interfaces.go
│ │ ├── logger/
│ │ │ ├── logger.go
│ │ │ └── sql.go
│ │ ├── migrator/
│ │ │ ├── column_type.go
│ │ │ ├── index.go
│ │ │ ├── migrator.go
│ │ │ └── table_type.go
│ │ ├── migrator.go
│ │ ├── model.go
│ │ ├── now/
│ │ │ ├── main.go
│ │ │ ├── now.go
│ │ │ └── time.go
│ │ ├── prepare_stmt.go
│ │ ├── scan.go
│ │ ├── schema/
│ │ │ ├── constraint.go
│ │ │ ├── field.go
│ │ │ ├── index.go
│ │ │ ├── interfaces.go
│ │ │ ├── naming.go
│ │ │ ├── pool.go
│ │ │ ├── relationship.go
│ │ │ ├── schema.go
│ │ │ ├── serializer.go
│ │ │ └── utils.go
│ │ ├── soft_delete.go
│ │ ├── statement.go
│ │ └── utils/
│ │ ├── tests/
│ │ │ ├── dummy_dialecter.go
│ │ │ ├── models.go
│ │ │ └── utils.go
│ │ └── utils.go
│ ├── main.go
│ ├── mysql/
│ │ ├── atomic_bool.go
│ │ ├── atomic_bool_go118.go
│ │ ├── auth.go
│ │ ├── buffer.go
│ │ ├── collations.go
│ │ ├── conncheck.go
│ │ ├── conncheck_dummy.go
│ │ ├── connection.go
│ │ ├── connector.go
│ │ ├── const.go
│ │ ├── driver.go
│ │ ├── dsn.go
│ │ ├── errors.go
│ │ ├── fields.go
│ │ ├── infile.go
│ │ ├── nulltime.go
│ │ ├── packets.go
│ │ ├── result.go
│ │ ├── rows.go
│ │ ├── statement.go
│ │ ├── transaction.go
│ │ └── utils.go
│ ├── pgsql/
│ │ ├── array.go
│ │ ├── buf.go
│ │ ├── conn.go
│ │ ├── conn_go115.go
│ │ ├── conn_go18.go
│ │ ├── connector.go
│ │ ├── copy.go
│ │ ├── encode.go
│ │ ├── error.go
│ │ ├── hstore/
│ │ │ └── hstore.go
│ │ ├── krb.go
│ │ ├── notice.go
│ │ ├── notify.go
│ │ ├── oid/
│ │ │ ├── doc.go
│ │ │ ├── gen.go
│ │ │ └── types.go
│ │ ├── rows.go
│ │ ├── scram/
│ │ │ └── scram.go
│ │ ├── ssl.go
│ │ ├── ssl_permissions.go
│ │ ├── ssl_windows.go
│ │ ├── url.go
│ │ ├── user_other.go
│ │ ├── user_posix.go
│ │ ├── user_windows.go
│ │ └── uuid.go
│ ├── pty/
│ │ ├── asm_solaris_amd64.s
│ │ ├── cmd_windows.go
│ │ ├── doc.go
│ │ ├── ioctl.go
│ │ ├── ioctl_bsd.go
│ │ ├── ioctl_inner.go
│ │ ├── ioctl_legacy.go
│ │ ├── ioctl_solaris.go
│ │ ├── ioctl_unsupported.go
│ │ ├── pty_darwin.go
│ │ ├── pty_dragonfly.go
│ │ ├── pty_freebsd.go
│ │ ├── pty_linux.go
│ │ ├── pty_netbsd.go
│ │ ├── pty_openbsd.go
│ │ ├── pty_solaris.go
│ │ ├── pty_unsupported.go
│ │ ├── pty_windows.go
│ │ ├── run.go
│ │ ├── run_unix.go
│ │ ├── run_windows.go
│ │ ├── types.go
│ │ ├── types_dragonfly.go
│ │ ├── types_freebsd.go
│ │ ├── types_netbsd.go
│ │ ├── types_openbsd.go
│ │ ├── winsize.go
│ │ ├── winsize_unix.go
│ │ ├── winsize_windows.go
│ │ ├── ztypes_386.go
│ │ ├── ztypes_amd64.go
│ │ ├── ztypes_arm.go
│ │ ├── ztypes_arm64.go
│ │ ├── ztypes_dragonfly_amd64.go
│ │ ├── ztypes_freebsd_386.go
│ │ ├── ztypes_freebsd_amd64.go
│ │ ├── ztypes_freebsd_arm.go
│ │ ├── ztypes_freebsd_arm64.go
│ │ ├── ztypes_freebsd_ppc64.go
│ │ ├── ztypes_freebsd_riscv64.go
│ │ ├── ztypes_loong64.go
│ │ ├── ztypes_mipsx.go
│ │ ├── ztypes_netbsd_32bit_int.go
│ │ ├── ztypes_openbsd_32bit_int.go
│ │ ├── ztypes_ppc.go
│ │ ├── ztypes_ppc64.go
│ │ ├── ztypes_ppc64le.go
│ │ ├── ztypes_riscvx.go
│ │ ├── ztypes_s390x.go
│ │ └── ztypes_sparcx.go
│ ├── readme.md
│ ├── sftp/
│ │ ├── allocator.go
│ │ ├── attrs.go
│ │ ├── attrs_stubs.go
│ │ ├── attrs_unix.go
│ │ ├── client.go
│ │ ├── conn.go
│ │ ├── debug.go
│ │ ├── fuzz.go
│ │ ├── internal/
│ │ │ ├── encoding/
│ │ │ │ └── ssh/
│ │ │ │ └── filexfer/
│ │ │ │ ├── attrs.go
│ │ │ │ ├── buffer.go
│ │ │ │ ├── extended_packets.go
│ │ │ │ ├── extensions.go
│ │ │ │ ├── filexfer.go
│ │ │ │ ├── fx.go
│ │ │ │ ├── fxp.go
│ │ │ │ ├── handle_packets.go
│ │ │ │ ├── init_packets.go
│ │ │ │ ├── open_packets.go
│ │ │ │ ├── openssh/
│ │ │ │ │ ├── fsync.go
│ │ │ │ │ ├── hardlink.go
│ │ │ │ │ ├── openssh.go
│ │ │ │ │ ├── posix-rename.go
│ │ │ │ │ └── statvfs.go
│ │ │ │ ├── packets.go
│ │ │ │ ├── path_packets.go
│ │ │ │ ├── permissions.go
│ │ │ │ └── response_packets.go
│ │ │ └── sftpfs/
│ │ │ ├── filesystem.go
│ │ │ └── walk.go
│ │ ├── ls_formatting.go
│ │ ├── ls_plan9.go
│ │ ├── ls_stub.go
│ │ ├── ls_unix.go
│ │ ├── match.go
│ │ ├── packet-manager.go
│ │ ├── packet-typing.go
│ │ ├── packet.go
│ │ ├── pool.go
│ │ ├── release.go
│ │ ├── request-attrs.go
│ │ ├── request-errors.go
│ │ ├── request-example.go
│ │ ├── request-interfaces.go
│ │ ├── request-plan9.go
│ │ ├── request-server.go
│ │ ├── request-unix.go
│ │ ├── request.go
│ │ ├── request_windows.go
│ │ ├── server.go
│ │ ├── server_plan9.go
│ │ ├── server_statvfs_darwin.go
│ │ ├── server_statvfs_impl.go
│ │ ├── server_statvfs_linux.go
│ │ ├── server_statvfs_plan9.go
│ │ ├── server_statvfs_stubs.go
│ │ ├── server_unix.go
│ │ ├── server_windows.go
│ │ ├── sftp.go
│ │ ├── stat_plan9.go
│ │ ├── stat_posix.go
│ │ ├── syscall_fixed.go
│ │ └── syscall_good.go
│ ├── sqlite/
│ │ ├── ddlmod.go
│ │ ├── errors.go
│ │ ├── migrator.go
│ │ └── sqlite.go
│ ├── sys/
│ │ ├── cpu/
│ │ │ ├── asm_aix_ppc64.s
│ │ │ ├── byteorder.go
│ │ │ ├── cpu.go
│ │ │ ├── cpu_aix.go
│ │ │ ├── cpu_arm.go
│ │ │ ├── cpu_arm64.go
│ │ │ ├── cpu_arm64.s
│ │ │ ├── cpu_gc_arm64.go
│ │ │ ├── cpu_gc_s390x.go
│ │ │ ├── cpu_gc_x86.go
│ │ │ ├── cpu_gccgo_arm64.go
│ │ │ ├── cpu_gccgo_s390x.go
│ │ │ ├── cpu_gccgo_x86.c
│ │ │ ├── cpu_gccgo_x86.go
│ │ │ ├── cpu_linux.go
│ │ │ ├── cpu_linux_arm.go
│ │ │ ├── cpu_linux_arm64.go
│ │ │ ├── cpu_linux_mips64x.go
│ │ │ ├── cpu_linux_noinit.go
│ │ │ ├── cpu_linux_ppc64x.go
│ │ │ ├── cpu_linux_s390x.go
│ │ │ ├── cpu_loong64.go
│ │ │ ├── cpu_mips64x.go
│ │ │ ├── cpu_mipsx.go
│ │ │ ├── cpu_netbsd_arm64.go
│ │ │ ├── cpu_openbsd_arm64.go
│ │ │ ├── cpu_openbsd_arm64.s
│ │ │ ├── cpu_other_arm.go
│ │ │ ├── cpu_other_arm64.go
│ │ │ ├── cpu_other_mips64x.go
│ │ │ ├── cpu_other_ppc64x.go
│ │ │ ├── cpu_other_riscv64.go
│ │ │ ├── cpu_ppc64x.go
│ │ │ ├── cpu_riscv64.go
│ │ │ ├── cpu_s390x.go
│ │ │ ├── cpu_s390x.s
│ │ │ ├── cpu_wasm.go
│ │ │ ├── cpu_x86.go
│ │ │ ├── cpu_x86.s
│ │ │ ├── cpu_zos.go
│ │ │ ├── cpu_zos_s390x.go
│ │ │ ├── endian_big.go
│ │ │ ├── endian_little.go
│ │ │ ├── hwcap_linux.go
│ │ │ ├── parse.go
│ │ │ ├── proc_cpuinfo_linux.go
│ │ │ ├── runtime_auxv.go
│ │ │ ├── runtime_auxv_go121.go
│ │ │ ├── syscall_aix_gccgo.go
│ │ │ └── syscall_aix_ppc64_gc.go
│ │ ├── execabs/
│ │ │ ├── execabs.go
│ │ │ ├── execabs_go118.go
│ │ │ └── execabs_go119.go
│ │ ├── plan9/
│ │ │ ├── asm.s
│ │ │ ├── asm_plan9_386.s
│ │ │ ├── asm_plan9_amd64.s
│ │ │ ├── asm_plan9_arm.s
│ │ │ ├── const_plan9.go
│ │ │ ├── dir_plan9.go
│ │ │ ├── env_plan9.go
│ │ │ ├── errors_plan9.go
│ │ │ ├── mkall.sh
│ │ │ ├── mkerrors.sh
│ │ │ ├── mksyscall.go
│ │ │ ├── mksysnum_plan9.sh
│ │ │ ├── pwd_go15_plan9.go
│ │ │ ├── pwd_plan9.go
│ │ │ ├── race.go
│ │ │ ├── race0.go
│ │ │ ├── str.go
│ │ │ ├── syscall.go
│ │ │ ├── syscall_plan9.go
│ │ │ ├── zsyscall_plan9_386.go
│ │ │ ├── zsyscall_plan9_amd64.go
│ │ │ ├── zsyscall_plan9_arm.go
│ │ │ └── zsysnum_plan9.go
│ │ ├── unix/
│ │ │ ├── README.md
│ │ │ ├── affinity_linux.go
│ │ │ ├── aliases.go
│ │ │ ├── asm_aix_ppc64.s
│ │ │ ├── asm_bsd_386.s
│ │ │ ├── asm_bsd_amd64.s
│ │ │ ├── asm_bsd_arm.s
│ │ │ ├── asm_bsd_arm64.s
│ │ │ ├── asm_bsd_ppc64.s
│ │ │ ├── asm_bsd_riscv64.s
│ │ │ ├── asm_linux_386.s
│ │ │ ├── asm_linux_amd64.s
│ │ │ ├── asm_linux_arm.s
│ │ │ ├── asm_linux_arm64.s
│ │ │ ├── asm_linux_loong64.s
│ │ │ ├── asm_linux_mips64x.s
│ │ │ ├── asm_linux_mipsx.s
│ │ │ ├── asm_linux_ppc64x.s
│ │ │ ├── asm_linux_riscv64.s
│ │ │ ├── asm_linux_s390x.s
│ │ │ ├── asm_openbsd_mips64.s
│ │ │ ├── asm_solaris_amd64.s
│ │ │ ├── asm_zos_s390x.s
│ │ │ ├── bluetooth_linux.go
│ │ │ ├── cap_freebsd.go
│ │ │ ├── constants.go
│ │ │ ├── dev_aix_ppc.go
│ │ │ ├── dev_aix_ppc64.go
│ │ │ ├── dev_darwin.go
│ │ │ ├── dev_dragonfly.go
│ │ │ ├── dev_freebsd.go
│ │ │ ├── dev_linux.go
│ │ │ ├── dev_netbsd.go
│ │ │ ├── dev_openbsd.go
│ │ │ ├── dev_zos.go
│ │ │ ├── dirent.go
│ │ │ ├── endian_big.go
│ │ │ ├── endian_little.go
│ │ │ ├── env_unix.go
│ │ │ ├── epoll_zos.go
│ │ │ ├── fcntl.go
│ │ │ ├── fcntl_darwin.go
│ │ │ ├── fcntl_linux_32bit.go
│ │ │ ├── fdset.go
│ │ │ ├── fstatfs_zos.go
│ │ │ ├── gccgo.go
│ │ │ ├── gccgo_c.c
│ │ │ ├── gccgo_linux_amd64.go
│ │ │ ├── ifreq_linux.go
│ │ │ ├── internal/
│ │ │ │ └── mkmerge/
│ │ │ │ └── mkmerge.go
│ │ │ ├── ioctl_linux.go
│ │ │ ├── ioctl_signed.go
│ │ │ ├── ioctl_unsigned.go
│ │ │ ├── ioctl_zos.go
│ │ │ ├── linux/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── mkall.go
│ │ │ │ ├── mksysnum.go
│ │ │ │ └── types.go
│ │ │ ├── mkall.sh
│ │ │ ├── mkasm.go
│ │ │ ├── mkerrors.sh
│ │ │ ├── mkpost.go
│ │ │ ├── mksyscall.go
│ │ │ ├── mksyscall_aix_ppc.go
│ │ │ ├── mksyscall_aix_ppc64.go
│ │ │ ├── mksyscall_solaris.go
│ │ │ ├── mksysctl_openbsd.go
│ │ │ ├── mksysnum.go
│ │ │ ├── mmap_nomremap.go
│ │ │ ├── mremap.go
│ │ │ ├── pagesize_unix.go
│ │ │ ├── pledge_openbsd.go
│ │ │ ├── ptrace_darwin.go
│ │ │ ├── ptrace_ios.go
│ │ │ ├── race.go
│ │ │ ├── race0.go
│ │ │ ├── readdirent_getdents.go
│ │ │ ├── readdirent_getdirentries.go
│ │ │ ├── sockcmsg_dragonfly.go
│ │ │ ├── sockcmsg_linux.go
│ │ │ ├── sockcmsg_unix.go
│ │ │ ├── sockcmsg_unix_other.go
│ │ │ ├── syscall.go
│ │ │ ├── syscall_aix.go
│ │ │ ├── syscall_aix_ppc.go
│ │ │ ├── syscall_aix_ppc64.go
│ │ │ ├── syscall_bsd.go
│ │ │ ├── syscall_darwin.go
│ │ │ ├── syscall_darwin_amd64.go
│ │ │ ├── syscall_darwin_arm64.go
│ │ │ ├── syscall_darwin_libSystem.go
│ │ │ ├── syscall_dragonfly.go
│ │ │ ├── syscall_dragonfly_amd64.go
│ │ │ ├── syscall_freebsd.go
│ │ │ ├── syscall_freebsd_386.go
│ │ │ ├── syscall_freebsd_amd64.go
│ │ │ ├── syscall_freebsd_arm.go
│ │ │ ├── syscall_freebsd_arm64.go
│ │ │ ├── syscall_freebsd_riscv64.go
│ │ │ ├── syscall_hurd.go
│ │ │ ├── syscall_hurd_386.go
│ │ │ ├── syscall_illumos.go
│ │ │ ├── syscall_linux.go
│ │ │ ├── syscall_linux_386.go
│ │ │ ├── syscall_linux_alarm.go
│ │ │ ├── syscall_linux_amd64.go
│ │ │ ├── syscall_linux_amd64_gc.go
│ │ │ ├── syscall_linux_arm.go
│ │ │ ├── syscall_linux_arm64.go
│ │ │ ├── syscall_linux_gc.go
│ │ │ ├── syscall_linux_gc_386.go
│ │ │ ├── syscall_linux_gc_arm.go
│ │ │ ├── syscall_linux_gccgo_386.go
│ │ │ ├── syscall_linux_gccgo_arm.go
│ │ │ ├── syscall_linux_loong64.go
│ │ │ ├── syscall_linux_mips64x.go
│ │ │ ├── syscall_linux_mipsx.go
│ │ │ ├── syscall_linux_ppc.go
│ │ │ ├── syscall_linux_ppc64x.go
│ │ │ ├── syscall_linux_riscv64.go
│ │ │ ├── syscall_linux_s390x.go
│ │ │ ├── syscall_linux_sparc64.go
│ │ │ ├── syscall_netbsd.go
│ │ │ ├── syscall_netbsd_386.go
│ │ │ ├── syscall_netbsd_amd64.go
│ │ │ ├── syscall_netbsd_arm.go
│ │ │ ├── syscall_netbsd_arm64.go
│ │ │ ├── syscall_openbsd.go
│ │ │ ├── syscall_openbsd_386.go
│ │ │ ├── syscall_openbsd_amd64.go
│ │ │ ├── syscall_openbsd_arm.go
│ │ │ ├── syscall_openbsd_arm64.go
│ │ │ ├── syscall_openbsd_libc.go
│ │ │ ├── syscall_openbsd_mips64.go
│ │ │ ├── syscall_openbsd_ppc64.go
│ │ │ ├── syscall_openbsd_riscv64.go
│ │ │ ├── syscall_solaris.go
│ │ │ ├── syscall_solaris_amd64.go
│ │ │ ├── syscall_unix.go
│ │ │ ├── syscall_unix_gc.go
│ │ │ ├── syscall_unix_gc_ppc64x.go
│ │ │ ├── syscall_zos_s390x.go
│ │ │ ├── sysvshm_linux.go
│ │ │ ├── sysvshm_unix.go
│ │ │ ├── sysvshm_unix_other.go
│ │ │ ├── timestruct.go
│ │ │ ├── types_aix.go
│ │ │ ├── types_darwin.go
│ │ │ ├── types_dragonfly.go
│ │ │ ├── types_freebsd.go
│ │ │ ├── types_netbsd.go
│ │ │ ├── types_openbsd.go
│ │ │ ├── types_solaris.go
│ │ │ ├── unveil_openbsd.go
│ │ │ ├── xattr_bsd.go
│ │ │ ├── zerrors_aix_ppc.go
│ │ │ ├── zerrors_aix_ppc64.go
│ │ │ ├── zerrors_darwin_amd64.go
│ │ │ ├── zerrors_darwin_arm64.go
│ │ │ ├── zerrors_dragonfly_amd64.go
│ │ │ ├── zerrors_freebsd_386.go
│ │ │ ├── zerrors_freebsd_amd64.go
│ │ │ ├── zerrors_freebsd_arm.go
│ │ │ ├── zerrors_freebsd_arm64.go
│ │ │ ├── zerrors_freebsd_riscv64.go
│ │ │ ├── zerrors_linux.go
│ │ │ ├── zerrors_linux_386.go
│ │ │ ├── zerrors_linux_amd64.go
│ │ │ ├── zerrors_linux_arm.go
│ │ │ ├── zerrors_linux_arm64.go
│ │ │ ├── zerrors_linux_loong64.go
│ │ │ ├── zerrors_linux_mips.go
│ │ │ ├── zerrors_linux_mips64.go
│ │ │ ├── zerrors_linux_mips64le.go
│ │ │ ├── zerrors_linux_mipsle.go
│ │ │ ├── zerrors_linux_ppc.go
│ │ │ ├── zerrors_linux_ppc64.go
│ │ │ ├── zerrors_linux_ppc64le.go
│ │ │ ├── zerrors_linux_riscv64.go
│ │ │ ├── zerrors_linux_s390x.go
│ │ │ ├── zerrors_linux_sparc64.go
│ │ │ ├── zerrors_netbsd_386.go
│ │ │ ├── zerrors_netbsd_amd64.go
│ │ │ ├── zerrors_netbsd_arm.go
│ │ │ ├── zerrors_netbsd_arm64.go
│ │ │ ├── zerrors_openbsd_386.go
│ │ │ ├── zerrors_openbsd_amd64.go
│ │ │ ├── zerrors_openbsd_arm.go
│ │ │ ├── zerrors_openbsd_arm64.go
│ │ │ ├── zerrors_openbsd_mips64.go
│ │ │ ├── zerrors_openbsd_ppc64.go
│ │ │ ├── zerrors_openbsd_riscv64.go
│ │ │ ├── zerrors_solaris_amd64.go
│ │ │ ├── zerrors_zos_s390x.go
│ │ │ ├── zptrace_armnn_linux.go
│ │ │ ├── zptrace_linux_arm64.go
│ │ │ ├── zptrace_mipsnn_linux.go
│ │ │ ├── zptrace_mipsnnle_linux.go
│ │ │ ├── zptrace_x86_linux.go
│ │ │ ├── zsyscall_aix_ppc.go
│ │ │ ├── zsyscall_aix_ppc64.go
│ │ │ ├── zsyscall_aix_ppc64_gc.go
│ │ │ ├── zsyscall_aix_ppc64_gccgo.go
│ │ │ ├── zsyscall_darwin_amd64.go
│ │ │ ├── zsyscall_darwin_amd64.s
│ │ │ ├── zsyscall_darwin_arm64.go
│ │ │ ├── zsyscall_darwin_arm64.s
│ │ │ ├── zsyscall_dragonfly_amd64.go
│ │ │ ├── zsyscall_freebsd_386.go
│ │ │ ├── zsyscall_freebsd_amd64.go
│ │ │ ├── zsyscall_freebsd_arm.go
│ │ │ ├── zsyscall_freebsd_arm64.go
│ │ │ ├── zsyscall_freebsd_riscv64.go
│ │ │ ├── zsyscall_illumos_amd64.go
│ │ │ ├── zsyscall_linux.go
│ │ │ ├── zsyscall_linux_386.go
│ │ │ ├── zsyscall_linux_amd64.go
│ │ │ ├── zsyscall_linux_arm.go
│ │ │ ├── zsyscall_linux_arm64.go
│ │ │ ├── zsyscall_linux_loong64.go
│ │ │ ├── zsyscall_linux_mips.go
│ │ │ ├── zsyscall_linux_mips64.go
│ │ │ ├── zsyscall_linux_mips64le.go
│ │ │ ├── zsyscall_linux_mipsle.go
│ │ │ ├── zsyscall_linux_ppc.go
│ │ │ ├── zsyscall_linux_ppc64.go
│ │ │ ├── zsyscall_linux_ppc64le.go
│ │ │ ├── zsyscall_linux_riscv64.go
│ │ │ ├── zsyscall_linux_s390x.go
│ │ │ ├── zsyscall_linux_sparc64.go
│ │ │ ├── zsyscall_netbsd_386.go
│ │ │ ├── zsyscall_netbsd_amd64.go
│ │ │ ├── zsyscall_netbsd_arm.go
│ │ │ ├── zsyscall_netbsd_arm64.go
│ │ │ ├── zsyscall_openbsd_386.go
│ │ │ ├── zsyscall_openbsd_386.s
│ │ │ ├── zsyscall_openbsd_amd64.go
│ │ │ ├── zsyscall_openbsd_amd64.s
│ │ │ ├── zsyscall_openbsd_arm.go
│ │ │ ├── zsyscall_openbsd_arm.s
│ │ │ ├── zsyscall_openbsd_arm64.go
│ │ │ ├── zsyscall_openbsd_arm64.s
│ │ │ ├── zsyscall_openbsd_mips64.go
│ │ │ ├── zsyscall_openbsd_mips64.s
│ │ │ ├── zsyscall_openbsd_ppc64.go
│ │ │ ├── zsyscall_openbsd_ppc64.s
│ │ │ ├── zsyscall_openbsd_riscv64.go
│ │ │ ├── zsyscall_openbsd_riscv64.s
│ │ │ ├── zsyscall_solaris_amd64.go
│ │ │ ├── zsyscall_zos_s390x.go
│ │ │ ├── zsysctl_openbsd_386.go
│ │ │ ├── zsysctl_openbsd_amd64.go
│ │ │ ├── zsysctl_openbsd_arm.go
│ │ │ ├── zsysctl_openbsd_arm64.go
│ │ │ ├── zsysctl_openbsd_mips64.go
│ │ │ ├── zsysctl_openbsd_ppc64.go
│ │ │ ├── zsysctl_openbsd_riscv64.go
│ │ │ ├── zsysnum_darwin_amd64.go
│ │ │ ├── zsysnum_darwin_arm64.go
│ │ │ ├── zsysnum_dragonfly_amd64.go
│ │ │ ├── zsysnum_freebsd_386.go
│ │ │ ├── zsysnum_freebsd_amd64.go
│ │ │ ├── zsysnum_freebsd_arm.go
│ │ │ ├── zsysnum_freebsd_arm64.go
│ │ │ ├── zsysnum_freebsd_riscv64.go
│ │ │ ├── zsysnum_linux_386.go
│ │ │ ├── zsysnum_linux_amd64.go
│ │ │ ├── zsysnum_linux_arm.go
│ │ │ ├── zsysnum_linux_arm64.go
│ │ │ ├── zsysnum_linux_loong64.go
│ │ │ ├── zsysnum_linux_mips.go
│ │ │ ├── zsysnum_linux_mips64.go
│ │ │ ├── zsysnum_linux_mips64le.go
│ │ │ ├── zsysnum_linux_mipsle.go
│ │ │ ├── zsysnum_linux_ppc.go
│ │ │ ├── zsysnum_linux_ppc64.go
│ │ │ ├── zsysnum_linux_ppc64le.go
│ │ │ ├── zsysnum_linux_riscv64.go
│ │ │ ├── zsysnum_linux_s390x.go
│ │ │ ├── zsysnum_linux_sparc64.go
│ │ │ ├── zsysnum_netbsd_386.go
│ │ │ ├── zsysnum_netbsd_amd64.go
│ │ │ ├── zsysnum_netbsd_arm.go
│ │ │ ├── zsysnum_netbsd_arm64.go
│ │ │ ├── zsysnum_openbsd_386.go
│ │ │ ├── zsysnum_openbsd_amd64.go
│ │ │ ├── zsysnum_openbsd_arm.go
│ │ │ ├── zsysnum_openbsd_arm64.go
│ │ │ ├── zsysnum_openbsd_mips64.go
│ │ │ ├── zsysnum_openbsd_ppc64.go
│ │ │ ├── zsysnum_openbsd_riscv64.go
│ │ │ ├── zsysnum_zos_s390x.go
│ │ │ ├── ztypes_aix_ppc.go
│ │ │ ├── ztypes_aix_ppc64.go
│ │ │ ├── ztypes_darwin_amd64.go
│ │ │ ├── ztypes_darwin_arm64.go
│ │ │ ├── ztypes_dragonfly_amd64.go
│ │ │ ├── ztypes_freebsd_386.go
│ │ │ ├── ztypes_freebsd_amd64.go
│ │ │ ├── ztypes_freebsd_arm.go
│ │ │ ├── ztypes_freebsd_arm64.go
│ │ │ ├── ztypes_freebsd_riscv64.go
│ │ │ ├── ztypes_linux.go
│ │ │ ├── ztypes_linux_386.go
│ │ │ ├── ztypes_linux_amd64.go
│ │ │ ├── ztypes_linux_arm.go
│ │ │ ├── ztypes_linux_arm64.go
│ │ │ ├── ztypes_linux_loong64.go
│ │ │ ├── ztypes_linux_mips.go
│ │ │ ├── ztypes_linux_mips64.go
│ │ │ ├── ztypes_linux_mips64le.go
│ │ │ ├── ztypes_linux_mipsle.go
│ │ │ ├── ztypes_linux_ppc.go
│ │ │ ├── ztypes_linux_ppc64.go
│ │ │ ├── ztypes_linux_ppc64le.go
│ │ │ ├── ztypes_linux_riscv64.go
│ │ │ ├── ztypes_linux_s390x.go
│ │ │ ├── ztypes_linux_sparc64.go
│ │ │ ├── ztypes_netbsd_386.go
│ │ │ ├── ztypes_netbsd_amd64.go
│ │ │ ├── ztypes_netbsd_arm.go
│ │ │ ├── ztypes_netbsd_arm64.go
│ │ │ ├── ztypes_openbsd_386.go
│ │ │ ├── ztypes_openbsd_amd64.go
│ │ │ ├── ztypes_openbsd_arm.go
│ │ │ ├── ztypes_openbsd_arm64.go
│ │ │ ├── ztypes_openbsd_mips64.go
│ │ │ ├── ztypes_openbsd_ppc64.go
│ │ │ ├── ztypes_openbsd_riscv64.go
│ │ │ ├── ztypes_solaris_amd64.go
│ │ │ └── ztypes_zos_s390x.go
│ │ ├── websocket/
│ │ │ ├── client.go
│ │ │ ├── dial.go
│ │ │ ├── hybi.go
│ │ │ ├── server.go
│ │ │ └── websocket.go
│ │ └── windows/
│ │ ├── aliases.go
│ │ ├── dll_windows.go
│ │ ├── empty.s
│ │ ├── env_windows.go
│ │ ├── eventlog.go
│ │ ├── exec_windows.go
│ │ ├── memory_windows.go
│ │ ├── mkerrors.bash
│ │ ├── mkknownfolderids.bash
│ │ ├── mksyscall.go
│ │ ├── mkwinsyscall/
│ │ │ └── mkwinsyscall.go
│ │ ├── race.go
│ │ ├── race0.go
│ │ ├── registry/
│ │ │ ├── key.go
│ │ │ ├── mksyscall.go
│ │ │ ├── syscall.go
│ │ │ ├── value.go
│ │ │ └── zsyscall_windows.go
│ │ ├── security_windows.go
│ │ ├── service.go
│ │ ├── setupapi_windows.go
│ │ ├── str.go
│ │ ├── svc/
│ │ │ ├── debug/
│ │ │ │ ├── log.go
│ │ │ │ └── service.go
│ │ │ ├── eventlog/
│ │ │ │ ├── install.go
│ │ │ │ └── log.go
│ │ │ ├── mgr/
│ │ │ │ ├── config.go
│ │ │ │ ├── mgr.go
│ │ │ │ ├── recovery.go
│ │ │ │ └── service.go
│ │ │ ├── security.go
│ │ │ └── service.go
│ │ ├── syscall.go
│ │ ├── syscall_windows.go
│ │ ├── types_windows.go
│ │ ├── types_windows_386.go
│ │ ├── types_windows_amd64.go
│ │ ├── types_windows_arm.go
│ │ ├── types_windows_arm64.go
│ │ ├── zerrors_windows.go
│ │ ├── zknownfolderids_windows.go
│ │ └── zsyscall_windows.go
│ ├── term/
│ │ ├── term.go
│ │ ├── term_plan9.go
│ │ ├── term_unix.go
│ │ ├── term_unix_bsd.go
│ │ ├── term_unix_other.go
│ │ ├── term_unsupported.go
│ │ ├── term_windows.go
│ │ └── terminal.go
│ ├── toml/
│ │ ├── README.md
│ │ ├── decode.go
│ │ ├── errors.go
│ │ ├── internal/
│ │ │ ├── characters/
│ │ │ │ ├── ascii.go
│ │ │ │ └── utf8.go
│ │ │ ├── cli/
│ │ │ │ └── cli.go
│ │ │ ├── danger/
│ │ │ │ ├── danger.go
│ │ │ │ └── typeid.go
│ │ │ ├── testsuite/
│ │ │ │ ├── add.go
│ │ │ │ ├── json.go
│ │ │ │ ├── parser.go
│ │ │ │ ├── rm.go
│ │ │ │ └── testsuite.go
│ │ │ └── tracker/
│ │ │ ├── key.go
│ │ │ ├── seen.go
│ │ │ └── tracker.go
│ │ ├── localtime.go
│ │ ├── marshaler.go
│ │ ├── strict.go
│ │ ├── types.go
│ │ ├── unmarshaler.go
│ │ └── unstable/
│ │ ├── ast.go
│ │ ├── builder.go
│ │ ├── doc.go
│ │ ├── kind.go
│ │ ├── parser.go
│ │ ├── scanner.go
│ │ └── unmarshaler.go
│ ├── webroot/
│ │ ├── assets/
│ │ │ ├── About-BpAaEtx1.js
│ │ │ ├── About-CLFeE-IU.css
│ │ │ ├── Manage-BTEK3ejV.css
│ │ │ ├── Manage-D_HsZWaT.js
│ │ │ ├── NotFound-Ts0Rt7lc.js
│ │ │ ├── SysInit-Lho0-Z3X.css
│ │ │ ├── SysInit-UcmoR0-x.js
│ │ │ ├── el-card-fwQOLwdi.css
│ │ │ ├── index-D6GWZ696.css
│ │ │ └── index-jH42E5tC.js
│ │ ├── index.html
│ │ └── readme.md
│ └── websocket/
│ ├── client.go
│ ├── compression.go
│ ├── conn.go
│ ├── doc.go
│ ├── join.go
│ ├── json.go
│ ├── mask.go
│ ├── mask_safe.go
│ ├── prepared.go
│ ├── proxy.go
│ ├── server.go
│ └── util.go
├── postman.json
├── sshd.dockerfile
└── webssh/
├── .gitignore
├── README.md
├── auto-imports.d.ts
├── components.d.ts
├── env.d.ts
├── index.html
├── package.json
├── src/
│ ├── App.vue
│ ├── components/
│ │ ├── Account.vue
│ │ ├── Connect.vue
│ │ ├── LoginAudit.vue
│ │ ├── NetFilter.vue
│ │ ├── SshdCert.vue
│ │ └── SshdUser.vue
│ ├── main.ts
│ ├── router/
│ │ └── index.ts
│ ├── stores/
│ │ └── store.ts
│ └── views/
│ ├── About.vue
│ ├── Empty.vue
│ ├── Home.vue
│ ├── Login.vue
│ ├── Manage.vue
│ ├── NotFound.vue
│ └── SysInit.vue
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/build-and-release.yml
================================================
name: Build & Release
on:
push:
tags:
- 'v*'
jobs:
build-release:
runs-on: ubuntu-latest
name: Build and Release for Multiple OS & Arch
permissions:
contents: write
strategy:
matrix:
include:
# Windows targets (64-bit only)
- os: windows
goos: windows
arch: amd64
suffix: .exe
- os: windows
goos: windows
arch: arm64
suffix: .exe
# Linux targets (64-bit architectures)
- os: linux
goos: linux
arch: amd64
suffix: ''
- os: linux
goos: linux
arch: arm64
suffix: ''
# macOS targets (64-bit only)
- os: macos
goos: darwin
arch: amd64
suffix: ''
- os: macos
goos: darwin
arch: arm64
suffix: ''
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.24.5'
- name: Prepare workspace
run: |
echo "📂 Workspace structure:"
ls -la
echo "📂 gossh directory content:"
ls -la gossh
# 确保目录存在
if [ ! -d "gossh" ]; then
echo "❌ Error: gossh directory not found!"
exit 1
fi
# 进入gossh目录准备构建
cd gossh
# 更新依赖
go mod tidy
go mod download
- name: Build for ${{ matrix.os }} (${{ matrix.arch }})
run: |
cd gossh
# 静态编译
CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.arch }} \
go build -trimpath -ldflags="-s -w" -o GoWebSSH${{ matrix.suffix }}
# 验证构建结果
if [ -f "GoWebSSH${{ matrix.suffix }}" ]; then
echo "✅ Build successful! Output file: GoWebSSH${{ matrix.suffix }}"
else
echo "❌ Build failed! No output file found in: $(pwd)"
ls -la
exit 1
fi
# 创建压缩包(在仓库根目录)
zip -j ../GoWebSSH-${{ matrix.os }}-${{ matrix.arch }}.zip GoWebSSH${{ matrix.suffix }}
- name: Create Release and Upload Assets
uses: softprops/action-gh-release@v2
with:
name: ${{ github.ref_name }}
tag_name: ${{ github.ref_name }}
files: |
GoWebSSH-*.zip
================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
######################
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
######################
# ide #
######################
.idea
*.iml
/gossh/go.sum
/gossh/gossh
/gossh/GoWebSSH.db
================================================
FILE: Dockerfile
================================================
# 第一阶段:构建
FROM golang:1.23.4 AS builder
WORKDIR /mnt
COPY gossh ./gossh
RUN cd /mnt/gossh && CGO_ENABLED=0 go build -o /mnt/gowebssh
# 第二阶段:运行
FROM alpine:3.21.0
WORKDIR /root/
VOLUME /var/lib/webssh
EXPOSE 8899
COPY --from=builder /mnt/gowebssh /bin/gowebssh
CMD ["/bin/gowebssh", "-WorkDir", "/var/lib/webssh"]
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 o8oo8o
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.
================================================
FILE: README.md
================================================
## GoWebSSH
<br/>
### 项目介绍:
* **Web版ssh客户端 + (sshd,sftp)服务端实现**
<br/>
### 概要:
* Golang 1.23 + (Vue3.5 + Vite6) 实现一个Web版单文件的(SSH+SSHD)
* 借助于Golang embed,打包以后只有一个文件,简单高效
* 使用及编译过程,超级简单,绝对保姆级
* 上一版主要本地运行,但是通过部分用户反馈,此项目定位改为服务器运行,所以此版本加入了很多企业场景中的功能
<br/>
### 联系我:
* **QQ:774309635**
<br/>
---
### Quick start(大象装进冰箱只需3步):
> 必须使用golang 1.21以上版本
* git clone https://github.com/o8oo8o/WebSSH.git
* cd WebSSH/gossh
* go build
* ./gossh
> 打开链接 http://127.0.0.1:8899/ 开始享用吧,第一次需要初始化
<br/>
### Docker 方式:
* git clone https://github.com/o8oo8o/WebSSH.git
* cd WebSSH
* docker build -f Dockerfile -t gowebssh:v2 .
* docker run -d --name webssh -p 8899:8899 -v gowebssh:/var/lib/webssh gowebssh:v2
<br/>
### 打赏我:
* **每一个开源项目的背后,都有一群默默付出、充满激情的开发者。他们用自己的业余时间,不断地优化代码、修复bug、撰写文档,只为让项目变得更好。如果您觉得我的项目对您有所帮助,如果您认可我的努力和付出,那么请考虑给予我一点小小的打赏,够买一瓶啤酒就行🍺,如果能同时打赏啤酒花生那更好🍺🥜,因为所有的代码都是喝完酒撸的。放上收款码的时候我是羞愧的,一个中年男人的最后的尊严和节操竟然没了😂,友情提示:打赏不退,怕被媳妇查到大额支出🥸,如果需要技术支持,需要收费哦**
<br/>
<br/>

<br/>
### 运行环境依赖:
* 需要MySQL8+及PostgreSQL12.2+或者直接使用内置SQLite数据库
### SSHD服务器功能:
* 可以配置只监听本地端口
* 支持Web配置sshd服务器账号密码及公钥
* 支持密码认证,公钥认证,增强登录过程的安全性
* 通过SFTP或SCP用户可以安全地在本地和远程服务器之间传输文件
<br/>
### Web客户端主要功能:
* 支持同时连接多个主机,支持重连、清屏功能
* 支持IPv4、IPv6
* 支持SSH证书登陆及证书密码
* 支持批量支持命令,当前终端及所有终端
* 支持命令收藏,方便重复执行命令,批量发送命令到所有会话
* 可以保存主机连接信息
* 支持直接通过Web上传下载文件
* 支持直接通过Web创建目录,删除文件及目录功能
* 支持手动输入路径
* 支持自定义终端字体大小、字体颜色、字体样式
* 支持自定义背景、光标颜色及光标样式
* 已保存的主机信息可直接编辑并连接
* 支持后台管理,强制断开连接
* 支持登陆日志审计,方便监控违规操作
* 支持访问控制,在公网场景中有效拦截非法访问
<br/>
### 为什么这么简单:
* 为了方便您使用,把golang编译的依赖已经整理好了,clone就一起下载了
* 前端已经编译完成,并把编译完成的静态资源拷贝到gossh/webroot目录中
* 可执行文件内嵌静态资源,方便你随性所欲的移动可执行文件
* 因内置sshd服务器,在受限的网络环境依然能通过web访问
<br/>
### 配置文件:
* 第一次运行会在用户home目录创建一个 .GoWebSSH 目录
* GoWebSSH.toml 可以配置server端口等信息
* cert.pem HTTPS服务器证书文件
* key.key HTTPS服务器私钥文件
<br/>
### 注意:
* 当程序检测到cert.pem 和 key.key 文件,会使用https协议,否则使用http协议
* 用户只需把证书文件和私钥文件放到 .GoWebSSH 目录就可以了
```shell
openssl genpkey -algorithm RSA -out key.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -x509 -key key.key -out cert.pem -days 365 -subj "/C=CN/ST=bj/L=bj/O=gowebssh/OU=gowebssh/CN=gowebssh.com"
```
<br/>
### Systemd 方式启动:
```shell
cat > /etc/systemd/system/gowebssh.service << "END"
##################################
[Unit]
Description=GoWebSSH Daemon
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=root
Environment=TERM=xterm
Environment=XDG_SESSION_TYPE=tty
Environment=HOME=/root
PrivateTmp=true
LimitNOFILE=65535
# 执行程序路径
ExecStart=/usr/local/gossh
# auto restart
StartLimitIntervalSec=0
Restart=always
RestartSec=1
[Install]
WantedBy=multi-user.target
##################################
END
systemctl daemon-reload
systemctl start gowebssh.service
systemctl enable gowebssh.service
```
<br/>
---
### 演示截图:






================================================
FILE: gossh/Makefile
================================================
.PHONY: clean all
all: linux-amd64 linux-arm64 macos-amd64 macos-arm64 windows-amd64
linux-amd64:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o WebSSH-linux-amd64
linux-arm64:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o WebSSH-linux-arm64
macos-amd64:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o WebSSH-macos-amd64
macos-arm64:
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o WebSSH-macos-arm64
windows-amd64:
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o WebSSH-windows-amd64.exe
WebSSH:
go build -o WebSSH
clean:
rm -f WebSSH-linux-amd64 WebSSH-linux-arm64 WebSSH-macos-amd64 WebSSH-macos-arm64 WebSSH-windows-amd64.exe
================================================
FILE: gossh/app/config/config.go
================================================
package config
import (
"flag"
"gossh/app/utils"
"gossh/toml"
"log/slog"
"os"
"path"
"time"
)
type AppConfig struct {
WebBaseDir string `json:"web_base_dir" toml:"web_base_dir"`
AppName string `json:"app_name" toml:"app_name"`
DbType string `json:"db_type" toml:"db_type"`
DbDsn string `json:"db_dsn" toml:"db_dsn"`
IsInit bool `json:"is_init" toml:"is_init"`
JwtSecret string `json:"jwt_secret" toml:"jwt_secret"`
AesSecret string `json:"aes_secret" toml:"aes_secret"`
JwtExpire time.Duration `json:"jwt_expire" toml:"jwt_expire"`
StatusRefresh time.Duration `json:"status_refresh" toml:"status_refresh"`
ClientCheck time.Duration `json:"client_check" toml:"client_check"`
SessionSecret string `json:"session_secret" toml:"session_secret"`
Address string `json:"address" toml:"address"`
Port string `json:"port" toml:"port"`
CertFile string `json:"cert_file" toml:"cert_file"`
KeyFile string `json:"key_file" toml:"key_file"`
}
func (c *AppConfig) write() error {
data, err := toml.Marshal(c)
if err != nil {
slog.Error("序列化TOML配置文件错误:", "err_msg", err)
return err
}
err = os.WriteFile(confFileFullPath, data, os.FileMode(0777))
if err != nil {
slog.Error("写入默认配置文件错误:", "err_msg", err.Error())
return err
}
return nil
}
var DefaultConfig = AppConfig{
WebBaseDir: "",
AppName: "GoWebSHH",
DbType: "mysql",
DbDsn: "",
IsInit: false,
JwtSecret: utils.RandString(64),
AesSecret: utils.RandString(32),
SessionSecret: utils.RandString(64),
JwtExpire: time.Minute * 120,
StatusRefresh: time.Second * 3,
ClientCheck: time.Second * 15,
Address: "",
Port: "8899",
CertFile: path.Join(WorkDir, "cert.pem"),
KeyFile: path.Join(WorkDir, "key.key"),
}
var UserHomeDir, _ = os.UserHomeDir()
var projectName = "GoWebSSH"
var confFileName = "GoWebSSH.toml"
var confPath = string(os.PathSeparator) + "." + projectName + string(os.PathSeparator)
// WorkDir 程序默认工作目录,在用户的home目录下 .GoWebSSH 目录
var WorkDir = path.Join(UserHomeDir, confPath)
var confFileFullPath = path.Join(WorkDir, confFileName)
func InitConfig() {
defer func() {
if err := recover(); err != nil {
slog.Error("init config failed", "err_msg", err)
os.Exit(255)
}
}()
var configDir string
var webBaseDir string
flag.StringVar(&configDir, "ConfigDir", "", "ConfigDir")
flag.StringVar(&webBaseDir, "WebBaseDir", "", "WebBaseDir")
flag.Parse()
DefaultConfig.WebBaseDir = configDir
if configDir != "" {
WorkDir = path.Join(configDir, confPath)
confFileFullPath = path.Join(WorkDir, confFileName)
DefaultConfig.CertFile = path.Join(WorkDir, "cert.pem")
DefaultConfig.KeyFile = path.Join(WorkDir, "key.key")
}
slog.Info("use-config-file", "path", confFileFullPath)
info, err := os.Stat(WorkDir)
if os.IsNotExist(err) {
err := os.MkdirAll(WorkDir, os.FileMode(0755))
if err != nil {
slog.Error("创建工作目录失败")
return
}
}
info, err = os.Stat(WorkDir)
if !info.IsDir() {
slog.Error("有一个和工作目录同名的目录", "dir", WorkDir)
return
}
_, err = os.Stat(confFileFullPath)
if os.IsNotExist(err) {
if err := DefaultConfig.write(); err != nil {
return
}
}
data, err := os.ReadFile(confFileFullPath)
if err != nil {
slog.Error("读取配置文件错误:", "err_msg", err.Error())
return
}
err = toml.Unmarshal(data, &DefaultConfig)
if err != nil {
slog.Error("TOML解析配置文件错误:", "err_msg", err.Error())
return
}
// 修正webBaseDir
if DefaultConfig.WebBaseDir != webBaseDir {
DefaultConfig.WebBaseDir = webBaseDir
if err := DefaultConfig.write(); err != nil {
return
}
}
slog.Debug("DefaultConfig:", "data", DefaultConfig)
}
func RewriteConfig(conf AppConfig) error {
data, err := toml.Marshal(conf)
if err != nil {
slog.Error("序列化TOML配置文件错误:", "err_msg", err)
return err
}
// 覆盖全局变量
DefaultConfig = conf
err = os.Remove(confFileFullPath)
if err != nil {
slog.Error("删除旧配置文件错误:", "err_msg", err.Error())
return err
}
err = os.WriteFile(confFileFullPath, data, os.FileMode(0777))
if err != nil {
slog.Error("写入默认配置文件错误:", "err_msg", err.Error())
return err
}
return nil
}
================================================
FILE: gossh/app/middleware/db_check.go
================================================
package middleware
import (
"gossh/app/config"
"gossh/app/model"
"gossh/gin"
)
func DbCheck() gin.HandlerFunc {
return func(c *gin.Context) {
if !config.DefaultConfig.IsInit {
c.Next()
return
}
if model.Db != nil {
tx := model.Db.Exec("select 1=1")
if tx.Error == nil {
c.Next()
} else {
err := model.DbMigrate(config.DefaultConfig.DbType, config.DefaultConfig.DbDsn)
if err != nil {
c.Abort()
c.JSON(500, gin.H{"code": 500, "msg": "数据库连接错误:" + err.Error()})
return
}
}
}
c.Next()
}
}
================================================
FILE: gossh/app/middleware/jwt_auth.go
================================================
package middleware
import (
"errors"
"gossh/app/config"
"gossh/gin"
"gossh/gin/jwt"
"strings"
"time"
)
// JwtSecret 生成JWT签名的密钥
var JwtSecret = []byte(config.DefaultConfig.JwtSecret)
type JwtClaims struct {
// 用户Id
Id uint
// 标准Claims结构体,可设置8个标准字段
jwt.RegisteredClaims
}
// GenerateToken 登录成功后调用,传入SshUser结构体
func GenerateToken(id uint) (string, error) {
// 两个小时有效期
expirationTime := time.Now().Add(config.DefaultConfig.JwtExpire)
claims := &JwtClaims{
Id: id,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(expirationTime),
Issuer: "go_web_ssh",
},
}
// 生成Token,指定签名算法和claims
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// 签名
tokenString, err := token.SignedString(JwtSecret)
if err != nil {
return "", err
}
return tokenString, nil
}
func ParseToken(tokenString string) (*JwtClaims, error) {
claims := &JwtClaims{}
_, err := jwt.ParseWithClaims(tokenString, claims, func(t *jwt.Token) (any, error) {
return JwtSecret, nil
})
// 若token只是过期claims是有数据的,若token无法解析claims无数据
return claims, err
}
func RenewToken(claims *JwtClaims) (string, error) {
// 若token过期不超过10分钟则给它续签
if withinLimit(claims.ExpiresAt.Time.Unix(), 600) {
return GenerateToken(claims.Id)
}
return "", errors.New("登录已过期")
}
// 计算过期时间是否超过l
func withinLimit(s, l int64) bool {
return time.Now().Unix()-s < l
}
func JWTAuth() gin.HandlerFunc {
return func(c *gin.Context) {
auth := c.Request.Header.Get("Authorization")
if len(auth) == 0 {
// Websocket SSE 从请求参数取
auth = c.Query("Authorization")
}
if len(auth) == 0 {
// 无token直接拒绝
c.Abort()
c.JSON(401, gin.H{"code": 401, "msg": "请添加Authorization请求头"})
return
}
// 校验token
claims, err := ParseToken(auth)
if err != nil {
if strings.Contains(err.Error(), "token is expired") {
// 若过期,调用续签函数
newToken, _ := RenewToken(claims)
if newToken != "" {
// 续签成功返回头设置一个NewToken字段
c.Header("NewToken", newToken)
//c.Request.Header.Set("Authorization", newToken)
c.Set("uid", claims.Id)
c.Next()
return
}
}
// Token验证失败或续签失败直接拒绝请求
c.Abort()
c.JSON(401, gin.H{"code": 401, "msg": "未登录"})
return
}
c.Set("uid", claims.Id)
// token未过期继续执行其他中间件
c.Next()
}
}
================================================
FILE: gossh/app/middleware/net_filter.go
================================================
package middleware
import (
"fmt"
"gossh/app/config"
"gossh/app/model"
"gossh/gin"
"log/slog"
"net"
)
func check(ip net.IP) bool {
var policyConf model.PolicyConf
conf, err := policyConf.FindByID(1)
if err != nil {
slog.Error("get policyConf:", "err_msg", err.Error())
return false
}
// 白名单检查
if conf.NetPolicy == "Y" {
// slog.Info("netFilterPolicy", "value", "Y")
var filter model.NetFilter
list, err := filter.FindAllPolicy("Y")
if err != nil {
slog.Error("FindAllPolicy:", "err_msg", err.Error())
}
isOK := false
for _, item := range list {
_, ipNet, err := net.ParseCIDR(item.Cidr)
if err != nil {
slog.Error("net.ParseCIDR:", "err_msg", err.Error())
return false
}
if ipNet.Contains(ip) {
isOK = true
break
}
}
return isOK
}
// 黑名单检查
if conf.NetPolicy == "N" {
// slog.Info("netFilterPolicy", "value", "N")
var filter model.NetFilter
list, err := filter.FindAllPolicy("N")
if err != nil {
slog.Error("FindAllPolicy:", "err_msg", err.Error())
}
isOK := true
for _, item := range list {
_, ipNet, err := net.ParseCIDR(item.Cidr)
if err != nil {
slog.Error("net.ParseCIDR:", "err_msg", err.Error())
return false
}
if ipNet.Contains(ip) {
isOK = false
break
}
}
return isOK
}
return false
}
func NetFilter() gin.HandlerFunc {
return func(c *gin.Context) {
// 系统没有进行初始化,过滤功能不生效
if !config.DefaultConfig.IsInit {
c.Next()
return
}
ip := net.ParseIP(c.RemoteIP())
if !check(ip) {
c.JSON(403, gin.H{"err_msg": fmt.Sprintf("Deny %s", ip.String())})
c.Abort()
return
}
c.Next()
}
}
================================================
FILE: gossh/app/middleware/perm_check.go
================================================
package middleware
import (
"fmt"
"gossh/app/config"
"gossh/app/model"
"gossh/gin"
"slices"
"strings"
)
var checkRoute = []string{
// "GET:/app/*filepath",
// "GET:/web_base_dir",
// "HEAD:/app/*filepath",
// "GET:/api/ssh/conn",
// "PATCH:/api/ssh/conn",
// "POST:/api/ssh/exec",
// "POST:/api/ssh/disconnect",
// "POST:/api/ssh/create_session",
// "GET:/api/conn_conf",
// "GET:/api/conn_conf/:id",
// "POST:/api/conn_conf",
// "PUT:/api/conn_conf",
// "DELETE:/api/conn_conf/:id",
// "GET:/api/cmd_note",
// "GET:/api/cmd_note/:id",
// "POST:/api/cmd_note",
// "PUT:/api/cmd_note",
// "DELETE:/api/cmd_note/:id",
// "GET:/api/sftp/download",
// "POST:/api/sftp/create_dir",
// "POST:/api/sftp/list",
// "DELETE:/api/sftp/delete",
// "PUT:/api/sftp/upload",
// "PUT:/api/conn_manage/refresh_conn_time",
// "POST:/api/login",
// "PATCH:/api/user/pwd",
"GET:/api/sshd_cert",
"GET:/api/sshd_cert_text",
"GET:/api/sshd_cert/:id",
"GET:/api/sshd_user",
"GET:/api/sshd_user/:id",
"GET:/api/sys/is_init",
"GET:/api/sys/config",
"GET:/api/conn_manage/online_client",
"GET:/api/policy_conf",
"GET:/api/policy_conf/:id",
"GET:/api/net_filter",
"GET:/api/net_filter/:id",
"GET:/api/user",
"GET:/api/user/:id",
"POST:/api/sshd_user",
"POST:/api/sshd_cert",
"POST:/api/sys/db_conn_check",
"POST:/api/sys/init",
"POST:/api/sys/config",
"POST:/api/login_audit",
"POST:/api/policy_conf",
"POST:/api/net_filter",
"POST:/api/user",
"PUT:/api/sshd_user",
"PUT:/api/sshd_cert",
"PUT:/api/policy_conf",
"PUT:/api/net_filter",
"PUT:/api/user",
"DELETE:/api/sshd_user/:id",
"DELETE:/api/sshd_cert/:id",
"DELETE:/api/policy_conf/:id",
"DELETE:/api/net_filter/:id",
"DELETE:/api/user/:id",
"PATCH:/api/sshd_user/check_name_exists",
"PATCH:/api/sshd_cert/check_name_exists",
"PATCH:/api/user/check_name_exists",
}
func PremCheck(engine *gin.Engine) gin.HandlerFunc {
return func(c *gin.Context) {
/*
for _, route := range engine.Routes() {
path := route.Path
method := route.Method
fmt.Printf("Route==>: %s:%s\n", method, path)
}
*/
var tmp = c.FullPath()
var baseDir = strings.Trim(config.DefaultConfig.WebBaseDir, " ")
if baseDir != "" && strings.HasPrefix(tmp, baseDir) {
tmp = strings.TrimPrefix(tmp, baseDir)
}
full := fmt.Sprintf("%s:%s", c.Request.Method, tmp)
// slog.Info("PermCheck", "base", baseDir, "path", full)
if slices.Contains(checkRoute, full) {
var wu model.WebUser
u, err := wu.FindByID(c.GetUint("uid"))
if err != nil || u.IsAdmin == "N" {
c.JSON(200, gin.H{"code": 403, "msg": "权限检查失败,非管理员拒绝操作"})
c.Abort()
return
}
}
c.Next()
}
}
================================================
FILE: gossh/app/middleware/sys_init.go
================================================
package middleware
import (
"gossh/app/config"
"gossh/gin"
)
func SysInit() gin.HandlerFunc {
return func(c *gin.Context) {
if !config.DefaultConfig.IsInit {
// 需要进行系统初始化
c.Abort()
c.JSON(401, gin.H{"code": 401, "msg": "请对系统进行初始化"})
return
}
c.Next()
}
}
================================================
FILE: gossh/app/model/cmd_note.go
================================================
package model
type CmdNote struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
Uid uint `gorm:"column:uid;not null;default:0" form:"uid" json:"uid"`
CmdName string `gorm:"column:cmd_name;type:text" form:"cmd_name" binding:"required" json:"cmd_name"`
CmdData string `gorm:"column:cmd_data;type:text" form:"cmd_data" binding:"required" json:"cmd_data"`
CreatedAt DateTime `gorm:"created_at" json:"-"`
UpdatedAt DateTime `gorm:"updated_at" json:"-"`
}
func (c CmdNote) Create(cmd *CmdNote) error {
return Db.Create(cmd).Error
}
func (c CmdNote) FindByName(name string) (CmdNote, error) {
var cmd CmdNote
err := Db.First(&cmd, "name = ?", name).Error
return cmd, err
}
func (c CmdNote) FindByID(id uint, uid uint) (CmdNote, error) {
var cmd CmdNote
err := Db.First(&cmd, "id = ? AND uid = ?", id, uid).Error
return cmd, err
}
func (c CmdNote) FindAll(offset, limit int, uid uint) ([]CmdNote, error) {
var list []CmdNote
err := Db.Where("uid = ?", uid).Offset(offset).Limit(limit).Order("updated_at desc").Find(&list).Error
return list, err
}
func (c CmdNote) UpdateById(id, uid uint, cmd *CmdNote) error {
return Db.Model(&c).Where("id = ? AND uid = ?", id, uid).Updates(cmd).Error
}
func (c CmdNote) DeleteByID(id, uid uint) error {
return Db.Unscoped().Delete(&c, "id = ? AND uid = ?", id, uid).Error
}
================================================
FILE: gossh/app/model/datetime.go
================================================
package model
import (
"database/sql/driver"
"fmt"
"time"
)
const (
TimeFormat = "2006-01-02 15:04:05"
)
type DateTime time.Time
func NewDateTime(str string) (DateTime, error) {
now, err := time.ParseInLocation(TimeFormat, str, time.Local)
if err != nil {
return DateTime{}, fmt.Errorf("can not convert %v to date,must like format:yyyy-MM-dd HH:mm:ss,simple example : %v", str, TimeFormat)
}
t := DateTime(now)
return t, nil
}
func (t DateTime) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, time.Time(t).Format(TimeFormat))), nil
}
func (t *DateTime) UnmarshalJSON(b []byte) error {
now, err := time.ParseInLocation(`"`+TimeFormat+`"`, string(b), time.Local)
if err != nil {
return fmt.Errorf("can not convert %v to date,must like format:yyyy-MM-dd HH:mm:ss,simple example : %v", string(b), TimeFormat)
}
*t = DateTime(now)
return nil
}
func (t DateTime) Value() (driver.Value, error) {
var zeroTime time.Time
if time.Time(t).UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return time.Time(t), nil
}
func (t *DateTime) Scan(v any) error {
value, ok := v.(time.Time)
if ok {
*t = DateTime(value)
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
func (t *DateTime) ToTime() time.Time {
return time.Time(*t)
}
func (t DateTime) String() string {
return time.Time(t).Format(TimeFormat)
}
================================================
FILE: gossh/app/model/db_init.go
================================================
package model
import (
"errors"
"fmt"
"gossh/app/config"
"gossh/gorm"
"gossh/gorm/driver/mysql"
"gossh/gorm/driver/pgsql"
"gossh/gorm/logger"
_ "gossh/mysql"
_ "gossh/pgsql"
"gossh/sqlite"
"log/slog"
"os"
"path"
"path/filepath"
)
var Db *gorm.DB
func InitDatabase() {
if !config.DefaultConfig.IsInit {
slog.Warn("系统未初始化,跳过DbMigrate")
return
}
err := DbMigrate(config.DefaultConfig.DbType, config.DefaultConfig.DbDsn)
if err != nil {
slog.Error("DbMigrate error", "err_msg", err.Error())
}
}
func GetSqliteDb(dsn string) (*gorm.DB, error) {
//loadInit()
dbPath := path.Join(config.WorkDir, dsn)
// 确保数据库目录存在
if err := os.MkdirAll(filepath.Dir(dbPath), 0755); err != nil {
return nil, fmt.Errorf("failed to create database directory: %v", err)
}
// 尝试打开数据库连接
db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{
Logger: logger.Default.LogMode(logger.Warn),
})
if err != nil {
return nil, fmt.Errorf("failed to connect to database: %v", err)
}
// 验证连接
sqlDB, err := db.DB()
if err != nil {
return nil, fmt.Errorf("failed to get database instance: %v", err)
}
if err := sqlDB.Ping(); err != nil {
return nil, fmt.Errorf("failed to ping database: %v", err)
}
return db, nil
}
func DbMigrate(dbType, dsn string) error {
defer func() {
if err := recover(); err != nil {
slog.Error("DbMigrate error", "err_msg", err)
}
}()
if dbType == "pgsql" {
db, err := gorm.Open(pgsql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Warn),
})
if err != nil {
return err
}
err = db.Exec("select 1=1;").Error
if err != nil {
return err
}
Db = db
}
if dbType == "mysql" {
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Warn),
})
if err != nil {
return err
}
err = db.Exec("select 1=1;").Error
if err != nil {
return err
}
Db = db
}
if dbType == "sqlite" {
db, err := GetSqliteDb(dsn)
if err != nil {
return err
}
Db = db
}
if Db == nil {
return errors.New("请检查数据库链接")
}
err := Db.AutoMigrate(
SshConf{}, WebUser{}, CmdNote{},
NetFilter{}, PolicyConf{}, LoginAudit{},
SshdConf{}, SshdUser{}, SshdCert{})
if err != nil {
slog.Error("AutoMigrate error:", "err_msg", err.Error())
return err
}
return nil
}
================================================
FILE: gossh/app/model/login_audit.go
================================================
package model
type LoginAudit struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
Name string `gorm:"column:name;not null;size:128" form:"name" binding:"required,min=1,max=128" json:"name"`
Pwd string `gorm:"column:pwd;size:128" form:"pwd" binding:"required,min=1,max=128" json:"pwd"`
ClientIp string `gorm:"column:client_ip;size:128" form:"client_ip" binding:"required,min=1,max=128" json:"client_ip"`
UserAgent string `gorm:"column:user_agent;size:512" form:"user_agent" binding:"required,min=0,max=512" json:"user_agent"`
ErrMsg string `gorm:"column:err_msg;size:64" form:"err_msg" binding:"required,min=1,max=64" json:"err_msg"`
IsSuccess string `gorm:"column:is_success;not null;size:64;default:'N'" form:"is_success" binding:"required,min=1,max=64,oneof=Y N" json:"is_success"`
OccurAt DateTime `gorm:"column:occur_at;not null" json:"occur_at" form:"occur_at" binding:"required"`
CreatedAt DateTime `gorm:"column:created_at" json:"-"`
UpdatedAt DateTime `gorm:"column:updated_at" json:"-"`
}
func (c LoginAudit) Create(audit *LoginAudit) error {
return Db.Create(audit).Error
}
func (c LoginAudit) Search(
isSuccess, name, clientIp string,
occurBegin, occurEnd DateTime, offset, limit int,
) ([]LoginAudit, int64, error) {
var list []LoginAudit
var db = Db
if isSuccess != "" {
db = db.Where("is_success = ?", isSuccess)
}
if name != "" {
db = db.Where("name like ?", "%"+name+"%")
}
if clientIp != "" {
db = db.Where("client_ip = ?", clientIp)
}
if occurBegin.String() != "0001-01-01 00:00:00" && occurEnd.String() != "0001-01-01 00:00:00" {
db = db.Where("occur_at between ? AND ?", occurBegin, occurEnd)
}
var count int64
err := db.Model(&LoginAudit{}).Count(&count).Error
if err != nil {
return list, count, err
}
return list, count, db.Debug().Order("occur_at desc").Offset(offset).Limit(limit).Find(&list).Error
}
func (c LoginAudit) FindByID(id uint) (LoginAudit, error) {
var audit LoginAudit
err := Db.First(&audit, "id = ?", id).Error
return audit, err
}
func (c LoginAudit) DeleteByID(id uint) error {
return Db.Unscoped().Delete(&c, "id = ? AND is_root = ?", id, "N").Error
}
================================================
FILE: gossh/app/model/net_filter.go
================================================
package model
import "time"
type NetFilter struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
Name string `gorm:"column:name;not null" form:"name" json:"name" binding:"required"`
Cidr string `gorm:"column:cidr;not null" form:"cidr" json:"cidr" binding:"required,cidr"`
NetPolicy string `gorm:"column:net_policy;not null;size:64;default:'Y'" form:"net_policy" binding:"required,min=1,max=64,oneof=Y N" json:"net_policy"`
PolicyNo uint `gorm:"column:policy_no;not null;" form:"policy_no" json:"policy_no" binding:"required,gte=1,lte=65535"`
ExpiryAt DateTime `gorm:"column:expiry_at;not null" json:"expiry_at" form:"expiry_at" binding:"required"`
CreatedAt DateTime `gorm:"column:created_at" json:"-"`
UpdatedAt DateTime `gorm:"column:updated_at" json:"-"`
}
func (c NetFilter) Create(filter *NetFilter) error {
return Db.Create(filter).Error
}
func (c NetFilter) FindByName(name string) (NetFilter, error) {
var filter NetFilter
err := Db.First(&filter, "name = ?", name).Error
return filter, err
}
func (c NetFilter) FindByID(id uint) (NetFilter, error) {
var filter NetFilter
err := Db.First(&filter, "id = ? ", id).Error
return filter, err
}
func (c NetFilter) FindAll(offset, limit int) ([]NetFilter, error) {
var list []NetFilter
err := Db.Offset(offset).Limit(limit).Order("policy_no asc, expiry_at, updated_at desc").Find(&list).Error
return list, err
}
func (c NetFilter) FindAllPolicy(policy string) ([]NetFilter, error) {
var list []NetFilter
err := Db.Where("net_policy = ? AND expiry_at > ?", policy, time.Now()).Order("policy_no asc, expiry_at, updated_at desc").Find(&list).Error
return list, err
}
func (c NetFilter) UpdateById(id uint, filter *NetFilter) error {
return Db.Model(&c).Where("id = ?", id).Updates(filter).Error
}
func (c NetFilter) DeleteByID(id uint) error {
return Db.Unscoped().Delete(&c, "id = ?", id).Error
}
================================================
FILE: gossh/app/model/policy_conf.go
================================================
package model
type PolicyConf struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
NetPolicy string `gorm:"column:net_policy;not null;size:64;default:'Y'" form:"net_policy" binding:"required,min=1,max=64,oneof=Y N" json:"net_policy"`
CreatedAt DateTime `gorm:"column:created_at" json:"-"`
UpdatedAt DateTime `gorm:"column:updated_at" json:"-"`
}
func (c PolicyConf) Create(conf *PolicyConf) error {
return Db.Create(conf).Error
}
func (c PolicyConf) FindByID(id uint) (PolicyConf, error) {
var conf PolicyConf
err := Db.First(&conf, "id = ? ", id).Error
return conf, err
}
func (c PolicyConf) FindAll(offset, limit int) ([]PolicyConf, error) {
var list []PolicyConf
err := Db.Offset(offset).Limit(limit).Order("updated_at desc").Find(&list).Error
return list, err
}
func (c PolicyConf) UpdateById(id uint, conf *PolicyConf) error {
return Db.Model(&c).Where("id = ?", id).Updates(conf).Error
}
func (c PolicyConf) DeleteByID(id uint) error {
return Db.Unscoped().Delete(&c, "id = ?", id).Error
}
================================================
FILE: gossh/app/model/ssh_conf.go
================================================
package model
import (
"errors"
"gossh/app/config"
"gossh/app/utils"
"gossh/gorm"
)
type SshConf struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
Uid uint `gorm:"column:uid;not null;default:0" form:"uid" json:"uid"`
Name string `gorm:"column:name;not null;size:64" form:"name" binding:"required,min=1,max=63" json:"name"`
Address string `gorm:"column:address;size:128" form:"address" binding:"required,min=1,max=128" json:"address"`
User string `gorm:"column:user;size:128" form:"user" binding:"required,min=1,max=128" json:"user"`
Pwd string `gorm:"column:pwd;not null;size:4096;default:''" form:"pwd" binding:"max=4096" json:"pwd"`
AuthType string `gorm:"column:auth_type;not null;size:32;default:'pwd'" form:"auth_type" binding:"required,min=1,max=32,oneof=pwd cert" json:"auth_type"`
NetType string `gorm:"column:net_type;not null;size:32;default:'tcp4'" form:"net_type" binding:"required,min=1,max=32,oneof=tcp4 tcp6" json:"net_type"`
CertData string `gorm:"column:cert_data;type:text" form:"cert_data" json:"cert_data"`
CertPwd string `gorm:"column:cert_pwd;not null;size:128;default:''" form:"cert_pwd" binding:"max=128" json:"cert_pwd"`
Port uint16 `gorm:"column:port;not null;default:22" form:"port" binding:"required,gte=1,lte=65535" json:"port"`
FontSize uint16 `gorm:"column:font_size;not null;default:14" form:"font_size" binding:"required,gte=8,lte=48" json:"font_size"`
Background string `gorm:"column:background;not null;size:128;default:'#000000'" form:"background" binding:"required,hexcolor" json:"background"`
Foreground string `gorm:"column:foreground;not null;size:128;default:'#FFFFFF'" form:"foreground" binding:"required,hexcolor" json:"foreground"`
CursorColor string `gorm:"column:cursor_color;not null;size:128;default:'#FFFFFF'" form:"cursor_color" binding:"required,hexcolor" json:"cursor_color"`
FontFamily string `gorm:"column:font_family;not null;size:128;default:'Courier'" form:"font_family" binding:"min=1,max=128" json:"font_family"`
CursorStyle string `gorm:"column:cursor_style;not null;size:128;default:'block'" form:"cursor_style" binding:"min=1,max=128" json:"cursor_style"`
Shell string `gorm:"column:shell;not null;size:64;default:'sh'" form:"shell" binding:"min=1,max=128" json:"shell"`
PtyType string `gorm:"column:pty_type;not null;size:64;default:'xterm-256color'" form:"pty_type" binding:"min=1,max=128" json:"pty_type"`
InitCmd string `gorm:"column:init_cmd;type:text" form:"init_cmd" json:"init_cmd"`
InitBanner string `gorm:"column:init_banner;type:text" form:"init_banner" json:"init_banner"`
CreatedAt DateTime `gorm:"column:created_at" json:"-"`
UpdatedAt DateTime `gorm:"column:updated_at" json:"-"`
}
func (c *SshConf) Create(conf *SshConf) error {
return Db.Create(conf).Error
}
func (c *SshConf) FindByID(id uint, uid uint) (SshConf, error) {
var conf SshConf
err := Db.First(&conf, "id = ? AND uid = ?", id, uid).Error
return conf, err
}
func (c *SshConf) FindAll(offset, limit int, uid uint) ([]SshConf, error) {
var list []SshConf
err := Db.Where("uid = ?", uid).Offset(offset).Limit(limit).Order("updated_at desc").Find(&list).Error
return list, err
}
func (_ *SshConf) UpdateById(id, uid uint, conf *SshConf) error {
return Db.Model(&conf).Where("id = ? AND uid = ?", id, uid).Select("*").Omit("id", "uid").Updates(conf).Error
}
func (c *SshConf) DeleteByID(id, uid uint) error {
return Db.Unscoped().Delete(&c, "id = ? AND uid = ?", id, uid).Error
}
// BeforeCreate Hook
func (c *SshConf) BeforeCreate(_ *gorm.DB) error {
_, err := c.sshConfEncrypt()
return err
}
// BeforeUpdate Hook
func (c *SshConf) BeforeUpdate(_ *gorm.DB) error {
_, err := c.sshConfEncrypt()
return err
}
// AfterFind Hook
func (c *SshConf) AfterFind(_ *gorm.DB) error {
var err error
c.Pwd, err = utils.DecryptString(c.Pwd, config.DefaultConfig.AesSecret)
if err != nil {
return errors.New("解密密码错误," + err.Error())
}
c.CertPwd, err = utils.DecryptString(c.CertPwd, config.DefaultConfig.AesSecret)
if err != nil {
return errors.New("解密证书密码错误,," + err.Error())
}
c.CertData, err = utils.DecryptString(c.CertData, config.DefaultConfig.AesSecret)
if err != nil {
return errors.New("解密密证书数据错误," + err.Error())
}
return nil
}
func (c *SshConf) sshConfEncrypt() (*SshConf, error) {
var err error
c.Pwd, err = utils.EncryptString(c.Pwd, config.DefaultConfig.AesSecret)
if err != nil {
return c, errors.New("加密密码错误," + err.Error())
}
c.CertPwd, err = utils.EncryptString(c.CertPwd, config.DefaultConfig.AesSecret)
if err != nil {
return c, errors.New("加密证书密码错误," + err.Error())
}
c.CertData, err = utils.EncryptString(c.CertData, config.DefaultConfig.AesSecret)
if err != nil {
return c, errors.New("加密证书数据错误," + err.Error())
}
return c, nil
}
================================================
FILE: gossh/app/model/sshd_cert.go
================================================
package model
import "time"
type SshdCert struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
DescInfo string `gorm:"column:desc_info;size:64" form:"desc_info" binding:"required,min=1,max=64" json:"desc_info"`
Name string `gorm:"column:name;uniqueIndex;not null;size:64" form:"name" binding:"required,min=1,max=63" json:"name"`
PubKey string `gorm:"column:pub_key;type:text;not null;" form:"pub_key" binding:"required,min=16" json:"pub_key"`
IsEnable string `gorm:"column:is_enable;not null;size:64;default:'Y'" form:"is_enable" binding:"required,min=1,max=64,oneof=Y N" json:"is_enable"`
ExpiryAt DateTime `gorm:"column:expiry_at;not null" json:"expiry_at" form:"expiry_at" binding:"required"`
CreatedAt DateTime `gorm:"column:created_at" json:"-"`
UpdatedAt DateTime `gorm:"column:updated_at" json:"-"`
}
func (c *SshdCert) Create(user *SshdCert) error {
return Db.Create(user).Error
}
func (c *SshdCert) FindByName(name string) (SshdCert, error) {
var user SshdCert
err := Db.Find(&user, "name = ?", name).Error
return user, err
}
func (c *SshdCert) FindByID(id uint) (SshdCert, error) {
var user SshdCert
err := Db.First(&user, "id = ?", id).Error
return user, err
}
func (c *SshdCert) FindAll(limit, offset int) ([]SshdCert, error) {
var list []SshdCert
err := Db.Limit(limit).Offset(offset).Find(&list).Error
return list, err
}
func (c *SshdCert) GetAuthorizedKeys() (string, error) {
var authorizedKeys = ""
var list []string
err := Db.Model(c).Select("pub_key").Where("is_enable = ? AND expiry_at > ?", "Y", time.Now()).Find(&list).Error
if err != nil {
return "", err
}
for _, v := range list {
authorizedKeys += v + "\n"
}
return authorizedKeys, err
}
func (c *SshdCert) UpdateById(id uint, user *SshdCert) error {
return Db.Model(&c).Where("id = ?", id).Select("*").Omit("id").Updates(user).Error
}
func (c *SshdCert) DeleteByID(id uint) error {
return Db.Unscoped().Delete(&c, "id = ?", id).Error
}
================================================
FILE: gossh/app/model/sshd_conf.go
================================================
package model
import (
"gossh/app/config"
"gossh/app/utils"
"gossh/gorm"
)
type SshdConf struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
Name string `gorm:"column:name;uniqueIndex;not null;size:64" form:"name" binding:"required,min=1,max=63" json:"name"`
Host string `gorm:"column:host;size:128" form:"host" binding:"required,min=1,max=128" json:"host"`
Port uint16 `gorm:"column:port;uniqueIndex;not null" form:"port" binding:"required,gte=1,lte=65535" json:"port"`
Shell string `gorm:"column:shell;not null;size:64;default:''" form:"shell" binding:"min=1,max=128" json:"shell"`
KeyFile string `gorm:"column:key_file;not null;type:text" form:"key_file" json:"key_file"`
KeySeed string `gorm:"column:key_seed;not null;size:4096;default:''" form:"key_seed" binding:"max=4096" json:"key_seed"`
KeepAlive uint16 `gorm:"column:keep_alive;not null;default:60" form:"keep_alive" binding:"required,gte=10,lte=360" json:"keep_alive"`
LoadEnv string `gorm:"column:load_env;not null;size:64;default:'Y'" form:"load_env" binding:"required,min=1,max=64,oneof=Y N" json:"load_env"`
AuthType string `gorm:"column:auth_type;not null;size:32;default:'all'" form:"auth_type" binding:"required,min=1,max=32,oneof=all pwd cert" json:"auth_type"`
ServerVersion string `gorm:"column:server_version;not null;size:64;default:'SSH-2.0-OpenSSH'" form:"name" binding:"required,min=10,max=63" json:"server_version"`
CreatedAt DateTime `gorm:"column:created_at" json:"-"`
UpdatedAt DateTime `gorm:"column:updated_at" json:"-"`
}
func (c *SshdConf) Create(conf *SshdConf) error {
return Db.Create(conf).Error
}
func (c *SshdConf) FindByName(name string) (SshdConf, error) {
var conf SshdConf
err := Db.Find(&conf, "name = ?", name).Error
return conf, err
}
func (c *SshdConf) FindByID(id uint) (SshdConf, error) {
var conf SshdConf
err := Db.First(&conf, "id = ?", id).Error
return conf, err
}
func (c *SshdConf) UpdateByName(name string, conf *SshdConf) error {
return Db.Model(&c).Where("name = ?", name).Select("*").Omit("id", "name").Updates(conf).Error
}
func (c *SshdConf) DeleteByName(name string) error {
return Db.Unscoped().Delete(&c, "name = ?", name).Error
}
// BeforeCreate Hook
func (c *SshdConf) BeforeCreate(_ *gorm.DB) error {
var err error
c.KeyFile, err = utils.EncryptString(c.KeyFile, config.DefaultConfig.AesSecret)
return err
}
// BeforeUpdate Hook
func (c *SshdConf) BeforeUpdate(_ *gorm.DB) error {
var err error
c.KeyFile, err = utils.EncryptString(c.KeyFile, config.DefaultConfig.AesSecret)
return err
}
// AfterFind Hook
func (c *SshdConf) AfterFind(_ *gorm.DB) error {
var err error
c.KeyFile, err = utils.DecryptString(c.KeyFile, config.DefaultConfig.AesSecret)
return err
}
================================================
FILE: gossh/app/model/sshd_user.go
================================================
package model
import (
"errors"
"fmt"
"gossh/app/config"
"gossh/app/utils"
"gossh/gorm"
"time"
)
type SshdUser struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
Name string `gorm:"column:name;uniqueIndex;not null;size:64" form:"name" binding:"required,min=1,max=63" json:"name"`
Pwd string `gorm:"column:pwd;size:64" form:"pwd" binding:"required,min=1,max=64" json:"pwd"`
DescInfo string `gorm:"column:desc_info;size:64" form:"desc_info" binding:"required,min=1,max=64" json:"desc_info"`
IsEnable string `gorm:"column:is_enable;not null;size:64;default:'Y'" form:"is_enable" binding:"required,min=1,max=64,oneof=Y N" json:"is_enable"`
WorkDir string `gorm:"column:work_dir;size:4096;default:''" form:"work_dir" binding:"max=4096" json:"work_dir"`
ExpiryAt DateTime `gorm:"column:expiry_at;not null" json:"expiry_at" form:"expiry_at" binding:"required"`
CreatedAt DateTime `gorm:"column:created_at" json:"-"`
UpdatedAt DateTime `gorm:"column:updated_at" json:"-"`
}
func (c *SshdUser) Create(user *SshdUser) error {
return Db.Create(user).Error
}
func (c *SshdUser) FindByNameAndPwd(name, pwd string) (SshdUser, error) {
var user SshdUser
err := Db.First(&user, "name = ? AND is_enable = ?", name, "Y").Error
if err != nil {
return SshdUser{}, err
}
if user.Pwd != pwd {
return SshdUser{}, errors.New("password error")
}
if user.ExpiryAt.ToTime().Unix() < time.Now().Unix() {
return user, errors.New(fmt.Sprintf("sshd user '%s' expired", name))
}
return user, err
}
func (c *SshdUser) FindByName(name string) (SshdUser, error) {
var user SshdUser
err := Db.Find(&user, "name = ?", name).Error
return user, err
}
func (c *SshdUser) FindByID(id uint) (SshdUser, error) {
var user SshdUser
err := Db.First(&user, "id = ?", id).Error
return user, err
}
func (c *SshdUser) FindAll(limit, offset int) ([]SshdUser, error) {
var list []SshdUser
err := Db.Limit(limit).Offset(offset).Find(&list).Error
return list, err
}
func (c *SshdUser) UpdateById(id uint, user *SshdUser) error {
return Db.Model(&c).Where("id = ?", id).Select("*").Omit("id").Updates(user).Error
}
func (c *SshdUser) DeleteByID(id uint) error {
return Db.Unscoped().Delete(&c, "id = ?", id).Error
}
// BeforeCreate Hook
func (c *SshdUser) BeforeCreate(_ *gorm.DB) error {
var err error
c.Pwd, err = utils.EncryptString(c.Pwd, config.DefaultConfig.AesSecret)
return err
}
// BeforeUpdate Hook
func (c *SshdUser) BeforeUpdate(_ *gorm.DB) error {
var err error
c.Pwd, err = utils.EncryptString(c.Pwd, config.DefaultConfig.AesSecret)
return err
}
// AfterFind Hook
func (c *SshdUser) AfterFind(_ *gorm.DB) error {
var err error
c.Pwd, err = utils.DecryptString(c.Pwd, config.DefaultConfig.AesSecret)
return err
}
================================================
FILE: gossh/app/model/web_user.go
================================================
package model
import (
"errors"
"gossh/app/config"
"gossh/app/utils"
"gossh/gorm"
)
type WebUser struct {
ID uint `gorm:"column:id;primaryKey,autoIncrement" form:"id" json:"id"`
Name string `gorm:"column:name;uniqueIndex;not null;size:64" form:"name" binding:"required,min=1,max=63" json:"name"`
Pwd string `gorm:"column:pwd;size:64" form:"pwd" binding:"required,min=1,max=64" json:"pwd"`
DescInfo string `gorm:"column:desc_info;size:64" form:"desc_info" binding:"required,min=1,max=64" json:"desc_info"`
IsAdmin string `gorm:"column:is_admin;not null;size:64;default:'N'" form:"is_admin" binding:"required,min=1,max=64,oneof=Y N" json:"is_admin"`
IsEnable string `gorm:"column:is_enable;not null;size:64;default:'Y'" form:"is_enable" binding:"required,min=1,max=64,oneof=Y N" json:"is_enable"`
IsRoot string `gorm:"column:is_root;not null;size:64;default:'N'" form:"is_root" json:"is_root"`
ExpiryAt DateTime `gorm:"column:expiry_at;not null" json:"expiry_at" form:"expiry_at" binding:"required"`
CreatedAt DateTime `gorm:"column:created_at" json:"-"`
UpdatedAt DateTime `gorm:"column:updated_at" json:"-"`
}
func (c *WebUser) Create(user *WebUser) error {
return Db.Create(user).Error
}
func (c *WebUser) FindByNameAndPwd(name, pwd string) (WebUser, error) {
var user WebUser
err := Db.First(&user, "name = ?", name).Error
if err != nil {
return WebUser{}, err
}
if user.Pwd != pwd {
return WebUser{}, errors.New("password error")
}
return user, err
}
func (c *WebUser) FindByName(name string) (WebUser, error) {
var user WebUser
err := Db.Find(&user, "name = ?", name).Error
return user, err
}
func (c *WebUser) FindByID(id uint) (WebUser, error) {
var user WebUser
err := Db.First(&user, "id = ?", id).Error
return user, err
}
func (c *WebUser) FindAll(limit, offset int) ([]WebUser, error) {
var list []WebUser
err := Db.Where("is_root = ?", "N").Limit(limit).Offset(offset).Find(&list).Error
return list, err
}
func (c *WebUser) UpdateById(id uint, user *WebUser) error {
return Db.Model(&c).Where("id = ? AND is_root = ?", id, "N").Select("*").Omit("id", "is_root").Updates(user).Error
}
func (c *WebUser) UpdatePassword(id uint, user *WebUser) error {
return Db.Model(&c).Where("id = ?", id).Select("*").Omit("id").Updates(user).Error
}
func (c *WebUser) DeleteByID(id uint) error {
return Db.Unscoped().Delete(&c, "id = ? AND is_root = ?", id, "N").Error
}
// BeforeCreate Hook
func (c *WebUser) BeforeCreate(_ *gorm.DB) error {
var err error
c.Pwd, err = utils.EncryptString(c.Pwd, config.DefaultConfig.AesSecret)
return err
}
// BeforeUpdate Hook
func (c *WebUser) BeforeUpdate(_ *gorm.DB) error {
var err error
c.Pwd, err = utils.EncryptString(c.Pwd, config.DefaultConfig.AesSecret)
return err
}
// AfterFind Hook
func (c *WebUser) AfterFind(_ *gorm.DB) error {
var err error
c.Pwd, err = utils.DecryptString(c.Pwd, config.DefaultConfig.AesSecret)
return err
}
================================================
FILE: gossh/app/service/cmd_note.go
================================================
package service
import (
"gossh/app/model"
"gossh/gin"
"strconv"
)
func CmdNoteCreate(c *gin.Context) {
var cmd model.CmdNote
if err := c.ShouldBind(&cmd); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
cmd.Uid = c.GetUint("uid")
err := cmd.Create(&cmd)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
CmdNoteFindAll(c)
}
func CmdNoteFindByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var cmd model.CmdNote
data, err := cmd.FindByID(uint(id), c.GetUint("uid"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func CmdNoteFindAll(c *gin.Context) {
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10000"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var cmd model.CmdNote
data, err := cmd.FindAll(offset, limit, c.GetUint("uid"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func CmdNoteUpdateById(c *gin.Context) {
var cmd model.CmdNote
if err := c.ShouldBind(&cmd); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err := cmd.UpdateById(cmd.ID, c.GetUint("uid"), &cmd)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
CmdNoteFindAll(c)
}
func CmdNoteDeleteById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var cmd model.CmdNote
err = cmd.DeleteByID(uint(id), c.GetUint("uid"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
CmdNoteFindAll(c)
}
================================================
FILE: gossh/app/service/db_conn.go
================================================
package service
import (
"gossh/app/config"
"gossh/app/model"
"gossh/gin"
"gossh/gorm"
"gossh/gorm/driver/mysql"
"gossh/gorm/driver/pgsql"
_ "gossh/mysql"
_ "gossh/pgsql"
"log/slog"
)
type DbConnConf struct {
DbDsn string `form:"db_dsn" binding:"required,min=1,max=65535" json:"db_dsn"`
DbType string `form:"db_type" binding:"required,oneof=sqlite pgsql mysql" json:"db_type"`
}
func DbConnCheck(c *gin.Context) {
if config.DefaultConfig.IsInit {
c.JSON(200, gin.H{"code": 1, "msg": "系统已经完成初始化配置"})
return
}
var dbConf DbConnConf
if err := c.ShouldBind(&dbConf); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err := DbConnTestCheck(dbConf)
if err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "连接成功"})
}
func DbConnTestCheck(dbConf DbConnConf) error {
slog.Info("DB link check", "db_type", dbConf.DbType, "db_dsn", dbConf.DbDsn)
if dbConf.DbType == "pgsql" {
Db, err := gorm.Open(pgsql.Open(dbConf.DbDsn), &gorm.Config{})
if err != nil {
return err
}
err = Db.Exec("select 1=1;").Error
if err != nil {
return err
}
}
if dbConf.DbType == "mysql" {
Db, err := gorm.Open(mysql.Open(dbConf.DbDsn), &gorm.Config{})
if err != nil {
return err
}
err = Db.Exec("select 1=1;").Error
if err != nil {
return err
}
}
if dbConf.DbType == "sqlite" {
Db, err := model.GetSqliteDb(dbConf.DbDsn)
if err != nil {
return err
}
err = Db.Exec("select 1=1;").Error
if err != nil {
return err
}
}
return nil
}
================================================
FILE: gossh/app/service/login_audit.go
================================================
package service
import (
"gossh/app/model"
"gossh/gin"
"strconv"
)
func AuditFindByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var audit model.LoginAudit
data, err := audit.FindByID(uint(id))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func LoginAuditSearch(c *gin.Context) {
type Param struct {
OccurBegin model.DateTime `json:"occur_begin" form:"occur_begin"`
OccurEnd model.DateTime `json:"occur_end" form:"occur_end"`
Offset int `form:"offset" json:"offset" binding:"min=0"`
Limit int `form:"limit" json:"limit" binding:"max=1000"`
Name string `form:"name" binding:"max=64" json:"name"`
ClientIp string `form:"client_ip" binding:"max=128" json:"client_ip"`
IsSuccess string `form:"is_success" binding:"max=1" json:"is_success"`
}
var p Param
if err := c.ShouldBind(&p); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
if p.Limit == 0 {
p.Limit = 100
}
var audit model.LoginAudit
data, count, err := audit.Search(p.IsSuccess, p.Name, p.ClientIp, p.OccurBegin, p.OccurEnd, p.Offset, p.Limit)
if err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data, "count": count})
}
func LoginAuditDeleteById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var audit model.LoginAudit
err = audit.DeleteByID(uint(id))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
}
================================================
FILE: gossh/app/service/net_filter.go
================================================
package service
import (
"gossh/app/model"
"gossh/gin"
"strconv"
)
func NetFilterCreate(c *gin.Context) {
var netFilter model.NetFilter
if err := c.ShouldBind(&netFilter); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err := netFilter.Create(&netFilter)
if err != nil {
c.JSON(200, gin.H{"code": 3, "msg": err.Error()})
return
}
NetFilterFindAll(c)
}
func NetFilterFindByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var netFilter model.NetFilter
data, err := netFilter.FindByID(uint(id))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func NetFilterFindAll(c *gin.Context) {
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10000"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var netFilter model.NetFilter
data, err := netFilter.FindAll(offset, limit)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func NetFilterUpdateById(c *gin.Context) {
var netFilter model.NetFilter
if err := c.ShouldBind(&netFilter); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err := netFilter.UpdateById(netFilter.ID, &netFilter)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
NetFilterFindAll(c)
}
func NetFilterDeleteById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var netFilter model.NetFilter
err = netFilter.DeleteByID(uint(id))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
NetFilterFindAll(c)
}
================================================
FILE: gossh/app/service/policy_conf.go
================================================
package service
import (
"gossh/app/model"
"gossh/gin"
"strconv"
)
func PolicyConfCreate(c *gin.Context) {
var conf model.PolicyConf
if err := c.ShouldBind(&conf); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err := conf.Create(&conf)
if err != nil {
c.JSON(200, gin.H{"code": 3, "msg": err.Error()})
return
}
PolicyConfFindAll(c)
}
func PolicyConfFindByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var conf model.PolicyConf
data, err := conf.FindByID(uint(id))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func PolicyConfFindAll(c *gin.Context) {
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10000"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var conf model.PolicyConf
data, err := conf.FindAll(offset, limit)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func PolicyConfUpdateById(c *gin.Context) {
var conf model.PolicyConf
if err := c.ShouldBind(&conf); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err := conf.UpdateById(conf.ID, &conf)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
data, err := conf.FindByID(conf.ID)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func PolicyConfDeleteById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var conf model.PolicyConf
err = conf.DeleteByID(uint(id))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
PolicyConfFindAll(c)
}
================================================
FILE: gossh/app/service/service_init.go
================================================
package service
import (
"gossh/app/config"
"io"
"log/slog"
"sync"
"time"
)
// OnlineClients 存储的客户端信息
var OnlineClients = sync.Map{}
func DeleteOnlineClient(sessionId string) {
defer func() {
if err := recover(); err != nil {
slog.Error("DeleteOnlineClient recover error:", "err_msg", err)
}
}()
cli, ok := OnlineClients.Load(sessionId)
if !ok || cli == nil {
slog.Info("OnlineClient sessionId not exist")
return
}
conn, ok := cli.(*SshConn)
if !ok || conn == nil {
slog.Error("DeleteOnlineClient type Asset error")
return
}
// 从map 中删除会话
defer OnlineClients.Delete(sessionId)
// 关闭 ssh 客户端
defer func() {
err := conn.sshClient.Close()
if err == io.EOF {
slog.Info("sshClient.Close EOF")
return
}
if err != nil {
slog.Error("DeleteOnlineClient.Close sshClient error:", "err_msg", err)
}
}()
// 关闭 sftp 客户端
defer func() {
err := conn.sftpClient.Close()
if err == io.EOF {
slog.Info("sftpClient.Close EOF")
return
}
if err != nil {
slog.Error("DeleteOnlineClient.Close sftpClient error:", "err_msg", err)
}
}()
// 关闭 ssh 会话
defer func() {
err := conn.sshSession.Close()
if err == io.EOF {
slog.Info("sshSession.Close EOF")
return
}
if err != nil {
slog.Error("DeleteOnlineClient.Close sshSession error:", "err_msg", err)
}
}()
// 关闭 websocket
defer func() {
err := conn.ws.Close()
if err != nil {
slog.Error("DeleteOnlineClient.Close ws error:", "err_msg", err)
}
}()
}
// 清理不活跃的会话
func cleanNoActiveSession() {
defer func() {
if err := recover(); err != nil {
slog.Error("cleanNoActiveSession error:", "err_msg", err)
}
}()
OnlineClients.Range(func(key, value any) bool {
// 对键进行类型断言
if sessionId, ok := key.(string); ok {
// 对值进行类型断言
if conn, ok := value.(*SshConn); ok {
if conn.LastActiveTime.Add(time.Minute).Before(time.Now()) {
slog.Info("clean not active session:", "sid", sessionId)
DeleteOnlineClient(sessionId)
}
}
}
return true
})
}
func initApp() {
defer func() {
if err := recover(); err != nil {
slog.Error("service init error")
}
}()
if config.DefaultConfig.IsInit {
isStartSshd <- true
}
for {
cleanNoActiveSession()
time.Sleep(config.DefaultConfig.ClientCheck)
}
}
func InitSessionClean() {
go initApp()
}
================================================
FILE: gossh/app/service/ssh_conf.go
================================================
package service
import (
"gossh/app/model"
"gossh/gin"
"strconv"
)
func ConfCreate(c *gin.Context) {
var config model.SshConf
if err := c.ShouldBind(&config); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
config.Uid = c.GetUint("uid")
err := config.Create(&config)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
ConfFindAll(c)
}
func ConfFindByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var config model.SshConf
data, err := config.FindByID(uint(id), c.GetUint("uid"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func ConfFindAll(c *gin.Context) {
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10000"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var config model.SshConf
data, err := config.FindAll(offset, limit, c.GetUint("uid"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func ConfUpdateById(c *gin.Context) {
var config model.SshConf
if err := c.ShouldBind(&config); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err := config.UpdateById(config.ID, c.GetUint("uid"), &config)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
// c.JSON(200, gin.H{"code": 0, "msg": "ok"})
ConfFindAll(c)
}
func ConfDeleteById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var config model.SshConf
err = config.DeleteByID(uint(id), c.GetUint("uid"))
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
// c.JSON(200, gin.H{"code": 0, "msg": "ok"})
ConfFindAll(c)
}
================================================
FILE: gossh/app/service/ssh_conn.go
================================================
package service
import (
"encoding/json"
"fmt"
"gossh/app/model"
"gossh/app/utils"
"gossh/crypto/ssh"
"gossh/gin"
"gossh/sftp"
"gossh/websocket"
"io"
"log/slog"
"net/http"
"strconv"
"strings"
"time"
)
type SshConn struct {
*model.SshConf
//会话ID
SessionId string `json:"session_id"`
// 最后活跃时间,心跳
LastActiveTime time.Time `json:"last_active_time"`
// 创建连接的时间
StartTime time.Time `json:"start_time"`
// 客户端IP
ClientIP string `json:"client_ip"`
//ssh客户端
sshClient *ssh.Client
//sftp客户端
sftpClient *sftp.Client
//ssh会话
sshSession *ssh.Session
// websocket 连接
ws *websocket.Conn
}
// MarshalJSON 重写序列化方法
func (s *SshConn) MarshalJSON() ([]byte, error) {
type Alias SshConn
return json.Marshal(&struct {
Alias
LastActiveTime string `json:"last_active_time"`
StartTime string `json:"start_time"`
Pwd string `json:"pwd"`
CertData string `json:"cert_data"`
CertPwd string `json:"cert_pwd"`
CreatedAt uint ` json:"created_at"`
UpdatedAt uint ` json:"updated_at"`
DeletedAt uint ` json:"deleted_at"`
}{
Alias: (Alias)(*s),
LastActiveTime: s.LastActiveTime.Format("2006-01-02 15:04:05"),
StartTime: s.StartTime.Format("2006-01-02 15:04:05"),
Pwd: "",
CertData: "",
CertPwd: "",
CreatedAt: 0,
UpdatedAt: 0,
DeletedAt: 0,
})
}
// 连接主机
func (s *SshConn) connect(clientIp string) error {
defer func() {
if err := recover(); err != nil {
slog.Error("ssh connect error:", "err_msg", err)
}
}()
s.ClientIP = clientIp
config := ssh.ClientConfig{
User: s.User,
Auth: []ssh.AuthMethod{
ssh.Password(s.Pwd),
ssh.KeyboardInteractive(func(name, instruction string, questions []string, echos []bool) ([]string, error) {
answers := make([]string, len(questions))
for i := range answers {
answers[i] = s.Pwd
}
return answers, nil
}),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: 30 * time.Second,
}
// 证书认证方式
if s.AuthType == "cert" {
privateKeyPassword := []byte(s.CertPwd)
privateKeyBytes := []byte(s.CertData)
if s.CertPwd != "" {
// 使用证书有证书密码登陆
signer, err := ssh.ParsePrivateKeyWithPassphrase(privateKeyBytes, privateKeyPassword)
if err != nil {
slog.Error("解析带密码私钥Key错误:", "err_msg", err.Error())
return err
}
config.Auth = []ssh.AuthMethod{
ssh.PublicKeys(signer),
}
} else {
// 使用证书空密码登陆
signer, err := ssh.ParsePrivateKey(privateKeyBytes)
if err != nil {
slog.Error("解析私钥Key错误:", "err_msg", err.Error())
return err
}
config.Auth = []ssh.AuthMethod{
ssh.PublicKeys(signer),
}
}
}
addr := fmt.Sprintf("%s:%d", s.Address, s.Port)
if s.NetType == "tcp6" {
addr = fmt.Sprintf("[%s]:%d", s.Address, s.Port)
}
sshClient, err := ssh.Dial(s.NetType, addr, &config)
if err != nil {
return err
}
s.sshClient = sshClient
//使用sshClient构建sftpClient
var sftpClient *sftp.Client
if sftpClient, err = sftp.NewClient(sshClient); err != nil {
slog.Error("create sftp sshClient error:", "err_msg", err)
}
s.sftpClient = sftpClient
sshSession, err := s.sshClient.NewSession()
if err != nil {
slog.Error("sshClient.NewSession error:", "err_msg", err.Error())
return err
}
s.sshSession = sshSession
return nil
}
// RunTerminal 运行一个终端
func (s *SshConn) RunTerminal(shell string, stdout, stderr io.Writer, stdin io.Reader, w, h int, ws *websocket.Conn) error {
defer func() {
DeleteOnlineClient(s.SessionId)
if err := recover(); err != nil {
slog.Error("RunTerminal error:", "err_msg", err)
}
}()
var err error
s.ws = ws
s.sshSession.Stdout = stdout
s.sshSession.Stderr = stderr
s.sshSession.Stdin = stdin
modes := ssh.TerminalModes{}
if err := s.sshSession.RequestPty(s.PtyType, h, w, modes); err != nil {
slog.Error("sshSession.RequestPty error:", "err_msg", err.Error())
ws.WriteMessage(websocket.BinaryMessage, []byte("sshSession.RequestPty error:"+err.Error()))
return err
}
if err = s.sshSession.Shell(); err != nil {
slog.Error("sshSession.Shell error:", "err_msg", err.Error())
return err
}
if err = s.sshSession.Wait(); err != nil {
if strings.Contains(err.Error(), "remote command exited without exit status or exit signal") {
slog.Info("sshSession.Wait remote command exited without exit status or exit signal")
return err
}
slog.Error("sshSession.Wait error:", "err_msg", err.Error())
return err
}
return nil
}
// ResizeWindow 调整终端大小
func (s *SshConn) ResizeWindow(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
slog.Error("ResizeWindow recover error:", "err_msg", err)
}
}()
w, err := strconv.Atoi(c.Query("w"))
if err != nil || (w < 40 || w > 8192) {
c.JSON(200, gin.H{
"code": 1,
"msg": fmt.Sprintf("connect error window width !!!")})
return
}
h, err := strconv.Atoi(c.Query("h"))
if err != nil || (h < 2 || h > 4096) {
c.JSON(200, gin.H{
"code": 1,
"msg": fmt.Sprintf("connect error window width !!!")})
return
}
sessionId := c.Query("session_id")
cli, ok := OnlineClients.Load(sessionId)
if !ok || cli == nil {
c.JSON(200, gin.H{"code": 1, "msg": "the client is disconnected"})
return
}
conn, ok := cli.(*SshConn)
if !ok || conn == nil {
DeleteOnlineClient(sessionId)
c.JSON(200, gin.H{"code": 1, "msg": "to type SshConn error"})
return
}
err = conn.sshSession.WindowChange(h, w)
if err != nil {
DeleteOnlineClient(sessionId)
slog.Error("sshSession.WindowChange error:", "err_msg", err.Error())
}
str := fmt.Sprintf("W:%d;H:%d\n", w, h)
c.JSON(200, gin.H{"code": 0, "data": str, "msg": "ok"})
return
}
func ResizeWindow(c *gin.Context) {
var sshObj = SshConn{}
sshObj.ResizeWindow(c)
}
func NewSshConn(c *gin.Context) {
// 设置 websocket upgrader
upgrader := websocket.Upgrader{
ReadBufferSize: 4096,
WriteBufferSize: 4096,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
// 升级 HTTP 连接为 WebSocket 连接
ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
slog.Error("Failed to upgrade connection:", "err_msg", err)
return
}
defer ws.Close()
// 设置 ping handler
ws.SetPingHandler(func(appData string) error {
return ws.WriteControl(websocket.PongMessage, []byte{}, time.Now().Add(time.Second*10))
})
// 启动 ping 保活
go func() {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if err := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(time.Second*10)); err != nil {
slog.Error("ping error:", "err_msg", err)
return
}
}
}
}()
sessionId := c.Query("session_id")
defer DeleteOnlineClient(sessionId)
w, err := strconv.Atoi(c.Query("w"))
if err != nil || (w < 40 || w > 8192) {
ws.WriteMessage(websocket.BinaryMessage, []byte("connect error window width !!!"))
DeleteOnlineClient(sessionId)
return
}
h, err := strconv.Atoi(c.Query("h"))
if err != nil || (h < 2 || h > 4096) {
ws.WriteMessage(websocket.BinaryMessage, []byte("connect error window height !!!"))
DeleteOnlineClient(sessionId)
return
}
cli, ok := OnlineClients.Load(sessionId)
if !ok || cli == nil {
ws.WriteMessage(websocket.BinaryMessage, []byte("session_id not exists !!!"))
DeleteOnlineClient(sessionId)
return
}
conn, ok := cli.(*SshConn)
if !ok || conn == nil {
ws.WriteMessage(websocket.BinaryMessage, []byte("to ssh.Session error !!!"))
DeleteOnlineClient(sessionId)
return
}
// 创建一个适配器来实现 io.Reader 和 io.Writer 接口
wsReadWriter := &WebSocketReadWriter{ws: ws}
err = conn.RunTerminal(conn.Shell, wsReadWriter, wsReadWriter, wsReadWriter, w, h, ws)
if err != nil {
ws.WriteMessage(websocket.BinaryMessage, []byte("connect error:"+err.Error()))
DeleteOnlineClient(sessionId)
return
}
}
// WebSocketReadWriter 实现 io.Reader 和 io.Writer 接口
type WebSocketReadWriter struct {
ws *websocket.Conn
}
func (w *WebSocketReadWriter) Read(p []byte) (n int, err error) {
_, message, err := w.ws.ReadMessage()
if err != nil {
return 0, err
}
copy(p, message)
return len(message), nil
}
func (w *WebSocketReadWriter) Write(p []byte) (n int, err error) {
err = w.ws.WriteMessage(websocket.BinaryMessage, p)
if err != nil {
return 0, err
}
return len(p), nil
}
func CreateSessionId(c *gin.Context) {
var conn SshConn
if err := c.ShouldBind(&conn); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
// 如果客户提供,使用客户的,并从会话列表删除,防止重复存在
sessionId := c.Query("session_id")
//DeleteOnlineClient(sessionId)
if sessionId == "" {
sessionId = utils.RandString(15)
}
conn.SessionId = sessionId
conn.LastActiveTime = time.Now()
conn.StartTime = time.Now()
err := conn.connect(c.RemoteIP())
if err != nil {
c.JSON(200, gin.H{"code": 1, "msg": "CreateSessionId error:" + err.Error()})
return
}
OnlineClients.Store(sessionId, &conn)
c.JSON(200, gin.H{"code": 0, "data": sessionId, "msg": "ok"})
}
func Disconnect(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.JSON(200, gin.H{
"code": 1,
"msg": "delete connect error",
})
}
}()
sessionId := c.Query("session_id")
if sessionId == "" {
c.JSON(200, gin.H{
"code": 1,
"msg": "session not exists",
})
return
}
DeleteOnlineClient(sessionId)
c.JSON(200, gin.H{
"code": 0,
"msg": "delete connect success",
})
}
func ExecCommand(c *gin.Context) {
type Param struct {
SessionId string `form:"session_id" binding:"required,min=10" json:"session_id"`
Cmd string `form:"cmd" binding:"required,min=1" json:"cmd"`
}
var param Param
if err := c.ShouldBind(¶m); err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
cli, ok := OnlineClients.Load(param.SessionId)
if !ok || cli == nil {
c.JSON(200, gin.H{"code": 3, "msg": "session not exists"})
return
}
conn, ok := cli.(*SshConn)
if !ok || conn == nil {
c.JSON(200, gin.H{"code": 4, "msg": "conn not exists"})
return
}
//创建ssh-session
session, err := conn.sshClient.NewSession()
if err != nil {
c.JSON(200, gin.H{"code": 5, "msg": "create session error"})
return
}
defer func(session *ssh.Session) {
_ = session.Close()
}(session)
//执行命令
out, err := session.CombinedOutput(param.Cmd)
if err != nil {
c.JSON(200, gin.H{"code": 6, "msg": "exec cmd error", "data": string(out)})
return
}
c.JSON(200, gin.H{
"code": 0,
"msg": "ok",
"data": string(out),
})
}
================================================
FILE: gossh/app/service/ssh_sftp.go
================================================
package service
import (
"errors"
"fmt"
"gossh/gin"
"io"
"log/slog"
"net/http"
"net/url"
"path"
"strconv"
"strings"
)
func getSshConn(sessionId string) (*SshConn, error) {
cli, ok := OnlineClients.Load(sessionId)
if !ok {
slog.Error("加载ssh连接错误")
return nil, errors.New("加载ssh连接错误")
}
conn, ok := cli.(*SshConn)
if conn != nil && !ok {
slog.Error("断言ssh连接错误")
return nil, errors.New("断言ssh连接错误")
}
return conn, nil
}
// SftpList GET sftp 获取指定目录下文件信息
func SftpList(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.JSON(200, gin.H{"code": 4, "msg": "读取目录错误"})
return
}
}()
dirPath := c.PostForm("path")
conn, err := getSshConn(c.PostForm("session_id"))
if err != nil {
slog.Error(err.Error())
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
files, err := conn.sftpClient.ReadDir(dirPath)
if err != nil {
slog.Error("sftp客户端ReadDir错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "sftp客户端读取目录错误"})
return
}
fileCount := 0
dirCount := 0
var fileList []any
for _, file := range files {
fileInfo := map[string]any{}
fileInfo["path"] = path.Join(dirPath, file.Name())
fileInfo["name"] = file.Name()
fileInfo["mode"] = file.Mode().String()
fileInfo["size"] = file.Size()
fileInfo["mod_time"] = file.ModTime().Format("2006-01-02 15:04:05")
if file.IsDir() {
fileInfo["type"] = "d"
dirCount += 1
} else {
fileInfo["type"] = "f"
fileCount += 1
}
fileList = append(fileList, fileInfo)
}
// 内部方法,处理路径信息
pathHandler := func(dirPath string) (paths []map[string]string) {
tmp := strings.Split(dirPath, "/")
var dirs []string
if strings.HasPrefix(dirPath, "/") {
dirs = append(dirs, "/")
}
for _, item := range tmp {
name := strings.TrimSpace(item)
if len(name) > 0 {
dirs = append(dirs, name)
}
}
for i, item := range dirs {
fullPath := path.Join(dirs[:i+1]...)
pathInfo := map[string]string{}
pathInfo["name"] = item
pathInfo["dir"] = fullPath
paths = append(paths, pathInfo)
}
return paths
}
data := map[string]any{
"files": fileList,
"file_count": fileCount,
"dir_count": dirCount,
"paths": pathHandler(dirPath),
"current_dir": dirPath,
}
c.JSON(200, gin.H{"code": 0, "data": data, "msg": "ok"})
}
// SftpDownLoad POST sftp 下载文件
func SftpDownLoad(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": "下载错误"})
return
}
}()
fullPath, err := url.QueryUnescape(c.Query("path"))
if err != nil {
slog.Error("获取文件路径参数错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 2, "msg": "获取文件路径参数错误"})
return
}
conn, err := getSshConn(c.Query("session_id"))
if err != nil {
slog.Error(err.Error())
c.JSON(200, gin.H{"code": 3, "msg": err.Error()})
return
}
file, err := conn.sftpClient.Open(fullPath)
defer func() {
_ = file.Close()
}()
if err != nil {
slog.Error("sftpClient.Openc错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 4, "msg": "sftp打开文件错误"})
return
}
stat, err := file.Stat()
if err != nil {
slog.Error("file.Stat()错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 4, "msg": "读取文件信息错误"})
return
}
c.Writer.WriteHeader(http.StatusOK)
c.Header("Content-Disposition", "attachment; filename="+stat.Name())
c.Header("Content-Type", "application/octet-stream")
//c.Header("Content-Type", "application/x-download")
c.Header("Content-Length", fmt.Sprintf("%d", stat.Size()))
_, err = file.WriteTo(c.Writer)
if err != nil {
slog.Error("file.WriteTo错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 5, "msg": "下载文件错误"})
return
}
c.Writer.Flush()
}
// SftpUpload PUT sftp 上传文件
func SftpUpload(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.JSON(200, gin.H{"code": 4, "msg": "上传错误"})
return
}
}()
dstPath := c.PostForm("path")
//获取上传的文件组
form, err := c.MultipartForm()
if err != nil {
slog.Error("获取form数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取form数据错误"})
return
}
files := form.File["files"]
// files := c.Request.MultipartForm.File["file"]
conn, err := getSshConn(c.PostForm("session_id"))
if err != nil {
slog.Error(err.Error())
c.JSON(200, gin.H{"code": 2, "msg": err.Error()})
return
}
var ret []string
for _, file := range files {
srcFile, err := file.Open()
if err != nil {
continue
}
fileName := file.Filename
dstFile, err := conn.sftpClient.Create(path.Join(dstPath, fileName))
if err != nil {
continue
}
_, err = io.Copy(dstFile, srcFile)
if err != nil {
continue
}
_ = srcFile.Close()
_ = dstFile.Close()
ret = append(ret, fileName)
}
msg := strconv.Itoa(len(ret)) + " 个文件上传成功"
c.JSON(200, gin.H{"code": 0, "msg": msg, "data": ret})
}
// SftpDelete DELETE sftp 删除文件或目录
func SftpDelete(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.JSON(200, gin.H{"code": 4, "msg": "删除错误"})
return
}
}()
type Body struct {
SessionId string `form:"session_id" binding:"required,min=1,max=128" json:"session_id"`
Path string `form:"path" binding:"required,min=1,max=1024" json:"path"`
}
var body Body
if err := c.ShouldBind(&body); err != nil {
slog.Error("绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
conn, err := getSshConn(body.SessionId)
if err != nil {
slog.Error(err.Error())
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err = conn.sftpClient.RemoveAll(body.Path)
if err != nil {
slog.Error("sftpClient.Remove错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 2, "msg": "删除文件错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "删除成功"})
}
// SftpCreateDir sftp 创建目录
func SftpCreateDir(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.JSON(200, gin.H{"code": 4, "msg": "创建目录错误"})
return
}
}()
type Body struct {
SessionId string `form:"session_id" binding:"required,min=1,max=128" json:"session_id"`
Path string `form:"path" binding:"required,min=1,max=1024" json:"path"`
}
var body Body
if err := c.ShouldBind(&body); err != nil {
slog.Error("绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
conn, err := getSshConn(body.SessionId)
if err != nil {
slog.Error(err.Error())
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err = conn.sftpClient.MkdirAll(body.Path)
if err != nil {
slog.Error("sftpClient.MkdirAll错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 2, "msg": "创建目录错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "创建目录成功"})
}
================================================
FILE: gossh/app/service/ssh_status.go
================================================
package service
import (
"gossh/app/config"
"gossh/gin"
"gossh/gin/sse"
"net/http"
"sort"
"time"
)
type SshConnById []SshConn
func (a SshConnById) Len() int { return len(a) }
func (a SshConnById) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a SshConnById) Less(i, j int) bool { return a[i].SessionId < a[j].SessionId }
func GetOnlineClient(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Connection", "keep-alive")
c.Header("Cache-Control", "no-cache")
c.Header("Content-Type", "text/event-stream")
for {
c.Writer.(http.Flusher).Flush()
time.Sleep(config.DefaultConfig.StatusRefresh)
select {
case <-c.Request.Context().Done():
return
default:
var data SshConnById
OnlineClients.Range(func(key, value any) bool {
conn, ok := value.(*SshConn)
if ok && conn != nil {
data = append(data, *conn)
}
return ok
})
sort.Sort(data)
c.Render(200, sse.Event{
Id: "200",
Event: "message",
Retry: 10000,
Data: map[string]any{
"code": 0,
"data": data,
"msg": "ok",
},
})
}
}
}
func RefreshConnTime(c *gin.Context) {
ids := c.PostFormArray("ids")
for _, key := range ids {
cli, ok := OnlineClients.Load(key)
if !ok {
continue
}
conn, ok := cli.(*SshConn)
if conn != nil && ok {
conn.LastActiveTime = time.Now()
}
}
c.JSON(200, gin.H{
"code": 0,
"data": ids,
"msg": "ok",
})
}
================================================
FILE: gossh/app/service/sshd_cert.go
================================================
package service
import (
"gossh/app/model"
"gossh/gin"
"log/slog"
"strconv"
)
func SshdCertCreate(c *gin.Context) {
var sshdCert model.SshdCert
if err := c.ShouldBind(&sshdCert); err != nil {
slog.Error("SshdCertCreate 绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
err := sshdCert.Create(&sshdCert)
if err != nil {
slog.Error("创建SSHD证书错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "创建SSHD证书错误"})
return
}
SshdCertFindAll(c)
}
func CheckSshdCertNameExists(c *gin.Context) {
type Name struct {
Name string `form:"name" binding:"required,min=1,max=128" json:"name"`
}
var name Name
if err := c.ShouldBind(&name); err != nil {
slog.Error("绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
var sshdCert model.SshdCert
tmp, err := sshdCert.FindByName(name.Name)
if err != nil {
slog.Error("FindByName错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "获取SSHD证书信息错误"})
return
}
if tmp.ID != 0 {
c.JSON(200, gin.H{"code": 4, "msg": "名称已经存存在"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok"})
return
}
func SshdCertFindByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
var sshdCert model.SshdCert
data, err := sshdCert.FindByID(uint(id))
if err != nil {
slog.Error("FindByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "获取SSHD证书信息错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func SshdCertFindAll(c *gin.Context) {
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10000"))
if err != nil {
slog.Error("获取limit错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取limit错误"})
return
}
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
if err != nil {
slog.Error("获取offset错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 2, "msg": "获取offset错误"})
return
}
var sshdCert model.SshdCert
data, err := sshdCert.FindAll(limit, offset)
if err != nil {
slog.Error("sshdCert.FindAll错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 4, "msg": "获取SSHD证书信息错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func SshdCertUpdateById(c *gin.Context) {
var sshdCert model.SshdCert
if err := c.ShouldBind(&sshdCert); err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
err := sshdCert.UpdateById(sshdCert.ID, &sshdCert)
if err != nil {
slog.Error("UpdateById错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 5, "msg": "更新SSHD证书错误"})
return
}
SshdCertFindAll(c)
}
func SshdCertDeleteById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
var sshdCert model.SshdCert
err = sshdCert.DeleteByID(uint(id))
if err != nil {
slog.Error("sshdCert.DeleteByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 5, "msg": "删除SSHD证书错误"})
return
}
SshdCertFindAll(c)
}
func GetSshdCertAuthorizedKeys(c *gin.Context) {
var sshdCert model.SshdCert
text, err := sshdCert.GetAuthorizedKeys()
if err != nil {
slog.Error("GetAuthorizedKeys failed", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 5, "msg": "获取SSHD证书错误", "err_msg": err})
return
}
c.JSON(200, gin.H{"code": 5, "msg": "ok", "data": text})
}
================================================
FILE: gossh/app/service/sshd_server.go
================================================
package service
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/base64"
"encoding/binary"
"encoding/pem"
"errors"
"fmt"
"gossh/app/model"
"gossh/crypto/ssh"
"gossh/pty"
"gossh/sftp"
"io"
"log"
"log/slog"
"net"
"os"
"os/exec"
"os/user"
"path/filepath"
"runtime"
"strings"
"sync"
"time"
)
type Server struct {
cli *model.SshdConf
config *ssh.ServerConfig
}
func NewServer(c *model.SshdConf) (*Server, error) {
s := &Server{cli: c}
sc, err := s.computeSSHConfig()
if err != nil {
return nil, err
}
s.config = sc
return s, nil
}
func (s *Server) Start() error {
listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.cli.Host, s.cli.Port))
if err != nil {
return fmt.Errorf("failed to listen on" + fmt.Sprintf("%s:%d", s.cli.Host, s.cli.Port))
}
slog.Info("Listening on", "host", s.cli.Host, "port", s.cli.Port)
for {
tcpConn, err := listen.Accept()
if err != nil {
slog.Error("Failed to accept incoming connection", "err", err)
continue
}
go s.handleConn(tcpConn)
}
}
func (s *Server) handleConn(tcpConn net.Conn) {
defer func() {
if err := recover(); err != nil {
slog.Error("recovered from panic in handleConn", "err", err)
}
}()
sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, s.config)
if err != nil {
if err != io.EOF {
slog.Info("Failed to handshake", "err", err)
}
return
}
slog.Info("New SSH connection from", "address", sshConn.RemoteAddr(), "client_version", sshConn.ClientVersion())
go ssh.DiscardRequests(reqs)
go s.handleChannels(chans)
}
func (s *Server) handleChannels(chans <-chan ssh.NewChannel) {
// Service the incoming Channel channel in go routine
for newChannel := range chans {
go s.handleChannel(newChannel)
}
}
func (s *Server) handleChannel(newChannel ssh.NewChannel) {
if t := newChannel.ChannelType(); t != "session" {
_ = newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
return
}
slog.Info("Channel request", "type", newChannel.ChannelType())
if d := newChannel.ExtraData(); len(d) > 0 {
slog.Info("Channel data", "data", d)
}
connection, requests, err := newChannel.Accept()
if err != nil {
slog.Error("Could not accept channel failed", "err", err)
return
}
log.Println("Channel accepted")
go s.handleRequests(connection, requests)
}
func (s *Server) handleRequests(connection ssh.Channel, requests <-chan *ssh.Request) {
defer func() {
if err := recover(); err != nil {
slog.Error("handleRequests recovered from panic", "err", err)
}
}()
// start keep alive loop
if ka := s.cli.KeepAlive; ka > 0 {
ticking := make(chan bool, 1)
interval := time.Duration(ka) * time.Second
go s.keepAlive(connection, interval, ticking)
defer close(ticking)
}
// prepare to handle client requests
env := os.Environ()
resizes := make(chan []byte, 10)
defer close(resizes)
for req := range requests {
switch req.Type {
case "subsystem":
if string(req.Payload[4:]) == "sftp" {
req.Reply(true, nil)
server, err := sftp.NewServer(connection, sftp.WithDebug(os.Stderr))
if err != nil {
slog.Error("create SFTP server error", "err", err)
connection.Close()
return
}
err = server.Serve()
if err == io.EOF {
server.Close()
connection.Close()
return
} else if err != nil {
slog.Error("SFTP server error", "err", err)
connection.Close()
return
} else {
connection.Close()
return
}
}
case "pty-req":
termLen := req.Payload[3]
resizes <- req.Payload[termLen+4:]
req.Reply(true, nil)
case "window-change":
resizes <- req.Payload
case "env":
e := struct{ Name, Value string }{}
_ = ssh.Unmarshal(req.Payload, &e)
kv := e.Name + "=" + e.Value
slog.Info("env", "data", kv)
if s.cli.LoadEnv == "Y" {
env = appendEnv(env, kv)
}
case "shell":
if len(req.Payload) > 0 {
slog.Info("shell command ignored", "payload", req.Payload)
}
slog.Info("sshd attachShell")
err := s.attachShell(connection, env, resizes)
if err != nil {
slog.Error("exec shell", "err", err)
}
req.Reply(err == nil, []byte{})
case "exec":
if req.WantReply {
req.Reply(true, nil)
}
command := string(req.Payload[4:])
slog.Info("exec command string", "cmd", command)
ret := ExecuteForChannel(command, connection)
slog.Info("exec return", "code", ret)
connection.Close()
return
default:
slog.Info("unknown request", "type", req.Type, "want_reply", req.WantReply, "payload", req.Payload)
}
}
}
func (s *Server) keepAlive(connection ssh.Channel, interval time.Duration, ticking <-chan bool) {
defer func() {
if err := recover(); err != nil {
slog.Error("keepAlive recovered from panic", "err", err)
}
}()
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
_, err := connection.SendRequest("ping", false, nil)
if err != nil {
slog.Error("failed to send keep alive ping", "err", err)
}
slog.Info("sent keep alive ping")
case <-ticking:
return
}
}
}
func (s *Server) attachShell(connection ssh.Channel, env []string, resizes <-chan []byte) error {
defer func() {
if err := recover(); err != nil {
fmt.Printf("recovered from panic in handleRequests: %s", err)
}
}()
shell := exec.Command(s.cli.Shell)
dir, err := os.UserHomeDir()
if err == nil {
shell.Dir = dir
}
shell.Env = env
slog.Info("Session env", "data", env)
closeFunc := func() {
err := connection.Close()
if err != nil {
slog.Error("close connect failed", "err_msg", err)
return
}
slog.Info("Session closed")
}
shellPty, err := pty.Start(shell)
if err != nil {
closeFunc()
return fmt.Errorf("could not start pty (%s)\n", err)
}
//dequeue resizes
go func() {
for payload := range resizes {
w, h := parseDims(payload)
SetWindowSize(shellPty, w, h)
}
}()
//pipe session to shell and visa-versa
var once sync.Once
go func() {
_, _ = io.Copy(connection, shellPty)
once.Do(closeFunc)
}()
go func() {
_, _ = io.Copy(shellPty, connection)
once.Do(closeFunc)
}()
slog.Info("shell attached")
go func() {
if shell.Process != nil {
if ps, err := shell.Process.Wait(); err != nil && ps != nil {
slog.Error("Failed to exit shell", "err", err)
}
// shellPty.Close()
}
slog.Info("Shell terminated and Session closed")
}()
return nil
}
func (s *Server) loadCertAuthFile() (map[string]string, error) {
var tmp model.SshdCert
authorizedKeys, err := tmp.GetAuthorizedKeys()
if err != nil {
slog.Error("GetAuthorizedKeys failed", "err_msg", err.Error())
return nil, err
}
keys, err := parseKeys([]byte(authorizedKeys))
if err != nil {
slog.Error("parseKeys failed", "err_msg", err.Error())
return nil, err
}
return keys, nil
}
func (s *Server) computeSSHConfig() (*ssh.ServerConfig, error) {
sc := &ssh.ServerConfig{}
if s.cli.Shell == "" {
if runtime.GOOS == "windows" {
s.cli.Shell = "powershell"
} else {
s.cli.Shell = "sh"
}
}
p, err := exec.LookPath(s.cli.Shell)
if err != nil {
return nil, fmt.Errorf("find shell failed: %s\n", s.cli.Shell)
}
s.cli.Shell = p
slog.Info("Session shell", "shell", s.cli.Shell)
//user provided key (can generate with 'ssh-keygen -t rsa')
pri, err := ssh.ParsePrivateKey([]byte(s.cli.KeyFile))
if err != nil {
return nil, fmt.Errorf("failed to parse private key\n")
}
sc.AddHostKey(pri)
slog.Info("RSA key", "fingerprint", fingerprint(pri.PublicKey()))
// 注册账号密码认证逻辑(回调函数)
sc.PasswordCallback = func(conn ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
var sshdUsers model.SshdUser
u, err := sshdUsers.FindByNameAndPwd(conn.User(), string(pass))
if err != nil {
slog.Error("Authentication failed", "username", conn.User(), "err_msg", err)
return nil, err
}
if conn.User() == u.Name && string(pass) == u.Pwd {
slog.Info("Authentication failed with password", "username", conn.User())
return nil, nil
}
slog.Info("Authentication failed", "username", conn.User(), "password", u.Pwd)
return nil, fmt.Errorf("auth denied\n")
}
// 注册证书认证逻辑(回调函数)
sc.PublicKeyCallback = func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
ks, err := s.loadCertAuthFile()
if err != nil {
return nil, err
}
slog.Info("Authentication enabled public keys", "size", len(ks))
return nil, s.matchKeys(key, ks)
}
// 注册BannerCallback(回调函数)
sc.BannerCallback = func(conn ssh.ConnMetadata) string {
// 写入自定义的横幅信息到客户端
return fmt.Sprintf("Welcome to the Go_SSH_Server\n=>user:(%s)\n=>remote addr:(%s)\n=>local addr:(%s)\n=>client ver:(%s)\n=>server ver:(%s)\n\n",
conn.User(), conn.RemoteAddr().String(), conn.LocalAddr(),
conn.ClientVersion(), conn.ServerVersion())
}
sc.ServerVersion = "SSH-2.0-OpenSSH"
cf, err := s.cli.FindByID(1)
if err == nil {
sc.ServerVersion = cf.ServerVersion
}
return sc, nil
}
func (s *Server) matchKeys(key ssh.PublicKey, keys map[string]string) error {
if cmt, exists := keys[string(key.Marshal())]; exists {
slog.Info("User authenticated with public key", "username", cmt, "public_key", fingerprint(key))
return nil
}
slog.Error("User authentication failed with public key", "err", fingerprint(key))
return fmt.Errorf("denied\n")
}
func appendEnv(env []string, kv string) []string {
p := strings.SplitN(kv, "=", 2)
k := p[0] + "="
for i, e := range env {
if strings.HasPrefix(e, k) {
env[i] = kv
return env
}
}
return append(env, kv)
}
// parseDims extracts terminal dimensions (width x height) from the provided buffer.
func parseDims(b []byte) (uint32, uint32) {
w := binary.BigEndian.Uint32(b)
h := binary.BigEndian.Uint32(b[4:])
return w, h
}
// SetWindowSize sets the size of the given pty.
func SetWindowSize(t pty.Pty, w, h uint32) {
ws := &pty.Winsize{Rows: uint16(h), Cols: uint16(w)}
_ = pty.Setsize(t, ws)
}
func generateKey(seed string) ([]byte, error) {
var r io.Reader
if seed == "" {
r = rand.Reader
} else {
r = newDetermRand([]byte(seed))
}
privateKey, err := rsa.GenerateKey(r, 2048)
if err != nil {
return nil, err
}
err = privateKey.Validate()
if err != nil {
return nil, err
}
b := x509.MarshalPKCS1PrivateKey(privateKey)
return pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: b}), nil
}
func parseKeys(b []byte) (map[string]string, error) {
lines := bytes.Split(b, []byte("\n"))
//parse each line
keys := map[string]string{}
for _, l := range lines {
if key, cmt, _, _, err := ssh.ParseAuthorizedKey(l); err == nil {
keys[string(key.Marshal())] = cmt
}
}
//ensure we got something
if len(keys) == 0 {
return nil, fmt.Errorf("no keys found\n")
}
return keys, nil
}
func fingerprint(k ssh.PublicKey) string {
bytesData := sha256.Sum256(k.Marshal())
b64 := base64.StdEncoding.EncodeToString(bytesData[:])
if strings.HasSuffix(b64, "=") {
b64 = strings.TrimSuffix(b64, "=") + "."
}
return "SHA256:" + b64
}
func newDetermRand(seed []byte) io.Reader {
const randSize = 2048
var out []byte
//strengthen seed
var next = seed
for i := 0; i < randSize; i++ {
next, out = hash(next)
}
return &determRand{
next: next,
out: out,
}
}
type determRand struct {
next, out []byte
}
func (d *determRand) Read(b []byte) (int, error) {
l := len(b)
//HACK: combat https://golang.org/src/crypto/rsa/rsa.go#L257
if l == 1 {
return 1, nil
}
n := 0
for n < l {
next, out := hash(d.next)
n += copy(b[n:], out)
d.next = next
}
return n, nil
}
func hash(input []byte) (next []byte, output []byte) {
nextout := sha512.Sum512(input)
return nextout[:sha512.Size/2], nextout[sha512.Size/2:]
}
// ExecuteForChannel Execute a process for the channel.
func ExecuteForChannel(shellCmd string, ch ssh.Channel) uint32 {
var err error
// Windows 下特殊处理命令
var proc *exec.Cmd
if runtime.GOOS == "windows" {
// 使用 Command 创建命令,并正确处理参数
proc = exec.Command("powershell", "-NoProfile", "-NonInteractive", "-Command",
"[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; $OutputEncoding = [System.Text.Encoding]::UTF8; chcp 65001 | Out-Null; "+shellCmd)
} else {
proc = exec.Command("sh", "-c", shellCmd)
}
proc.Env = append(os.Environ(), "LANG=zh_CN.UTF-8", "LC_ALL=zh_CN.UTF-8")
exe, err := os.Executable()
if err != nil {
slog.Error("get os.Executable error", "err", err)
}
slog.Info("os.Executable() exe:", "path", exe)
dir := filepath.Dir(exe)
slog.Info("exec dir info:", "path", dir)
proc.Dir = dir
if userInfo, err := user.Current(); err == nil {
proc.Dir = userInfo.HomeDir
}
stdin, err := proc.StdinPipe()
if err != nil {
slog.Error("create pipe failed", "err", err)
return 1
}
go func() {
defer stdin.Close()
_, _ = io.Copy(stdin, ch)
}()
proc.Stdout = ch
proc.Stderr = ch.Stderr()
// 执行命令
err = proc.Start()
if err != nil {
slog.Error("start command failed", "err", err)
_, _ = ch.Write([]byte(fmt.Sprintf("start command failed: %v\n", err)))
return 1
}
// 等待命令完成
err = proc.Wait()
if err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
slog.Error("wait command failed", "exit code", exitErr.ExitCode())
return uint32(exitErr.ExitCode())
}
slog.Error("exec command failed", "err", err)
_, _ = ch.Write([]byte(fmt.Sprintf("exec command failed: %v\n", err)))
return 1
}
slog.Info("exec command success")
return 0
}
func startSshServer() {
status := <-isStartSshd
if status {
slog.Info("start sshd server")
}
var sshdConf model.SshdConf
conf, err := sshdConf.FindByID(1)
if err != nil {
slog.Error("find sshd server config failed", "err_msg", err)
return
}
slog.Info("find sshd server config", "conf", conf)
s, err := NewServer(&conf)
if err != nil {
slog.Error("NewServer failed", "err_msg", err)
return
}
slog.Info("start sshd server")
err = s.Start()
if err != nil {
slog.Error("sshd server start failed", "err_msg", err)
return
}
}
var isStartSshd = make(chan bool)
func InitSshServer() {
go startSshServer()
slog.Info("exec sshd init func")
}
================================================
FILE: gossh/app/service/sshd_user.go
================================================
package service
import (
"gossh/app/model"
"gossh/gin"
"log/slog"
"strconv"
)
func SshdUserCreate(c *gin.Context) {
var sshdUser model.SshdUser
if err := c.ShouldBind(&sshdUser); err != nil {
slog.Error("UserCreate 绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
err := sshdUser.Create(&sshdUser)
if err != nil {
slog.Error("创建用户错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "创建用户错误"})
return
}
SshdUserFindAll(c)
}
func CheckSshdUserNameExists(c *gin.Context) {
type Name struct {
Name string `form:"name" binding:"required,min=1,max=128" json:"name"`
}
var name Name
if err := c.ShouldBind(&name); err != nil {
slog.Error("绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
var sshdUser model.SshdUser
tmp, err := sshdUser.FindByName(name.Name)
if err != nil {
slog.Error("FindByName错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "获取用户信息错误"})
return
}
if tmp.ID != 0 {
c.JSON(200, gin.H{"code": 4, "msg": "用户名已经存存在"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok"})
return
}
func SshdUserFindByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
var sshdUser model.SshdUser
data, err := sshdUser.FindByID(uint(id))
if err != nil {
slog.Error("FindByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "获取用户信息错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func SshdUserFindAll(c *gin.Context) {
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10000"))
if err != nil {
slog.Error("获取limit错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取limit错误"})
return
}
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
if err != nil {
slog.Error("获取offset错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 2, "msg": "获取offset错误"})
return
}
var sshdUser model.SshdUser
data, err := sshdUser.FindAll(limit, offset)
if err != nil {
slog.Error("user.FindAl错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 4, "msg": "获取用户信息错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func SshdUserUpdateById(c *gin.Context) {
var sshdUser model.SshdUser
if err := c.ShouldBind(&sshdUser); err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
err := sshdUser.UpdateById(sshdUser.ID, &sshdUser)
if err != nil {
slog.Error("UpdateById错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 5, "msg": "更新用户错误"})
return
}
SshdUserFindAll(c)
}
func SshdUserDeleteById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
var sshdUser model.SshdUser
err = sshdUser.DeleteByID(uint(id))
if err != nil {
slog.Error("user.DeleteByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 5, "msg": "删除用户错误"})
return
}
SshdUserFindAll(c)
}
================================================
FILE: gossh/app/service/sys_init.go
================================================
package service
import (
"gossh/app/config"
"gossh/app/model"
"gossh/gin"
"log/slog"
"os/exec"
"runtime"
)
func GetRunConf(c *gin.Context) {
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": config.DefaultConfig})
}
func SetRunConf(c *gin.Context) {
if config.DefaultConfig.IsInit {
c.JSON(200, gin.H{"code": 1, "msg": "已经初始化"})
return
}
var appConfig config.AppConfig
if err := c.ShouldBind(&appConfig); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
err := config.RewriteConfig(appConfig)
if err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": config.DefaultConfig})
}
func GetIsInit(c *gin.Context) {
c.JSON(200, gin.H{
"code": 0, "msg": "ok", "data": map[string]any{
"is_init": config.DefaultConfig.IsInit,
},
})
}
type InitConfig struct {
DbConnConf
JwtSecret string `json:"jwt_secret" binding:"required,min=1,max=128"`
SessionSecret string `json:"session_secret" binding:"required,min=1,max=128"`
Username string `json:"username" binding:"required,min=1,max=63"`
Password string `json:"password" binding:"required,min=1,max=63"`
SshdHost string `json:"sshd_host" binding:"required,min=1,max=127"`
SshdPort uint16 `json:"sshd_port" binding:"required,gte=1,lte=65535"`
SshdUser string `json:"sshd_user" binding:"required,min=1,max=63"`
SshdPwd string `json:"sshd_pwd" binding:"required,min=1,max=63"`
}
func SysInit(c *gin.Context) {
var initConf InitConfig
if err := c.ShouldBind(&initConf); err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
// 1.检查系统是否已经初始化
if config.DefaultConfig.IsInit {
c.JSON(200, gin.H{"code": 1, "msg": "系统已经初始化"})
return
}
// 2.数据库连接检查
dbConf := DbConnConf{
DbDsn: initConf.DbDsn,
DbType: initConf.DbType,
}
err := DbConnTestCheck(dbConf)
if err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error()})
return
}
// 3.数据库表迁移
err = model.DbMigrate(initConf.DbType, initConf.DbDsn)
if err != nil {
c.JSON(200, gin.H{"code": 1, "msg": err.Error(), "data": "执行数据库迁移错误"})
return
}
// root 用户过期时间
dateTime, _ := model.NewDateTime("2099-12-31 00:00:00")
// 4.创建初始化用户
var user = model.WebUser{
ID: 0,
Name: initConf.Username,
Pwd: initConf.Password,
DescInfo: "管理员",
IsAdmin: "Y",
IsEnable: "Y",
IsRoot: "Y",
ExpiryAt: dateTime,
}
err = user.Create(&user)
if err != nil {
c.JSON(200, gin.H{"code": 3, "msg": err.Error(), "data": "初始化创建账号错误"})
return
}
// 5.设置默认网络策略
var policyConf = model.PolicyConf{
NetPolicy: "N",
}
err = policyConf.Create(&policyConf)
if err != nil {
c.JSON(200, gin.H{"code": 3, "msg": err.Error(), "data": "初始化网络策略错误"})
return
}
privateKey, err := generateKey("webssh")
if err != nil {
slog.Error("failed to generate private key")
c.JSON(200, gin.H{"code": 3, "msg": err.Error(), "data": "初始化生成SSHD私钥错误"})
return
}
var shell = "sh"
if runtime.GOOS == "windows" {
shell = "powershell"
} else {
sh, err := exec.LookPath("bash")
if err == nil {
slog.Info("init find shell is bash\n")
shell = sh
}
}
// 6.初始化sshd服务端配置
var sshdConf = model.SshdConf{
ID: 1,
Name: "init",
Host: initConf.SshdHost,
Port: initConf.SshdPort,
Shell: shell,
KeyFile: string(privateKey),
KeySeed: "webssh",
KeepAlive: 60,
LoadEnv: "Y",
AuthType: "all",
ServerVersion: "SSH-2.0-OpenSSH",
}
err = sshdConf.Create(&sshdConf)
if err != nil {
c.JSON(200, gin.H{"code": 3, "msg": err.Error(), "data": "初始化SSHD服务端配置错误"})
return
}
// 7.初始化sshd服务端账号
var sshdUser = model.SshdUser{
ID: 1,
Name: initConf.SshdUser,
Pwd: initConf.SshdPwd,
DescInfo: "服务器初始化账号",
IsEnable: "Y",
WorkDir: "",
ExpiryAt: dateTime,
}
err = sshdUser.Create(&sshdUser)
if err != nil {
c.JSON(200, gin.H{"code": 3, "msg": err.Error(), "data": "初始化SSHD服务端账号错误"})
return
}
// 8.覆盖默认配置
var defConf = config.DefaultConfig
defConf.IsInit = true
defConf.DbType = initConf.DbType
defConf.DbDsn = initConf.DbDsn
defConf.JwtSecret = initConf.JwtSecret
defConf.SessionSecret = initConf.SessionSecret
err = config.RewriteConfig(defConf)
if err != nil {
c.JSON(200, gin.H{"code": 2, "msg": err.Error(), "data": "写入配置错误"})
return
}
// 9.创建默认连接
var sshConf = model.SshConf{
Uid: 1,
Name: "self_sshd",
Address: "127.0.0.1",
User: initConf.SshdUser,
Pwd: initConf.SshdPwd,
AuthType: "pwd",
NetType: "tcp4",
CertData: "",
CertPwd: "",
Port: initConf.SshdPort,
FontSize: 16,
Background: "#000000",
Foreground: "#FFFFFF",
CursorColor: "#FFFFFF",
FontFamily: "Courier",
CursorStyle: "block",
Shell: "sh",
PtyType: "xterm-256color",
InitCmd: "",
InitBanner: "# https://github.com/o8oo8o/WebSSH",
}
err = sshConf.Create(&sshConf)
if err != nil {
c.JSON(200, gin.H{"code": 3, "msg": err.Error(), "data": "初始化创建默认连接错误"})
return
}
isStartSshd <- true
c.JSON(200, gin.H{"code": 0, "msg": "系统初始化完成"})
}
================================================
FILE: gossh/app/service/web_user.go
================================================
package service
import (
"gossh/app/config"
"gossh/app/middleware"
"gossh/app/model"
"gossh/app/utils"
"gossh/gin"
"log/slog"
"net/http"
"strconv"
"time"
)
func UserCreate(c *gin.Context) {
var user model.WebUser
if err := c.ShouldBind(&user); err != nil {
slog.Error("UserCreate 绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
var err error
user.IsRoot = "N"
err = user.Create(&user)
if err != nil {
slog.Error("创建用户错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "创建用户错误"})
return
}
UserFindAll(c)
}
func ModifyPasswd(c *gin.Context) {
type password struct {
Pwd string `form:"pwd" binding:"required,min=1,max=64" json:"pwd"`
}
var pwd password
if err := c.ShouldBind(&pwd); err != nil {
slog.Error("绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
uid := c.GetUint("uid")
var tmp model.WebUser
user, err := tmp.FindByID(uid)
if err != nil {
slog.Error("FindByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 2, "msg": "获取用户信息错误"})
return
}
user.Pwd = pwd.Pwd
err = user.UpdatePassword(uid, &user)
if err != nil {
slog.Error("UpdatePassword错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "更新用户密码错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "更新密码成功"})
}
func CheckUserNameExists(c *gin.Context) {
type Name struct {
Name string `form:"name" binding:"required,min=1,max=128" json:"name"`
}
var name Name
if err := c.ShouldBind(&name); err != nil {
slog.Error("绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
var user model.WebUser
tmp, err := user.FindByName(name.Name)
if err != nil {
slog.Error("FindByName错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "获取用户信息错误"})
return
}
if tmp.ID != 0 {
c.JSON(200, gin.H{"code": 4, "msg": "用户名已经存存在"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok"})
return
}
func UserFindByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
var user model.WebUser
data, err := user.FindByID(uint(id))
if err != nil {
slog.Error("FindByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "获取用户信息错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func UserFindAll(c *gin.Context) {
limit, err := strconv.Atoi(c.DefaultQuery("limit", "10000"))
if err != nil {
slog.Error("获取limit错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取limit错误"})
return
}
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
if err != nil {
slog.Error("获取offset错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 2, "msg": "获取offset错误"})
return
}
var user model.WebUser
data, err := user.FindAll(limit, offset)
if err != nil {
slog.Error("user.FindAl错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 4, "msg": "获取用户信息错误"})
return
}
c.JSON(200, gin.H{"code": 0, "msg": "ok", "data": data})
}
func UserUpdateById(c *gin.Context) {
var user model.WebUser
if err := c.ShouldBind(&user); err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
tmpUser, err := user.FindByID(user.ID)
if err != nil {
slog.Error("FindByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "获取用户信息错误"})
return
}
// 防止越权操作
if tmpUser.IsRoot == "N" {
user.IsRoot = "N"
}
if tmpUser.IsRoot == "Y" {
c.JSON(200, gin.H{"code": 4, "msg": "内置Root用户不能更新"})
return
}
err = user.UpdateById(user.ID, &user)
if err != nil {
slog.Error("UpdateById错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 5, "msg": "更新用户错误"})
return
}
UserFindAll(c)
}
func UserDeleteById(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
slog.Error("获取ID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "获取ID错误"})
return
}
var user model.WebUser
tmpUser, err := user.FindByID(uint(id))
if err != nil {
slog.Error("user.FindByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 3, "msg": "获取用户信息错误"})
return
}
// 防止越权操作
if tmpUser.IsRoot == "Y" {
c.JSON(200, gin.H{"code": 4, "msg": "内置Root用户不能删除"})
return
}
err = user.DeleteByID(uint(id))
if err != nil {
slog.Error("user.DeleteByID错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 5, "msg": "删除用户错误"})
return
}
UserFindAll(c)
}
func UserLogin(c *gin.Context) {
if !config.DefaultConfig.IsInit {
slog.Warn("system no init")
c.JSON(401, gin.H{"code": 401, "msg": "请对系统进行初始化"})
return
}
type Param struct {
Name string `form:"name" binding:"required,min=1,max=64" json:"name"`
Pwd string `form:"pwd" binding:"required,min=1,max=64" json:"pwd"`
}
var loginAudit model.LoginAudit
var param Param
audit := model.LoginAudit{
ClientIp: c.ClientIP(),
UserAgent: utils.TruncateString(c.Request.UserAgent(), 500),
ErrMsg: "请求参数错误",
IsSuccess: "N",
OccurAt: model.DateTime(time.Now()),
}
if err := c.ShouldBind(¶m); err != nil {
audit.Name = utils.TruncateString(param.Name, 60)
audit.Pwd = utils.TruncateString(param.Pwd, 60)
_ = loginAudit.Create(&audit)
slog.Error("绑定数据错误", "err_msg", err.Error())
c.JSON(200, gin.H{"code": 1, "msg": "输入数据不合法"})
return
}
audit.Name = utils.TruncateString(param.Name, 60)
audit.Pwd = utils.TruncateString(param.Pwd, 60)
var user model.WebUser
u, err := user.FindByNameAndPwd(param.Name, param.Pwd)
if err != nil {
audit.ErrMsg = "账号密码错误"
_ = loginAudit.Create(&audit)
slog.Error("账号密码错误", "err_msg", err.Error())
c.JSON(401, gin.H{"code": 2, "msg": "账号密码错误"})
return
}
if u.IsEnable == "N" {
audit.ErrMsg = "账号已禁用"
_ = loginAudit.Create(&audit)
c.JSON(401, gin.H{"code": 3, "msg": "账号已禁用"})
return
}
if u.ExpiryAt.ToTime().Unix() < time.Now().Unix() {
audit.ErrMsg = "账号已过期"
_ = loginAudit.Create(&audit)
c.JSON(401, gin.H{"code": 4, "msg": "账号已过期"})
return
}
tokenString, err := middleware.GenerateToken(u.ID)
if err != nil {
audit.ErrMsg = "生成Token错误"
_ = loginAudit.Create(&audit)
c.JSON(401, gin.H{"code": 5, "msg": err.Error()})
return
}
audit.Name = param.Name
audit.Pwd = "*"
audit.ErrMsg = "*"
audit.IsSuccess = "Y"
_ = loginAudit.Create(&audit)
c.JSON(http.StatusOK, gin.H{
"code": 0,
"token": tokenString,
"msg": "登录成功",
"is_root": u.IsRoot,
"is_admin": u.IsAdmin,
"user_name": u.Name,
"user_desc": u.DescInfo,
"user_expiry_at": u.ExpiryAt.String(),
})
}
================================================
FILE: gossh/app/utils/crypto.go
================================================
package utils
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"io"
"log/slog"
"strings"
)
func AesEncrypt(orig string, key string) (string, error) {
orig = strings.TrimSpace(orig)
defer func() {
if err := recover(); err != nil {
slog.Error("AES加密错误", "err_msg", err)
}
}()
if len(orig) == 0 {
return "", nil
}
if len(key) != 32 {
return "", errors.New("加密需要的key长度错误")
}
// 转成字节数组
origData := []byte(orig)
k := []byte(key)
// 分组秘钥
block, err := aes.NewCipher(k)
if err != nil {
return "", err
}
// 获取秘钥块的长度
blockSize := block.BlockSize()
//补码
PKCS7Padding := func(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padText...)
}
origData = PKCS7Padding(origData, blockSize)
// 加密模式
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
// 创建数组
crypt := make([]byte, len(origData))
// 加密
blockMode.CryptBlocks(crypt, origData)
return base64.StdEncoding.EncodeToString(crypt), nil
}
func AesDecrypt(crypt string, key string) (string, error) {
crypt = strings.TrimSpace(crypt)
defer func() {
if err := recover(); err != nil {
slog.Error("AES解密错误", "err_msg", err)
}
}()
if len(crypt) == 0 {
return "", nil
}
if len(crypt) < 1 || len(key) != 32 {
return "", errors.New("解密需要的key长度错误")
}
// 转成字节数组
cryptByte, _ := base64.StdEncoding.DecodeString(crypt)
k := []byte(key)
// 分组秘钥
block, err := aes.NewCipher(k)
if err != nil {
return "", err
}
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 加密模式
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
// 创建数组
orig := make([]byte, len(cryptByte))
// 解密
blockMode.CryptBlocks(orig, cryptByte)
// 去补全码
PKCS7UnPadding := func(origData []byte) []byte {
length := len(origData)
unPadding := int(origData[length-1])
return origData[:(length - unPadding)]
}
orig = PKCS7UnPadding(orig)
return string(orig), nil
}
func EncryptString(plaintext, key string) (string, error) {
plaintext = strings.TrimSpace(plaintext)
defer func() {
if err := recover(); err != nil {
slog.Error("AES加密错误", "err_msg", err)
}
}()
if len(plaintext) == 0 {
return "", nil
}
if len(key) != 32 {
return "", errors.New("加密需要的key长度错误")
}
// 创建 cipher
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
// 创建 GCM 模式
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
// 创建 nonce
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return "", err
}
// 加密
ciphertext := gcm.Seal(nonce, nonce, []byte(plaintext), nil)
// 返回 base64 编码的结果
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
func DecryptString(encrypted, key string) (string, error) {
encrypted = strings.TrimSpace(encrypted)
defer func() {
if err := recover(); err != nil {
slog.Error("AES解密错误", "err_msg", err)
}
}()
if len(encrypted) == 0 {
return "", nil
}
if len(encrypted) < 1 || len(key) != 32 {
return "", errors.New("解密需要的key长度错误")
}
// 解码 base64
ciphertext, err := base64.StdEncoding.DecodeString(encrypted)
if err != nil {
return "", err
}
// 创建 cipher
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
// 创建 GCM 模式
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
// 提取 nonce
if len(ciphertext) < gcm.NonceSize() {
return "", fmt.Errorf("ciphertext too short")
}
nonce, ciphertext := ciphertext[:gcm.NonceSize()], ciphertext[gcm.NonceSize():]
// 解密
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return "", err
}
return string(plaintext), nil
}
================================================
FILE: gossh/app/utils/utils.go
================================================
package utils
import (
"math/rand"
"time"
"unicode/utf8"
)
// RandString 生成指定长度随机字符串
func RandString(length int) string {
str := "0123456789abcdefghijklmnopqrstuvwxyz"
data := []byte(str)
var result []byte
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < length; i++ {
result = append(result, data[r.Intn(len(data))])
}
return string(result)
}
func TruncateString(s string, length int) string {
if utf8.RuneCountInString(s) <= length {
return s
}
runes := []rune(s)
if length < 1 {
return ""
}
return string(runes[:length])
}
================================================
FILE: gossh/crypto/blowfish/block.go
================================================
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package blowfish
// getNextWord returns the next big-endian uint32 value from the byte slice
// at the given position in a circular manner, updating the position.
func getNextWord(b []byte, pos *int) uint32 {
var w uint32
j := *pos
for i := 0; i < 4; i++ {
w = w<<8 | uint32(b[j])
j++
if j >= len(b) {
j = 0
}
}
*pos = j
return w
}
// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
// pi and substitution tables for calls to Encrypt. This is used, primarily,
// by the bcrypt package to reuse the Blowfish key schedule during its
// set up. It's unlikely that you need to use this directly.
func ExpandKey(key []byte, c *Cipher) {
j := 0
for i := 0; i < 18; i++ {
// Using inlined getNextWord for performance.
var d uint32
for k := 0; k < 4; k++ {
d = d<<8 | uint32(key[j])
j++
if j >= len(key) {
j = 0
}
}
c.p[i] ^= d
}
var l, r uint32
for i := 0; i < 18; i += 2 {
l, r = encryptBlock(l, r, c)
c.p[i], c.p[i+1] = l, r
}
for i := 0; i < 256; i += 2 {
l, r = encryptBlock(l, r, c)
c.s0[i], c.s0[i+1] = l, r
}
for i := 0; i < 256; i += 2 {
l, r = encryptBlock(l, r, c)
c.s1[i], c.s1[i+1] = l, r
}
for i := 0; i < 256; i += 2 {
l, r = encryptBlock(l, r, c)
c.s2[i], c.s2[i+1] = l, r
}
for i := 0; i < 256; i += 2 {
l, r = encryptBlock(l, r, c)
c.s3[i], c.s3[i+1] = l, r
}
}
// This is similar to ExpandKey, but folds the salt during the key
// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
// and specializing it here is useful.
func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
j := 0
for i := 0; i < 18; i++ {
c.p[i] ^= getNextWord(key, &j)
}
j = 0
var l, r uint32
for i := 0; i < 18; i += 2 {
l ^= getNextWord(salt, &j)
r ^= getNextWord(salt, &j)
l, r = encryptBlock(l, r, c)
c.p[i], c.p[i+1] = l, r
}
for i := 0; i < 256; i += 2 {
l ^= getNextWord(salt, &j)
r ^= getNextWord(salt, &j)
l, r = encryptBlock(l, r, c)
c.s0[i], c.s0[i+1] = l, r
}
for i := 0; i < 256; i += 2 {
l ^= getNextWord(salt, &j)
r ^= getNextWord(salt, &j)
l, r = encryptBlock(l, r, c)
c.s1[i], c.s1[i+1] = l, r
}
for i := 0; i < 256; i += 2 {
l ^= getNextWord(salt, &j)
r ^= getNextWord(salt, &j)
l, r = encryptBlock(l, r, c)
c.s2[i], c.s2[i+1] = l, r
}
for i := 0; i < 256; i += 2 {
l ^= getNextWord(salt, &j)
r ^= getNextWord(salt, &j)
l, r = encryptBlock(l, r, c)
c.s3[i], c.s3[i+1] = l, r
}
}
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
xl, xr := l, r
xl ^= c.p[0]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
xr ^= c.p[17]
return xr, xl
}
func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
xl, xr := l, r
xl ^= c.p[17]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
xr ^= c.p[0]
return xr, xl
}
================================================
FILE: gossh/crypto/blowfish/cipher.go
================================================
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
//
// Blowfish is a legacy cipher and its short block size makes it vulnerable to
// birthday bound attacks (see https://sweet32.info). It should only be used
// where compatibility with legacy systems, not security, is the goal.
//
// Deprecated: any new system should use AES (from crypto/aes, if necessary in
// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
// golang.org/x/crypto/chacha20poly1305).
package blowfish // import "golang.org/x/crypto/blowfish"
// The code is a port of Bruce Schneier's C implementation.
// See https://www.schneier.com/blowfish.html.
import "strconv"
// The Blowfish block size in bytes.
const BlockSize = 8
// A Cipher is an instance of Blowfish encryption using a particular key.
type Cipher struct {
p [18]uint32
s0, s1, s2, s3 [256]uint32
}
type KeySizeError int
func (k KeySizeError) Error() string {
return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
}
// NewCipher creates and returns a Cipher.
// The key argument should be the Blowfish key, from 1 to 56 bytes.
func NewCipher(key []byte) (*Cipher, error) {
var result Cipher
if k := len(key); k < 1 || k > 56 {
return nil, KeySizeError(k)
}
initCipher(&result)
ExpandKey(key, &result)
return &result, nil
}
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
// sufficient and desirable. For bcrypt compatibility, the key can be over 56
// bytes.
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
if len(salt) == 0 {
return NewCipher(key)
}
var result Cipher
if k := len(key); k < 1 {
return nil, KeySizeError(k)
}
initCipher(&result)
expandKeyWithSalt(key, salt, &result)
return &result, nil
}
// BlockSize returns the Blowfish block size, 8 bytes.
// It is necessary to satisfy the Block interface in the
// package "crypto/cipher".
func (c *Cipher) BlockSize() int { return BlockSize }
// Encrypt encrypts the 8-byte buffer src using the key k
// and stores the result in dst.
// Note that for amounts of data larger than a block,
// it is not safe to just call Encrypt on successive blocks;
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
func (c *Cipher) Encrypt(dst, src []byte) {
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
l, r = encryptBlock(l, r, c)
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
}
// Decrypt decrypts the 8-byte buffer src using the key k
// and stores the result in dst.
func (c *Cipher) Decrypt(dst, src []byte) {
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
l, r = decryptBlock(l, r, c)
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
}
func initCipher(c *Cipher) {
copy(c.p[0:], p[0:])
copy(c.s0[0:], s0[0:])
copy(c.s1[0:], s1[0:])
copy(c.s2[0:], s2[0:])
copy(c.s3[0:], s3[0:])
}
================================================
FILE: gossh/crypto/blowfish/const.go
================================================
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The startup permutation array and substitution boxes.
// They are the hexadecimal digits of PI; see:
// https://www.schneier.com/code/constants.txt.
package blowfish
var s0 = [256]uint32{
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
}
var s1 = [256]uint32{
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
}
var s2 = [256]uint32{
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
}
var s3 = [256]uint32{
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
}
var p = [18]uint32{
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
}
================================================
FILE: gossh/crypto/chacha20/chacha_arm64.go
================================================
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build gc && !purego
package chacha20
const bufSize = 256
//go:noescape
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
}
================================================
FILE: gossh/crypto/chacha20/chacha_arm64.s
================================================
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build gc && !purego
#include "textflag.h"
#define NUM_ROUNDS 10
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
MOVD dst+0(FP), R1
MOVD src+24(FP), R2
MOVD src_len+32(FP), R3
MOVD key+48(FP), R4
MOVD nonce+56(FP), R6
MOVD counter+64(FP), R7
MOVD $·constants(SB), R10
MOVD $·incRotMatrix(SB), R11
MOVW (R7), R20
AND $~255, R3, R13
ADD R2, R13, R12 // R12 for block end
AND $255, R3, R13
loop:
MOVD $NUM_ROUNDS, R21
VLD1 (R11), [V30.S4, V31.S4]
// load contants
// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4]
WORD $0x4D60E940
// load keys
// VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4]
WORD $0x4DFFE884
// VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4]
WORD $0x4DFFE888
SUB $32, R4
// load counter + nonce
// VLD1R (R7), [V12.S4]
WORD $0x4D40C8EC
// VLD3R (R6), [V13.S4, V14.S4, V15.S4]
WORD $0x4D40E8CD
// update counter
VADD V30.S4, V12.S4, V12.S4
chacha:
// V0..V3 += V4..V7
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 16)
VADD V0.S4, V4.S4, V0.S4
VADD V1.S4, V5.S4, V1.S4
VADD V2.S4, V6.S4, V2.S4
VADD V3.S4, V7.S4, V3.S4
VEOR V12.B16, V0.B16, V12.B16
VEOR V13.B16, V1.B16, V13.B16
VEOR V14.B16, V2.B16, V14.B16
VEOR V15.B16, V3.B16, V15.B16
VREV32 V12.H8, V12.H8
VREV32 V13.H8, V13.H8
VREV32 V14.H8, V14.H8
VREV32 V15.H8, V15.H8
// V8..V11 += V12..V15
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 12)
VADD V8.S4, V12.S4, V8.S4
VADD V9.S4, V13.S4, V9.S4
VADD V10.S4, V14.S4, V10.S4
VADD V11.S4, V15.S4, V11.S4
VEOR V8.B16, V4.B16, V16.B16
VEOR V9.B16, V5.B16, V17.B16
VEOR V10.B16, V6.B16, V18.B16
VEOR V11.B16, V7.B16, V19.B16
VSHL $12, V16.S4, V4.S4
VSHL $12, V17.S4, V5.S4
VSHL $12, V18.S4, V6.S4
VSHL $12, V19.S4, V7.S4
VSRI $20, V16.S4, V4.S4
VSRI $20, V17.S4, V5.S4
VSRI $20, V18.S4, V6.S4
VSRI $20, V19.S4, V7.S4
// V0..V3 += V4..V7
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 8)
VADD V0.S4, V4.S4, V0.S4
VADD V1.S4, V5.S4, V1.S4
VADD V2.S4, V6.S4, V2.S4
VADD V3.S4, V7.S4, V3.S4
VEOR V12.B16, V0.B16, V12.B16
VEOR V13.B16, V1.B16, V13.B16
VEOR V14.B16, V2.B16, V14.B16
VEOR V15.B16, V3.B16, V15.B16
VTBL V31.B16, [V12.B16], V12.B16
VTBL V31.B16, [V13.B16], V13.B16
VTBL V31.B16, [V14.B16], V14.B16
VTBL V31.B16, [V15.B16], V15.B16
// V8..V11 += V12..V15
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 7)
VADD V12.S4, V8.S4, V8.S4
VADD V13.S4, V9.S4, V9.S4
VADD V14.S4, V10.S4, V10.S4
VADD V15.S4, V11.S4, V11.S4
VEOR V8.B16, V4.B16, V16.B16
VEOR V9.B16, V5.B16, V17.B16
VEOR V10.B16, V6.B16, V18.B16
VEOR V11.B16, V7.B16, V19.B16
VSHL $7, V16.S4, V4.S4
VSHL $7, V17.S4, V5.S4
VSHL $7, V18.S4, V6.S4
VSHL $7, V19.S4, V7.S4
VSRI $25, V16.S4, V4.S4
VSRI $25, V17.S4, V5.S4
VSRI $25, V18.S4, V6.S4
VSRI $25, V19.S4, V7.S4
// V0..V3 += V5..V7, V4
// V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16)
VADD V0.S4, V5.S4, V0.S4
VADD V1.S4, V6.S4, V1.S4
VADD V2.S4, V7.S4, V2.S4
VADD V3.S4, V4.S4, V3.S4
VEOR V15.B16, V0.B16, V15.B16
VEOR V12.B16, V1.B16, V12.B16
VEOR V13.B16, V2.B16, V13.B16
VEOR V14.B16, V3.B16, V14.B16
VREV32 V12.H8, V12.H8
VREV32 V13.H8, V13.H8
VREV32 V14.H8, V14.H8
VREV32 V15.H8, V15.H8
// V10 += V15; V5 <<<= ((V10 XOR V5), 12)
// ...
VADD V15.S4, V10.S4, V10.S4
VADD V12.S4, V11.S4, V11.S4
VADD V13.S4, V8.S4, V8.S4
VADD V14.S4, V9.S4, V9.S4
VEOR V10.B16, V5.B16, V16.B16
VEOR V11.B16, V6.B16, V17.B16
VEOR V8.B16, V7.B16, V18.B16
VEOR V9.B16, V4.B16, V19.B16
VSHL $12, V16.S4, V5.S4
VSHL $12, V17.S4, V6.S4
VSHL $12, V18.S4, V7.S4
VSHL $12, V19.S4, V4.S4
VSRI $20, V16.S4, V5.S4
VSRI $20, V17.S4, V6.S4
VSRI $20, V18.S4, V7.S4
VSRI $20, V19.S4, V4.S4
// V0 += V5; V15 <<<= ((V0 XOR V15), 8)
// ...
VADD V5.S4, V0.S4, V0.S4
VADD V6.S4, V1.S4, V1.S4
VADD V7.S4, V2.S4, V2.S4
VADD V4.S4, V3.S4, V3.S4
VEOR V0.B16, V15.B16, V15.B16
VEOR V1.B16, V12.B16, V12.B16
VEOR V2.B16, V13.B16, V13.B16
VEOR V3.B16, V14.B16, V14.B16
VTBL V31.B16, [V12.B16], V12.B16
VTBL V31.B16, [V13.B16], V13.B16
VTBL V31.B16, [V14.B16], V14.B16
VTBL V31.B16, [V15.B16], V15.B16
// V10 += V15; V5 <<<= ((V10 XOR V5), 7)
// ...
VADD V15.S4, V10.S4, V10.S4
VADD V12.S4, V11.S4, V11.S4
VADD V13.S4, V8.S4, V8.S4
VADD V14.S4, V9.S4, V9.S4
VEOR V10.B16, V5.B16, V16.B16
VEOR V11.B16, V6.B16, V17.B16
VEOR V8.B16, V7.B16, V18.B16
VEOR V9.B16, V4.B16, V19.B16
VSHL $7, V16.S4, V5.S4
VSHL $7, V17.S4, V6.S4
VSHL $7, V18.S4, V7.S4
VSHL $7, V19.S4, V4.S4
VSRI $25, V16.S4, V5.S4
VSRI $25, V17.S4, V6.S4
VSRI $25, V18.S4, V7.S4
VSRI $25, V19.S4, V4.S4
SUB $1, R21
CBNZ R21, chacha
// VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4]
WORD $0x4D60E950
// VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4]
WORD $0x4DFFE894
VADD V30.S4, V12.S4, V12.S4
VADD V16.S4, V0.S4, V0.S4
VADD V17.S4, V1.S4, V1.S4
VADD V18.S4, V2.S4, V2.S4
VADD V19.S4, V3.S4, V3.S4
// VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4]
WORD $0x4DFFE898
// restore R4
SUB $32, R4
// load counter + nonce
// VLD1R (R7), [V28.S4]
WORD $0x4D40C8FC
// VLD3R (R6), [V29.S4, V30.S4, V31.S4]
WORD $0x4D40E8DD
VADD V20.S4, V4.S4, V4.S4
VADD V21.S4, V5.S4, V5.S4
VADD V22.S4, V6.S4, V6.S4
VADD V23.S4, V7.S4, V7.S4
VADD V24.S4, V8.S4, V8.S4
VADD V25.S4, V9.S4, V9.S4
VADD V26.S4, V10.S4, V10.S4
VADD V27.S4, V11.S4, V11.S4
VADD V28.S4, V12.S4, V12.S4
VADD V29.S4, V13.S4, V13.S4
VADD V30.S4, V14.S4, V14.S4
VADD V31.S4, V15.S4, V15.S4
VZIP1 V1.S4, V0.S4, V16.S4
VZIP2 V1.S4, V0.S4, V17.S4
VZIP1 V3.S4, V2.S4, V18.S4
VZIP2 V3.S4, V2.S4, V19.S4
VZIP1 V5.S4, V4.S4, V20.S4
VZIP2 V5.S4, V4.S4, V21.S4
VZIP1 V7.S4, V6.S4, V22.S4
VZIP2 V7.S4, V6.S4, V23.S4
VZIP1 V9.S4, V8.S4, V24.S4
VZIP2 V9.S4, V8.S4, V25.S4
VZIP1 V11.S4, V10.S4, V26.S4
VZIP2 V11.S4, V10.S4, V27.S4
VZIP1 V13.S4, V12.S4, V28.S4
VZIP2 V13.S4, V12.S4, V29.S4
VZIP1 V15.S4, V14.S4, V30.S4
VZIP2 V15.S4, V14.S4, V31.S4
VZIP1 V18.D2, V16.D2, V0.D2
VZIP2 V18.D2, V16.D2, V4.D2
VZIP1 V19.D2, V17.D2, V8.D2
VZIP2 V19.D2, V17.D2, V12.D2
VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16]
VZIP1 V22.D2, V20.D2, V1.D2
VZIP2 V22.D2, V20.D2, V5.D2
VZIP1 V23.D2, V21.D2, V9.D2
VZIP2 V23.D2, V21.D2, V13.D2
VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16]
VZIP1 V26.D2, V24.D2, V2.D2
VZIP2 V26.D2, V24.D2, V6.D2
VZIP1 V27.D2, V25.D2, V10.D2
VZIP2 V27.D2, V25.D2, V14.D2
VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16]
VZIP1 V30.D2, V28.D2, V3.D2
VZIP2 V30.D2, V28.D2, V7.D2
VZIP1 V31.D2, V29.D2, V11.D2
VZIP2 V31.D2, V29.D2, V15.D2
VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16]
VEOR V0.B16, V16.B16, V16.B16
VEOR V1.B16, V17.B16, V17.B16
VEOR V2.B16, V18.B16, V18.B16
VEOR V3.B16, V19.B16, V19.B16
VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1)
VEOR V4.B16, V20.B16, V20.B16
VEOR V5.B16, V21.B16, V21.B16
VEOR V6.B16, V22.B16, V22.B16
VEOR V7.B16, V23.B16, V23.B16
VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1)
VEOR V8.B16, V24.B16, V24.B16
VEOR V9.B16, V25.B16, V25.B16
VEOR V10.B16, V26.B16, V26.B16
VEOR V11.B16, V27.B16, V27.B16
VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1)
VEOR V12.B16, V28.B16, V28.B16
VEOR V13.B16, V29.B16, V29.B16
VEOR V14.B16, V30.B16, V30.B16
VEOR V15.B16, V31.B16, V31.B16
VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1)
ADD $4, R20
MOVW R20, (R7) // update counter
CMP R2, R12
BGT loop
RET
DATA ·constants+0x00(SB)/4, $0x61707865
DATA ·constants+0x04(SB)/4, $0x3320646e
DATA ·constants+0x08(SB)/4, $0x79622d32
DATA ·constants+0x0c(SB)/4, $0x6b206574
GLOBL ·constants(SB), NOPTR|RODATA, $32
DATA ·incRotMatrix+0x00(SB)/4, $0x00000000
DATA ·incRotMatrix+0x04(SB)/4, $0x00000001
DATA ·incRotMatrix+0x08(SB)/4, $0x00000002
DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003
DATA ·incRotMatrix+0x10(SB)/4, $0x02010003
DATA ·incRotMatrix+0x14(SB)/4, $0x06050407
DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B
DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F
GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32
================================================
FILE: gossh/crypto/chacha20/chacha_generic.go
================================================
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms
// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01.
package chacha20
import (
"crypto/cipher"
"encoding/binary"
"errors"
"math/bits"
"gossh/crypto/internal/alias"
)
const (
// KeySize is the size of the key used by this cipher, in bytes.
KeySize = 32
// NonceSize is the size of the nonce used with the standard variant of this
// cipher, in bytes.
//
// Note that this is too short to be safely generated at random if the same
// key is reused more than 2³² times.
NonceSize = 12
// NonceSizeX is the size of the nonce used with the XChaCha20 variant of
// this cipher, in bytes.
NonceSizeX = 24
)
// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key
// and nonce. A *Cipher implements the cipher.Stream interface.
type Cipher struct {
// The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter
// (incremented after each block), and 3 of nonce.
key [8]uint32
counter uint32
nonce [3]uint32
// The last len bytes of buf are leftover key stream bytes from the previous
// XORKeyStream invocation. The size of buf depends on how many blocks are
// computed at a time by xorKeyStreamBlocks.
buf [bufSize]byte
len int
// overflow is set when the counter overflowed, no more blocks can be
// generated, and the next XORKeyStream call should panic.
overflow bool
// The counter-independent results of the first round are cached after they
// are computed the first time.
precompDone bool
p1, p5, p9, p13 uint32
p2, p6, p10, p14 uint32
p3, p7, p11, p15 uint32
}
var _ cipher.Stream = (*Cipher)(nil)
// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given
// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided,
// the XChaCha20 construction will be used. It returns an error if key or nonce
// have any other length.
//
// Note that ChaCha20, like all stream ciphers, is not authenticated and allows
// attackers to silently tamper with the plaintext. For this reason, it is more
// appropriate as a building block than as a standalone encryption mechanism.
// Instead, consider using package golang.org/x/crypto/chacha20poly1305.
func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) {
// This function is split into a wrapper so that the Cipher allocation will
// be inlined, and depending on how the caller uses the return value, won't
// escape to the heap.
c := &Cipher{}
return newUnauthenticatedCipher(c, key, nonce)
}
func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) {
if len(key) != KeySize {
return nil, errors.New("chacha20: wrong key size")
}
if len(nonce) == NonceSizeX {
// XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a
// derived key, allowing it to operate on a nonce of 24 bytes. See
// draft-irtf-cfrg-xchacha-01, Section 2.3.
key, _ = HChaCha20(key, nonce[0:16])
cNonce := make([]byte, NonceSize)
copy(cNonce[4:12], nonce[16:24])
nonce = cNonce
} else if len(nonce) != NonceSize {
return nil, errors.New("chacha20: wrong nonce size")
}
key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint
c.key = [8]uint32{
binary.LittleEndian.Uint32(key[0:4]),
binary.LittleEndian.Uint32(key[4:8]),
binary.LittleEndian.Uint32(key[8:12]),
binary.LittleEndian.Uint32(key[12:16]),
binary.LittleEndian.Uint32(key[16:20]),
binary.LittleEndian.Uint32(key[20:24]),
binary.LittleEndian.Uint32(key[24:28]),
binary.LittleEndian.Uint32(key[28:32]),
}
c.nonce = [3]uint32{
binary.LittleEndian.Uint32(nonce[0:4]),
binary.LittleEndian.Uint32(nonce[4:8]),
binary.LittleEndian.Uint32(nonce[8:12]),
}
return c, nil
}
// The constant first 4 words of the ChaCha20 state.
const (
j0 uint32 = 0x61707865 // expa
j1 uint32 = 0x3320646e // nd 3
j2 uint32 = 0x79622d32 // 2-by
j3 uint32 = 0x6b206574 // te k
)
const blockSize = 64
// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words.
// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16
// words each round, in columnar or diagonal groups of 4 at a time.
func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
a += b
d ^= a
d = bits.RotateLeft32(d, 16)
c += d
b ^= c
b = bits.RotateLeft32(b, 12)
a += b
d ^= a
d = bits.RotateLeft32(d, 8)
c += d
b ^= c
b = bits.RotateLeft32(b, 7)
return a, b, c, d
}
// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will
// behave as if (64 * counter) bytes had been encrypted so far.
//
// To prevent accidental counter reuse, SetCounter panics if counter is less
// than the current value.
//
// Note that the execution time of XORKeyStream is not independent of the
// counter value.
func (s *Cipher) SetCounter(counter uint32) {
// Internally, s may buffer multiple blocks, which complicates this
// implementation slightly. When checking whether the counter has rolled
// back, we must use both s.counter and s.len to determine how many blocks
// we have already output.
outputCounter := s.counter - uint32(s.len)/blockSize
if s.overflow || counter < outputCounter {
panic("chacha20: SetCounter attempted to rollback counter")
}
// In the general case, we set the new counter value and reset s.len to 0,
// causing the next call to XORKeyStream to refill the buffer. However, if
// we're advancing within the existing buffer, we can save work by simply
// setting s.len.
if counter < s.counter {
s.len = int(s.counter-counter) * blockSize
} else {
s.counter = counter
s.len = 0
}
}
// XORKeyStream XORs each byte in the given slice with a byte from the
// cipher's key stream. Dst and src must overlap entirely or not at all.
//
// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
// to pass a dst bigger than src, and in that case, XORKeyStream will
// only update dst[:len(src)] and will not touch the rest of dst.
//
// Multiple calls to XORKeyStream behave as if the concatenation of
// the src buffers was passed in a single run. That is, Cipher
// maintains state and does not reset at each XORKeyStream call.
func (s *Cipher) XORKeyStream(dst, src []byte) {
if len(src) == 0 {
return
}
if len(dst) < len(src) {
panic("chacha20: output smaller than input")
}
dst = dst[:len(src)]
if alias.InexactOverlap(dst, src) {
panic("chacha20: invalid buffer overlap")
}
// First, drain any remaining key stream from a previous XORKeyStream.
if s.len != 0 {
keyStream := s.buf[bufSize-s.len:]
if len(src) < len(keyStream) {
keyStream = keyStream[:len(src)]
}
_ = src[len(keyStream)-1] // bounds check elimination hint
for i, b := range keyStream {
dst[i] = src[i] ^ b
}
s.len -= len(keyStream)
dst, src = dst[len(keyStream):], src[len(keyStream):]
}
if len(src) == 0 {
return
}
// If we'd need to let the counter overflow and keep generating output,
// panic immediately. If instead we'd only reach the last block, remember
// not to generate any more output after the buffer is drained.
numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize
if s.overflow || uint64(s.counter)+numBlocks > 1<<32 {
panic("chacha20: counter overflow")
} else if uint64(s.counter)+numBlocks == 1<<32 {
s.overflow = true
}
// xorKeyStreamBlocks implementations expect input lengths that are a
// multiple of bufSize. Platform-specific ones process multiple blocks at a
// time, so have bufSizes that are a multiple of blockSize.
full := len(src) - len(src)%bufSize
if full > 0 {
s.xorKeyStreamBlocks(dst[:full], src[:full])
}
dst, src = dst[full:], src[full:]
// If using a multi-block xorKeyStreamBlocks would overflow, use the generic
// one that does one block at a time.
const blocksPerBuf = bufSize / blockSize
if uint64(s.counter)+blocksPerBuf > 1<<32 {
s.buf = [bufSize]byte{}
numBlocks := (len(src) + blockSize - 1) / blockSize
buf := s.buf[bufSize-numBlocks*blockSize:]
copy(buf, src)
s.xorKeyStreamBlocksGeneric(buf, buf)
s.len = len(buf) - copy(dst, buf)
return
}
// If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and
// keep the leftover keystream for the next XORKeyStream invocation.
if len(src) > 0 {
s.buf = [bufSize]byte{}
copy(s.buf[:], src)
s.xorKeyStreamBlocks(s.buf[:], s.buf[:])
s.len = bufSize - copy(dst, s.buf[:])
}
}
func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
if len(dst) != len(src) || len(dst)%blockSize != 0 {
panic("chacha20: internal error: wrong dst and/or src length")
}
// To generate each block of key stream, the initial cipher state
// (represented below) is passed through 20 rounds of shuffling,
// alternatively applying quarterRounds by columns (like 1, 5, 9, 13)
// or by diagonals (like 1, 6, 11, 12).
//
// 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc
// 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk
// 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk
// 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn
//
// c=constant k=key b=blockcount n=nonce
var (
c0, c1, c2, c3 = j0, j1, j2, j3
c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3]
c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7]
_, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2]
)
// Three quarters of the first round don't depend on the counter, so we can
// calculate them here, and reuse them for multiple blocks in the loop, and
// for future XORKeyStream invocations.
if !s.precompDone {
s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13)
s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14)
s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15)
s.precompDone = true
}
// A condition of len(src) > 0 would be sufficient, but this also
// acts as a bounds check elimination hint.
for len(src) >= 64 && len(dst) >= 64 {
// The remainder of the first column round.
fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter)
// The second diagonal round.
x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15)
x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12)
x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13)
x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14)
// The remaining 18 rounds.
for i := 0; i < 9; i++ {
// Column round.
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
// Diagonal round.
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
}
// Add back the initial state to generate the key stream, then
// XOR the key stream with the source and write out the result.
addXor(dst[0:4], src[0:4], x0, c0)
addXor(dst[4:8], src[4:8], x1, c1)
addXor(dst[8:12], src[8:12], x2, c2)
addXor(dst[12:16], src[12:16], x3, c3)
addXor(dst[16:20], src[16:20], x4, c4)
addXor(dst[20:24], src[20:24], x5, c5)
addXor(dst[24:28], src[24:28], x6, c6)
addXor(dst[28:32], src[28:32], x7, c7)
addXor(dst[32:36], src[32:36], x8, c8)
addXor(dst[36:40], src[36:40], x9, c9)
addXor(dst[40:44], src[40:44], x10, c10)
addXor(dst[44:48], src[44:48], x11, c11)
addXor(dst[48:52], src[48:52], x12, s.counter)
addXor(dst[52:56], src[52:56], x13, c13)
addXor(dst[56:60], src[56:60], x14, c14)
addXor(dst[60:64], src[60:64], x15, c15)
s.counter += 1
src, dst = src[blockSize:], dst[blockSize:]
}
}
// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes
// key and a 16 bytes nonce. It returns an error if key or nonce have any other
// length. It is used as part of the XChaCha20 construction.
func HChaCha20(key, nonce []byte) ([]byte, error) {
// This function is split into a wrapper so that the slice allocation will
// be inlined, and depending on how the caller uses the return value, won't
// escape to the heap.
out := make([]byte, 32)
return hChaCha20(out, key, nonce)
}
func hChaCha20(out, key, nonce []byte) ([]byte, error) {
if len(key) != KeySize {
return nil, errors.New("chacha20: wrong HChaCha20 key size")
}
if len(nonce) != 16 {
return nil, errors.New("chacha20: wrong HChaCha20 nonce size")
}
x0, x1, x2, x3 := j0, j1, j2, j3
x4 := binary.LittleEndian.Uint32(key[0:4])
x5 := binary.LittleEndian.Uint32(key[4:8])
x6 := binary.LittleEndian.Uint32(key[8:12])
x7 := binary.LittleEndian.Uint32(key[12:16])
x8 := binary.LittleEndian.Uint32(key[16:20])
x9 := binary.LittleEndian.Uint32(key[20:24])
x10 := binary.LittleEndian.Uint32(key[24:28])
x11 := binary.LittleEndian.Uint32(key[28:32])
x12 := binary.LittleEndian.Uint32(nonce[0:4])
x13 := binary.LittleEndian.Uint32(nonce[4:8])
x14 := binary.LittleEndian.Uint32(nonce[8:12])
x15 := binary.LittleEndian.Uint32(nonce[12:16])
for i := 0; i < 10; i++ {
// Diagonal round.
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
// Column round.
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
}
_ = out[31] // bounds check elimination hint
binary.LittleEndian.PutUint32(out[0:4], x0)
binary.LittleEndian.PutUint32(out[4:8], x1)
binary.LittleEndian.PutUint32(out[8:12], x2)
binary.LittleEndian.PutUint32(out[12:16], x3)
binary.LittleEndian.PutUint32(out[16:20], x12)
binary.LittleEndian.PutUint32(out[20:24], x13)
binary.LittleEndian.PutUint32(out[24:28], x14)
binary.LittleEndian.PutUint32(out[28:32], x15)
return out, nil
}
================================================
FILE: gossh/crypto/chacha20/chacha_noasm.go
================================================
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (!arm64 && !s390x && !ppc64le) || !gc || purego
package chacha20
const bufSize = blockSize
func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) {
s.xorKeyStreamBlocksGeneric(dst, src)
}
================================================
FILE: gossh/crypto/chacha20/chacha_ppc64le.go
================================================
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build gc && !purego
package chacha20
const bufSize = 256
//go:noescape
func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter)
}
================================================
FILE: gossh/crypto/chacha20/chacha_ppc64le.s
================================================
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on CRYPTOGAMS code with the following comment:
// # ====================================================================
// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
// # project. The module is, however, dual licensed under OpenSSL and
// # CRYPTOGAMS licenses depending on where you obtain it. For further
// # details see http://www.openssl.org/~appro/cryptogams/.
// # ====================================================================
// Code for the perl script that generates the ppc64 assembler
// can be found in the cryptogams repository at the link below. It is based on
// the original from openssl.
// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91
// The differences in this and the original implementation are
// due to the calling conventions and initialization of constants.
//go:build gc && !purego
#include "textflag.h"
#define OUT R3
#define INP R4
#define LEN R5
#define KEY R6
#define CNT R7
#define TMP R15
#define CONSTBASE R16
#define BLOCKS R17
DATA consts<>+0x00(SB)/8, $0x3320646e61707865
DATA consts<>+0x08(SB)/8, $0x6b20657479622d32
DATA consts<>+0x10(SB)/8, $0x0000000000000001
DATA consts<>+0x18(SB)/8, $0x0000000000000000
DATA consts<>+0x20(SB)/8, $0x0000000000000004
DATA consts<>+0x28(SB)/8, $0x0000000000000000
DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d
DATA consts<>+0x38(SB)/8, $0x0203000106070405
DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c
DATA consts<>+0x48(SB)/8, $0x0102030005060704
DATA consts<>+0x50(SB)/8, $0x6170786561707865
DATA consts<>+0x58(SB)/8, $0x6170786561707865
DATA consts<>+0x60(SB)/8, $0x3320646e3320646e
DATA consts<>+0x68(SB)/8, $0x3320646e3320646e
DATA consts<>+0x70(SB)/8, $0x79622d3279622d32
DATA consts<>+0x78(SB)/8, $0x79622d3279622d32
DATA consts<>+0x80(SB)/8, $0x6b2065746b206574
DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
DATA consts<>+0x90(SB)/8, $0x0000000100000000
DATA consts<>+0x98(SB)/8, $0x0000000300000002
GLOBL consts<>(SB), RODATA, $0xa0
//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
MOVD out+0(FP), OUT
MOVD inp+8(FP), INP
MOVD len+16(FP), LEN
MOVD key+24(FP), KEY
MOVD counter+32(FP), CNT
// Addressing for constants
MOVD $consts<>+0x00(SB), CONSTBASE
MOVD $16, R8
MOVD $32, R9
MOVD $48, R10
MOVD $64, R11
SRD $6, LEN, BLOCKS
// V16
LXVW4X (CONSTBASE)(R0), VS48
ADD $80,CONSTBASE
// Load key into V17,V18
LXVW4X (KEY)(R0), VS49
LXVW4X (KEY)(R8), VS50
// Load CNT, NONCE into V19
LXVW4X (CNT)(R0), VS51
// Clear V27
VXOR V27, V27, V27
// V28
LXVW4X (CONSTBASE)(R11), VS60
// splat slot from V19 -> V26
VSPLTW $0, V19, V26
VSLDOI $4, V19, V27, V19
VSLDOI $12, V27, V19, V19
VADDUWM V26, V28, V26
MOVD $10, R14
MOVD R14, CTR
loop_outer_vsx:
// V0, V1, V2, V3
LXVW4X (R0)(CONSTBASE), VS32
LXVW4X (R8)(CONSTBASE), VS33
LXVW4X (R9)(CONSTBASE), VS34
LXVW4X (R10)(CONSTBASE), VS35
// splat values from V17, V18 into V4-V11
VSPLTW $0, V17, V4
VSPLTW $1, V17, V5
VSPLTW $2, V17, V6
VSPLTW $3, V17, V7
VSPLTW $0, V18, V8
VSPLTW $1, V18, V9
VSPLTW $2, V18, V10
VSPLTW $3, V18, V11
// VOR
VOR V26, V26, V12
// splat values from V19 -> V13, V14, V15
VSPLTW $1, V19, V13
VSPLTW $2, V19, V14
VSPLTW $3, V19, V15
// splat const values
VSPLTISW $-16, V27
VSPLTISW $12, V28
VSPLTISW $8, V29
VSPLTISW $7, V30
loop_vsx:
VADDUWM V0, V4, V0
VADDUWM V1, V5, V1
VADDUWM V2, V6, V2
VADDUWM V3, V7, V3
VXOR V12, V0, V12
VXOR V13, V1, V13
VXOR V14, V2, V14
VXOR V15, V3, V15
VRLW V12, V27, V12
VRLW V13, V27, V13
VRLW V14, V27, V14
VRLW V15, V27, V15
VADDUWM V8, V12, V8
VADDUWM V9, V13, V9
VADDUWM V10, V14, V10
VADDUWM V11, V15, V11
VXOR V4, V8, V4
VXOR V5, V9, V5
VXOR V6, V10, V6
VXOR V7, V11, V7
VRLW V4, V28, V4
VRLW V5, V28, V5
VRLW V6, V28, V6
VRLW V7, V28, V7
VADDUWM V0, V4, V0
VADDUWM V1, V5, V1
VADDUWM V2, V6, V2
VADDUWM V3, V7, V3
VXOR V12, V0, V12
VXOR V13, V1, V13
VXOR V14, V2, V14
VXOR V15, V3, V15
VRLW V12, V29, V12
VRLW V13, V29, V13
VRLW V14, V29, V14
VRLW V15, V29, V15
VADDUWM V8, V12, V8
VADDUWM V9, V13, V9
VADDUWM V10, V14, V10
VADDUWM V11, V15, V11
VXOR V4, V8, V4
VXOR V5, V9, V5
VXOR V6, V10, V6
VXOR V7, V11, V7
VRLW V4, V30, V4
VRLW V5, V30, V5
VRLW V6, V30, V6
VRLW V7, V30, V7
VADDUWM V0, V5, V0
VADDUWM V1, V6, V1
VADDUWM V2, V7, V2
VADDUWM V3, V4, V3
VXOR V15, V0, V15
VXOR V12, V1, V12
VXOR V13, V2, V13
VXOR V14, V3, V14
VRLW V15, V27, V15
VRLW V12, V27, V12
VRLW V13, V27, V13
VRLW V14, V27, V14
VADDUWM V10, V15, V10
VADDUWM V11, V12, V11
VADDUWM V8, V13, V8
VADDUWM V9, V14, V9
VXOR V5, V10, V5
VXOR V6, V11, V6
VXOR V7, V8, V7
VXOR V4, V9, V4
VRLW V5, V28, V5
VRLW V6, V28, V6
VRLW V7, V28, V7
VRLW V4, V28, V4
VADDUWM V0, V5, V0
VADDUWM V1, V6, V1
VADDUWM V2, V7, V2
VADDUWM V3, V4, V3
VXOR V15, V0, V15
VXOR V12, V1, V12
VXOR V13, V2, V13
VXOR V14, V3, V14
VRLW V15, V29, V15
VRLW V12, V29, V12
VRLW V13, V29, V13
VRLW V14, V29, V14
VADDUWM V10, V15, V10
VADDUWM V11, V12, V11
VADDUWM V8, V13, V8
VADDUWM V9, V14, V9
VXOR V5, V10, V5
VXOR V6, V11, V6
VXOR V7, V8, V7
VXOR V4, V9, V4
VRLW V5, V30, V5
VRLW V6, V30, V6
VRLW V7, V30, V7
VRLW V4, V30, V4
BC 16, LT, loop_vsx
VADDUWM V12, V26, V12
WORD $0x13600F8C // VMRGEW V0, V1, V27
WORD $0x13821F8C // VMRGEW V2, V3, V28
WORD $0x10000E8C // VMRGOW V0, V1, V0
WORD $0x10421E8C // VMRGOW V2, V3, V2
WORD $0x13A42F8C // VMRGEW V4, V5, V29
WORD $0x13C63F8C // VMRGEW V6, V7, V30
XXPERMDI VS32, VS34, $0, VS33
XXPERMDI VS32, VS34, $3, VS35
XXPERMDI VS59, VS60, $0, VS32
XXPERMDI VS59, VS60, $3, VS34
WORD $0x10842E8C // VMRGOW V4, V5, V4
WORD $0x10C63E8C // VMRGOW V6, V7, V6
WORD $0x13684F8C // VMRGEW V8, V9, V27
WORD $0x138A5F8C // VMRGEW V10, V11, V28
XXPERMDI VS36, VS38, $0, VS37
XXPERMDI VS36, VS38, $3, VS39
XXPERMDI VS61, VS62, $0, VS36
XXPERMDI VS61, VS62, $3, VS38
WORD $0x11084E8C // VMRGOW V8, V9, V8
WORD $0x114A5E8C // VMRGOW V10, V11, V10
WORD $0x13AC6F8C // VMRGEW V12, V13, V29
WORD $0x13CE7F8C // VMRGEW V14, V15, V30
XXPERMDI VS40, VS42, $0, VS41
XXPERMDI VS40, VS42, $3, VS43
XXPERMDI VS59, VS60, $0, VS40
XXPERMDI VS59, VS60, $3, VS42
WORD $0x118C6E8C // VMRGOW V12, V13, V12
WORD $0x11CE7E8C // VMRGOW V14, V15, V14
VSPLTISW $4, V27
VADDUWM V26, V27, V26
XXPERMDI VS44, VS46, $0, VS45
XXPERMDI VS44, VS46, $3, VS47
XXPERMDI VS61, VS62, $0, VS44
XXPERMDI VS61, VS62, $3, VS46
VADDUWM V0, V16, V0
VADDUWM V4, V17, V4
VADDUWM V8, V18, V8
VADDUWM V12, V19, V12
CMPU LEN, $64
BLT tail_vsx
// Bottom of loop
LXVW4X (INP)(R0), VS59
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
STXVW4X VS59, (OUT)(R0)
STXVW4X VS60, (OUT)(R8)
ADD $64, INP
STXVW4X VS61, (OUT)(R9)
ADD $-64, LEN
STXVW4X VS62, (OUT)(R10)
ADD $64, OUT
BEQ done_vsx
VADDUWM V1, V16, V0
VADDUWM V5, V17, V4
VADDUWM V9, V18, V8
VADDUWM V13, V19, V12
CMPU LEN, $64
BLT tail_vsx
LXVW4X (INP)(R0), VS59
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
STXVW4X VS59, (OUT)(R0)
STXVW4X VS60, (OUT)(R8)
ADD $64, INP
STXVW4X VS61, (OUT)(R9)
ADD $-64, LEN
STXVW4X VS62, (OUT)(V10)
ADD $64, OUT
BEQ done_vsx
VADDUWM V2, V16, V0
VADDUWM V6, V17, V4
VADDUWM V10, V18, V8
VADDUWM V14, V19, V12
CMPU LEN, $64
BLT tail_vsx
LXVW4X (INP)(R0), VS59
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
STXVW4X VS59, (OUT)(R0)
STXVW4X VS60, (OUT)(R8)
ADD $64, INP
STXVW4X VS61, (OUT)(R9)
ADD $-64, LEN
STXVW4X VS62, (OUT)(R10)
ADD $64, OUT
BEQ done_vsx
VADDUWM V3, V16, V0
VADDUWM V7, V17, V4
VADDUWM V11, V18, V8
VADDUWM V15, V19, V12
CMPU LEN, $64
BLT tail_vsx
LXVW4X (INP)(R0), VS59
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
STXVW4X VS59, (OUT)(R0)
STXVW4X VS60, (OUT)(R8)
ADD $64, INP
STXVW4X VS61, (OUT)(R9)
ADD $-64, LEN
STXVW4X VS62, (OUT)(R10)
ADD $64, OUT
MOVD $10, R14
MOVD R14, CTR
BNE loop_outer_vsx
done_vsx:
// Increment counter by number of 64 byte blocks
MOVD (CNT), R14
ADD BLOCKS, R14
MOVD R14, (CNT)
RET
tail_vsx:
ADD $32, R1, R11
MOVD LEN, CTR
// Save values on stack to copy from
STXVW4X VS32, (R11)(R0)
STXVW4X VS36, (R11)(R8)
STXVW4X VS40, (R11)(R9)
STXVW4X VS44, (R11)(R10)
ADD $-1, R11, R12
ADD $-1, INP
ADD $-1, OUT
looptail_vsx:
// Copying the result to OUT
// in bytes.
MOVBZU 1(R12), KEY
MOVBZU 1(INP), TMP
XOR KEY, TMP, KEY
MOVBU KEY, 1(OUT)
BC 16, LT, looptail_vsx
// Clear the stack values
STXVW4X VS48, (R11)(R0)
STXVW4X VS48, (R11)(R8)
STXVW4X VS48, (R11)(R9)
STXVW4X VS48, (R11)(R10)
BR done_vsx
================================================
FILE: gossh/crypto/chacha20/chacha_s390x.go
================================================
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build gc && !purego
package chacha20
import "gossh/sys/cpu"
var haveAsm = cpu.S390X.HasVX
const bufSize = 256
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
// be called when the vector facility is available. Implementation in asm_s390x.s.
//
//go:noescape
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
if cpu.S390X.HasVX {
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
} else {
c.xorKeyStreamBlocksGeneric(dst, src)
}
}
================================================
FILE: gossh/crypto/chacha20/chacha_s390x.s
================================================
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build gc && !purego
#include "go_asm.h"
#include "textflag.h"
// This is an implementation of the ChaCha20 encryption algorithm as
// specified in RFC 7539. It uses vector instructions to compute
// 4 keystream blocks in parallel (256 bytes) which are then XORed
// with the bytes in the input slice.
GLOBL ·constants<>(SB), RODATA|NOPTR, $32
// BSWAP: swap bytes in each 4-byte element
DATA ·constants<>+0x00(SB)/4, $0x03020100
DATA ·constants<>+0x04(SB)/4, $0x07060504
DATA ·constants<>+0x08(SB)/4, $0x0b0a0908
DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c
// J0: [j0, j1, j2, j3]
DATA ·constants<>+0x10(SB)/4, $0x61707865
DATA ·constants<>+0x14(SB)/4, $0x3320646e
DATA ·constants<>+0x18(SB)/4, $0x79622d32
DATA ·constants<>+0x1c(SB)/4, $0x6b206574
#define BSWAP V5
#define J0 V6
#define KEY0 V7
#define KEY1 V8
#define NONCE V9
#define CTR V10
#define M0 V11
#define M1 V12
#define M2 V13
#define M3 V14
#define INC V15
#define X0 V16
#define X1 V17
#define X2 V18
#define X3 V19
#define X4 V20
#define X5 V21
#define X6 V22
#define X7 V23
#define X8 V24
#define X9 V25
#define X10 V26
#define X11 V27
#define X12 V28
#define X13 V29
#define X14 V30
#define X15 V31
#define NUM_ROUNDS 20
#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \
VAF a1, a0, a0 \
VAF b1, b0, b0 \
VAF c1, c0, c0 \
VAF d1, d0, d0 \
VX a0, a2, a2 \
VX b0, b2, b2 \
VX c0, c2, c2 \
VX d0, d2, d2 \
VERLLF $16, a2, a2 \
VERLLF $16, b2, b2 \
VERLLF $16, c2, c2 \
VERLLF $16, d2, d2 \
VAF a2, a3, a3 \
VAF b2, b3, b3 \
VAF c2, c3, c3 \
VAF d2, d3, d3 \
VX a3, a1, a1 \
VX b3, b1, b1 \
VX c3, c1, c1 \
VX d3, d1, d1 \
VERLLF $12, a1, a1 \
VERLLF $12, b1, b1 \
VERLLF $12, c1, c1 \
VERLLF $12, d1, d1 \
VAF a1, a0, a0 \
VAF b1, b0, b0 \
VAF c1, c0, c0 \
VAF d1, d0, d0 \
VX a0, a2, a2 \
VX b0, b2, b2 \
VX c0, c2, c2 \
VX d0, d2, d2 \
VERLLF $8, a2, a2 \
VERLLF $8, b2, b2 \
VERLLF $8, c2, c2 \
VERLLF $8, d2, d2 \
VAF a2, a3, a3 \
VAF b2, b3, b3 \
VAF c2, c3, c3 \
VAF d2, d3, d3 \
VX a3, a1, a1 \
VX b3, b1, b1 \
VX c3, c1, c1 \
VX d3, d1, d1 \
VERLLF $7, a1, a1 \
VERLLF $7, b1, b1 \
VERLLF $7, c1, c1 \
VERLLF $7, d1, d1
#define PERMUTE(mask, v0, v1, v2, v3) \
VPERM v0, v0, mask, v0 \
VPERM v1, v1, mask, v1 \
VPERM v2, v2, mask, v2 \
VPERM v3, v3, mask, v3
#define ADDV(x, v0, v1, v2, v3) \
VAF x, v0, v0 \
VAF x, v1, v1 \
VAF x, v2, v2 \
VAF x, v3, v3
#define XORV(off, dst, src, v0, v1, v2, v3) \
VLM off(src), M0, M3 \
PERMUTE(BSWAP, v0, v1, v2, v3) \
VX v0, M0, M0 \
VX v1, M1, M1 \
VX v2, M2, M2 \
VX v3, M3, M3 \
VSTM M0, M3, off(dst)
#define SHUFFLE(a, b, c, d, t, u, v, w) \
VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]}
VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]}
VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]}
VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]}
VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]}
VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]}
VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]}
VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]}
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
MOVD $·constants<>(SB), R1
MOVD dst+0(FP), R2 // R2=&dst[0]
LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src)
MOVD key+48(FP), R5 // R5=key
MOVD nonce+56(FP), R6 // R6=nonce
MOVD counter+64(FP), R7 // R7=counter
// load BSWAP and J0
VLM (R1), BSWAP, J0
// setup
MOVD $95, R0
VLM (R5), KEY0, KEY1
VLL R0, (R6), NONCE
VZERO M0
VLEIB $7, $32, M0
VSRLB M0, NONCE, NONCE
// initialize counter values
VLREPF (R7), CTR
VZERO INC
VLEIF $1, $1, INC
VLEIF $2, $2, INC
VLEIF $3, $3, INC
VAF INC, CTR, CTR
VREPIF $4, INC
chacha:
VREPF $0, J0, X0
VREPF $1, J0, X1
VREPF $2, J0, X2
VREPF $3, J0, X3
VREPF $0, KEY0, X4
VREPF $1, KEY0, X5
VREPF $2, KEY0, X6
VREPF $3, KEY0, X7
VREPF $0, KEY1, X8
VREPF $1, KEY1, X9
VREPF $2, KEY1, X10
VREPF $3, KEY1, X11
VLR CTR, X12
VREPF $1, NONCE, X13
VREPF $2, NONCE, X14
VREPF $3, NONCE, X15
MOVD $(NUM_ROUNDS/2), R1
loop:
ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11)
ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9)
ADD $-1, R1
BNE loop
// decrement length
ADD $-256, R4
// rearrange vectors
SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3)
ADDV(J0, X0, X1, X2, X3)
SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3)
ADDV(KEY0, X4, X5, X6, X7)
SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3)
ADDV(KEY1, X8, X9, X10, X11)
VAF CTR, X12, X12
SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3)
ADDV(NONCE, X12, X13, X14, X15)
// increment counters
VAF INC, CTR, CTR
// xor keystream with plaintext
XORV(0*64, R2, R3, X0, X4, X8, X12)
XORV(1*64, R2, R3, X1, X5, X9, X13)
XORV(2*64, R2, R3, X2, X6, X10, X14)
XORV(3*64, R2, R3, X3, X7, X11, X15)
// increment pointers
MOVD $256(R2), R2
MOVD $256(R3), R3
CMPBNE R4, $0, chacha
VSTEF $0, CTR, (R7)
RET
================================================
FILE: gossh/crypto/chacha20/xor.go
================================================
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found src the LICENSE file.
package chacha20
import "runtime"
// Platforms that have fast unaligned 32-bit little endian accesses.
const unaligned = runtime.GOARCH == "386" ||
runtime.GOARCH == "amd64" ||
runtime.GOARCH == "arm64" ||
runtime.GOARCH == "ppc64le" ||
runtime.GOARCH == "s390x"
// addXor reads a little endian uint32 from src, XORs it with (a + b) and
// places the result in little endian byte order in dst.
func addXor(dst, src []byte, a, b uint32) {
_, _ = src[3], dst[3] // bounds check elimination hint
if unaligned {
// The compiler should optimize this code into
// 32-bit unaligned little endian loads and stores.
// TODO: delete once the compiler does a reliably
// good job with the generic code below.
// See issue #25111 for more details.
v := uint32(src[0])
v |= uint32(src[1]) << 8
v |= uint32(src[2]) << 16
v |= uint32(src[3]) << 24
v ^= a + b
dst[0] = byte(v)
dst[1] = byte(v >> 8)
dst[2] = byte(v >> 16)
dst[3] = byte(v >> 24)
} else {
a += b
dst[0] = src[0] ^ byte(a)
dst[1] = src[1] ^ byte(a>>8)
dst[2] = src[2] ^ byte(a>>16)
dst[3] = src[3] ^ byte(a>>24)
}
}
================================================
FILE: gossh/crypto/chacha20poly1305/chacha20poly1305.go
================================================
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its
// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and
// draft-irtf-cfrg-xchacha-01.
package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305"
import (
"crypto/cipher"
"errors"
)
const (
// KeySize is the size of the key used by this AEAD, in bytes.
KeySize = 32
// NonceSize is the size of the nonce used with the standard variant of this
// AEAD, in bytes.
//
// Note that this is too short to be safely generated at random if the same
// key is reused more than 2³² times.
NonceSize = 12
// NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305
// variant of this AEAD, in bytes.
NonceSizeX = 24
// Overhead is the size of the Poly1305 authentication tag, and the
// difference between a ciphertext length and its plaintext.
Overhead = 16
)
type chacha20poly1305 struct {
key [KeySize]byte
}
// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key.
func New(key []byte) (cipher.AEAD, error) {
if len(key) != KeySize {
return nil, errors.New("chacha20poly1305: bad key length")
}
ret := new(chacha20poly1305)
copy(ret.key[:], key)
return ret, nil
}
func (c *chacha20poly1305) NonceSize() int {
return NonceSize
}
func (c *chacha20poly1305) Overhead() int {
return Overhead
}
func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
if len(nonce) != NonceSize {
panic("chacha20poly1305: bad nonce length passed to Seal")
}
if uint64(len(plaintext)) > (1<<38)-64 {
panic("chacha20poly1305: plaintext too large")
}
return c.seal(dst, nonce, plaintext, additionalData)
}
var errOpen = errors.New("chacha20poly1305: message authentication failed")
func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
if len(nonce) != NonceSize {
panic("chacha20poly1305: bad nonce length passed to Open")
}
if len(ciphertext) < 16 {
return nil, errOpen
}
if uint64(len(ciphertext)) > (1<<38)-48 {
panic("chacha20poly1305: ciphertext too large")
}
return c.open(dst, nonce, ciphertext, additionalData)
}
// sliceForAppend takes a slice and a requested number of bytes. It returns a
// slice with the contents of the given slice followed by that many bytes and a
// second slice that aliases into it and contains only the extra bytes. If the
// original slice has sufficient capacity then no allocation is performed.
func sliceForAppend(in []byte, n int) (head, tail []byte) {
if total := len(in) + n; cap(in) >= total {
head = in[:total]
} else {
head = make([]byte, total)
copy(head, in)
}
tail = head[len(in):]
return
}
================================================
FILE: gossh/crypto/chacha20poly1305/chacha20poly1305_amd64.go
================================================
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build gc && !purego
package chacha20poly1305
import (
"encoding/binary"
"gossh/crypto/internal/alias"
"gossh/sys/cpu"
)
//go:noescape
func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
//go:noescape
func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
var (
useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
)
// setupState writes a ChaCha20 input matrix to state. See
// https://tools.ietf.org/html/rfc7539#section-2.3.
func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
state[0] = 0x61707865
state[1] = 0x3320646e
state[2] = 0x79622d32
state[3] = 0x6b206574
state[4] = binary.LittleEndian.Uint32(key[0:4])
state[5] = binary.LittleEndian.Uint32(key[4:8])
state[6] = binary.LittleEndian.Uint32(key[8:12])
state[7] = binary.LittleEndian.Uint32(key[12:16])
state[8] = binary.LittleEndian.Uint32(key[16:20])
state[9] = binary.LittleEndian.Uint32(key[20:24])
state[10] = binary.LittleEndian.Uint32(key[24:28])
state[11] = binary.LittleEndian.Uint32(key[28:32])
state[12] = 0
state[13] = binary.LittleEndian.Uint32(nonce[0:4])
state[14] = binary.LittleEndian.Uint32(nonce[4:8])
state[15] = binary.LittleEndian.Uint32(nonce[8:12])
}
func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
if !cpu.X86.HasSSSE3 {
return c.sealGeneric(dst, nonce, plaintext, additionalData)
}
var state [16]uint32
setupState(&state, &c.key, nonce)
ret, out := sliceForAppend(dst, len(plaintext)+16)
if alias.InexactOverlap(out, plaintext) {
panic("chacha20poly1305: invalid buffer overlap")
}
chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
return ret
}
func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
if !cpu.X86.HasSSSE3 {
return c.openGeneric(dst, nonce, ciphertext, additionalData)
}
var state [16]uint32
setupState(&state, &c.key, nonce)
ciphertext = ciphertext[:len(ciphertext)-16]
ret, out := sliceForAppend(dst, len(ciphertext))
if alias.InexactOverlap(out, ciphertext) {
panic("chacha20poly1305: invalid buffer overlap")
}
if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
for i := range out {
out[i] = 0
}
return nil, errOpen
}
return ret, nil
}
================================================
FILE: gossh/crypto/chacha20poly1305/chacha20poly1305_amd64.s
================================================
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare.
//go:build gc && !purego
#include "textflag.h"
// General register allocation
#define oup DI
#define inp SI
#define inl BX
#define adp CX // free to reuse, after we hash the additional data
#define keyp R8 // free to reuse, when we copy the key to stack
#define itr2 R9 // general iterator
#define itr1 CX // general iterator
#define acc0 R10
#define acc1 R11
#define acc2 R12
#define t0 R13
#define t1 R14
#define t2 R15
#define t3 R8
// Register and stack allocation for the SSE code
#define rStore (0*16)(BP)
#define sStore (1*16)(BP)
#define state1Store (2*16)(BP)
#define state2Store (3*16)(BP)
#define tmpStore (4*16)(BP)
#define ctr0Store (5*16)(BP)
#define ctr1Store (6*16)(BP)
#define ctr2Store (7*16)(BP)
#define ctr3Store (8*16)(BP)
#define A0 X0
#define A1 X1
#define A2 X2
#define B0 X3
#define B1 X4
#define B2 X5
#define C0 X6
#define C1 X7
#define C2 X8
#define D0 X9
#define D1 X10
#define D2 X11
#define T0 X12
#define T1 X13
#define T2 X14
#define T3 X15
#define A3 T0
#define B3 T1
#define C3 T2
#define D3 T3
// Register and stack allocation for the AVX2 code
#define rsStoreAVX2 (0*32)(BP)
#define state1StoreAVX2 (1*32)(BP)
#define state2StoreAVX2 (2*32)(BP)
#define ctr0StoreAVX2 (3*32)(BP)
#define ctr1StoreAVX2 (4*32)(BP)
#define ctr2StoreAVX2 (5*32)(BP)
#define ctr3StoreAVX2 (6*32)(BP)
#define tmpStoreAVX2 (7*32)(BP) // 256 bytes on stack
#define AA0 Y0
#define AA1 Y5
#define AA2 Y6
#define AA3 Y7
#define BB0 Y14
#define BB1 Y9
#define BB2 Y10
#define BB3 Y11
#define CC0 Y12
#define CC1 Y13
#define CC2 Y8
#define CC3 Y15
#define DD0 Y4
#define DD1 Y1
#define DD2 Y2
#define DD3 Y3
#define TT0 DD3
#define TT1 AA3
#define TT2 BB3
#define TT3 CC3
// ChaCha20 constants
DATA ·chacha20Constants<>+0x00(SB)/4, $0x61707865
DATA ·chacha20Constants<>+0x04(SB)/4, $0x3320646e
DATA ·chacha20Constants<>+0x08(SB)/4, $0x79622d32
DATA ·chacha20Constants<>+0x0c(SB)/4, $0x6b206574
DATA ·chacha20Constants<>+0x10(SB)/4, $0x61707865
DATA ·chacha20Constants<>+0x14(SB)/4, $0x3320646e
DATA ·chacha20Constants<>+0x18(SB)/4, $0x79622d32
DATA ·chacha20Constants<>+0x1c(SB)/4, $0x6b206574
// <<< 16 with PSHUFB
DATA ·rol16<>+0x00(SB)/8, $0x0504070601000302
DATA ·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A
DATA ·rol16<>+0x10(SB)/8, $0x0504070601000302
DATA ·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A
// <<< 8 with PSHUFB
DATA ·rol8<>+0x00(SB)/8, $0x0605040702010003
DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B
DATA ·rol8<>+0x10(SB)/8, $0x0605040702010003
DATA ·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B
DATA ·avx2InitMask<>+0x00(SB)/8, $0x0
DATA ·avx2InitMask<>+0x08(SB)/8, $0x0
DATA ·avx2InitMask<>+0x10(SB)/8, $0x1
DATA ·avx2InitMask<>+0x18(SB)/8, $0x0
DATA ·avx2IncMask<>+0x00(SB)/8, $0x2
DATA ·avx2IncMask<>+0x08(SB)/8, $0x0
DATA ·avx2IncMask<>+0x10(SB)/8, $0x2
DATA ·avx2IncMask<>+0x18(SB)/8, $0x0
// Poly1305 key clamp
DATA ·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
DATA ·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
DATA ·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF
DATA ·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF
DATA ·sseIncMask<>+0x00(SB)/8, $0x1
DATA ·sseIncMask<>+0x08(SB)/8, $0x0
// To load/store the last < 16 bytes in a buffer
DATA ·andMask<>+0x00(SB)/8, $0x00000000000000ff
DATA ·andMask<>+0x08(SB)/8, $0x0000000000000000
DATA ·andMask<>+0x10(SB)/8, $0x000000000000ffff
DATA ·andMask<>+0x18(SB)/8, $0x0000000000000000
DATA ·andMask<>+0x20(SB)/8, $0x0000000000ffffff
DATA ·andMask<>+0x28(SB)/8, $0x0000000000000000
DATA ·andMask<>+0x30(SB)/8, $0x00000000ffffffff
DATA ·andMask<>+0x38(SB)/8, $0x0000000000000000
DATA ·andMask<>+0x40(SB)/8, $0x000000ffffffffff
DATA ·andMask<>+0x48(SB)/8, $0x0000000000000000
DATA ·andMask<>+0x50(SB)/8, $0x0000ffffffffffff
DATA ·andMask<>+0x58(SB)/8, $0x0000000000000000
DATA ·andMask<>+0x60(SB)/8, $0x00ffffffffffffff
DATA ·andMask<>+0x68(SB)/8, $0x0000000000000000
DATA ·andMask<>+0x70(SB)/8, $0xffffffffffffffff
DATA ·andMask<>+0x78(SB)/8, $0x0000000000000000
DATA ·andMask<>+0x80(SB)/8, $0xffffffffffffffff
DATA ·andMask<>+0x88(SB)/8, $0x00000000000000ff
DATA ·andMask<>+0x90(SB)/8, $0xffffffffffffffff
DATA ·andMask<>+0x98(SB)/8, $0x000000000000ffff
DATA ·andMask<>+0xa0(SB)/8, $0xffffffffffffffff
DATA ·andMask<>+0xa8(SB)/8, $0x0000000000ffffff
DATA ·andMask<>+0xb0(SB)/8, $0xffffffffffffffff
DATA ·andMask<>+0xb8(SB)/8, $0x00000000ffffffff
DATA ·andMask<>+0xc0(SB)/8, $0xffffffffffffffff
DATA ·andMask<>+0xc8(SB)/8, $0x000000ffffffffff
DATA ·andMask<>+0xd0(SB)/8, $0xffffffffffffffff
DATA ·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff
DATA ·andMask<>+0xe0(SB)/8, $0xffffffffffffffff
DATA ·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff
GLOBL ·chacha20Constants<>(SB), (NOPTR+RODATA), $32
GLOBL ·rol16<>(SB), (NOPTR+RODATA), $32
GLOBL ·rol8<>(SB), (NOPTR+RODATA), $32
GLOBL ·sseIncMask<>(SB), (NOPTR+RODATA), $16
GLOBL ·avx2IncMask<>(SB), (NOPTR+RODATA), $32
GLOBL ·avx2InitMask<>(SB), (NOPTR+RODATA), $32
GLOBL ·polyClampMask<>(SB), (NOPTR+RODATA), $32
GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240
// No PALIGNR in Go ASM yet (but VPALIGNR is present).
#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3
#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4
#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5
#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13
#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6
#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7
#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8
#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14
#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9
#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10
#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11
#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15
#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3
#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4
#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5
#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13
#define shiftC0Right shiftC0Left
#define shiftC1Right shiftC1Left
#define shiftC2Right shiftC2Left
#define shiftC3
gitextract_q8k6q315/
├── .github/
│ └── workflows/
│ └── build-and-release.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── gossh/
│ ├── Makefile
│ ├── app/
│ │ ├── config/
│ │ │ └── config.go
│ │ ├── middleware/
│ │ │ ├── db_check.go
│ │ │ ├── jwt_auth.go
│ │ │ ├── net_filter.go
│ │ │ ├── perm_check.go
│ │ │ └── sys_init.go
│ │ ├── model/
│ │ │ ├── cmd_note.go
│ │ │ ├── datetime.go
│ │ │ ├── db_init.go
│ │ │ ├── login_audit.go
│ │ │ ├── net_filter.go
│ │ │ ├── policy_conf.go
│ │ │ ├── ssh_conf.go
│ │ │ ├── sshd_cert.go
│ │ │ ├── sshd_conf.go
│ │ │ ├── sshd_user.go
│ │ │ └── web_user.go
│ │ ├── service/
│ │ │ ├── cmd_note.go
│ │ │ ├── db_conn.go
│ │ │ ├── login_audit.go
│ │ │ ├── net_filter.go
│ │ │ ├── policy_conf.go
│ │ │ ├── service_init.go
│ │ │ ├── ssh_conf.go
│ │ │ ├── ssh_conn.go
│ │ │ ├── ssh_sftp.go
│ │ │ ├── ssh_status.go
│ │ │ ├── sshd_cert.go
│ │ │ ├── sshd_server.go
│ │ │ ├── sshd_user.go
│ │ │ ├── sys_init.go
│ │ │ └── web_user.go
│ │ └── utils/
│ │ ├── crypto.go
│ │ └── utils.go
│ ├── crypto/
│ │ ├── blowfish/
│ │ │ ├── block.go
│ │ │ ├── cipher.go
│ │ │ └── const.go
│ │ ├── chacha20/
│ │ │ ├── chacha_arm64.go
│ │ │ ├── chacha_arm64.s
│ │ │ ├── chacha_generic.go
│ │ │ ├── chacha_noasm.go
│ │ │ ├── chacha_ppc64le.go
│ │ │ ├── chacha_ppc64le.s
│ │ │ ├── chacha_s390x.go
│ │ │ ├── chacha_s390x.s
│ │ │ └── xor.go
│ │ ├── chacha20poly1305/
│ │ │ ├── chacha20poly1305.go
│ │ │ ├── chacha20poly1305_amd64.go
│ │ │ ├── chacha20poly1305_amd64.s
│ │ │ ├── chacha20poly1305_generic.go
│ │ │ ├── chacha20poly1305_noasm.go
│ │ │ └── xchacha20poly1305.go
│ │ ├── curve25519/
│ │ │ ├── curve25519.go
│ │ │ ├── curve25519_compat.go
│ │ │ ├── curve25519_go120.go
│ │ │ └── internal/
│ │ │ └── field/
│ │ │ ├── fe.go
│ │ │ ├── fe_amd64.go
│ │ │ ├── fe_amd64.s
│ │ │ ├── fe_amd64_noasm.go
│ │ │ ├── fe_arm64.go
│ │ │ ├── fe_arm64.s
│ │ │ ├── fe_arm64_noasm.go
│ │ │ ├── fe_generic.go
│ │ │ ├── sync.checkpoint
│ │ │ └── sync.sh
│ │ ├── internal/
│ │ │ ├── alias/
│ │ │ │ ├── alias.go
│ │ │ │ └── alias_purego.go
│ │ │ ├── poly1305/
│ │ │ │ ├── mac_noasm.go
│ │ │ │ ├── poly1305.go
│ │ │ │ ├── sum_amd64.go
│ │ │ │ ├── sum_amd64.s
│ │ │ │ ├── sum_generic.go
│ │ │ │ ├── sum_ppc64le.go
│ │ │ │ ├── sum_ppc64le.s
│ │ │ │ ├── sum_s390x.go
│ │ │ │ └── sum_s390x.s
│ │ │ └── testenv/
│ │ │ ├── exec.go
│ │ │ ├── testenv_notunix.go
│ │ │ └── testenv_unix.go
│ │ └── ssh/
│ │ ├── agent/
│ │ │ ├── client.go
│ │ │ ├── forward.go
│ │ │ ├── keyring.go
│ │ │ └── server.go
│ │ ├── buffer.go
│ │ ├── certs.go
│ │ ├── channel.go
│ │ ├── cipher.go
│ │ ├── client.go
│ │ ├── client_auth.go
│ │ ├── common.go
│ │ ├── connection.go
│ │ ├── doc.go
│ │ ├── handshake.go
│ │ ├── internal/
│ │ │ └── bcrypt_pbkdf/
│ │ │ └── bcrypt_pbkdf.go
│ │ ├── kex.go
│ │ ├── keys.go
│ │ ├── knownhosts/
│ │ │ └── knownhosts.go
│ │ ├── mac.go
│ │ ├── messages.go
│ │ ├── mux.go
│ │ ├── server.go
│ │ ├── session.go
│ │ ├── ssh_gss.go
│ │ ├── streamlocal.go
│ │ ├── tcpip.go
│ │ ├── terminal/
│ │ │ └── terminal.go
│ │ └── transport.go
│ ├── gin/
│ │ ├── auth.go
│ │ ├── binding/
│ │ │ ├── binding.go
│ │ │ ├── default_validator.go
│ │ │ ├── form.go
│ │ │ ├── form_mapping.go
│ │ │ ├── header.go
│ │ │ ├── json.go
│ │ │ ├── multipart_form_mapping.go
│ │ │ ├── query.go
│ │ │ ├── uri.go
│ │ │ └── xml.go
│ │ ├── context.go
│ │ ├── debug.go
│ │ ├── errors.go
│ │ ├── fs.go
│ │ ├── gin.go
│ │ ├── ginS/
│ │ │ ├── README.md
│ │ │ └── gins.go
│ │ ├── internal/
│ │ │ ├── bytesconv/
│ │ │ │ └── bytesconv.go
│ │ │ └── json/
│ │ │ └── json.go
│ │ ├── jwt/
│ │ │ ├── README.md
│ │ │ ├── claims.go
│ │ │ ├── cmd/
│ │ │ │ └── jwt/
│ │ │ │ ├── README.md
│ │ │ │ └── main.go
│ │ │ ├── ecdsa.go
│ │ │ ├── ecdsa_utils.go
│ │ │ ├── ed25519.go
│ │ │ ├── ed25519_utils.go
│ │ │ ├── errors.go
│ │ │ ├── errors_go1_20.go
│ │ │ ├── errors_go_other.go
│ │ │ ├── hmac.go
│ │ │ ├── map_claims.go
│ │ │ ├── none.go
│ │ │ ├── parser.go
│ │ │ ├── parser_option.go
│ │ │ ├── registered_claims.go
│ │ │ ├── request/
│ │ │ │ ├── doc.go
│ │ │ │ ├── extractor.go
│ │ │ │ ├── oauth2.go
│ │ │ │ └── request.go
│ │ │ ├── rsa.go
│ │ │ ├── rsa_pss.go
│ │ │ ├── rsa_utils.go
│ │ │ ├── signing_method.go
│ │ │ ├── token.go
│ │ │ ├── token_option.go
│ │ │ ├── types.go
│ │ │ └── validator.go
│ │ ├── logger.go
│ │ ├── mode.go
│ │ ├── path.go
│ │ ├── recovery.go
│ │ ├── render/
│ │ │ ├── data.go
│ │ │ ├── html.go
│ │ │ ├── json.go
│ │ │ ├── reader.go
│ │ │ ├── redirect.go
│ │ │ ├── render.go
│ │ │ ├── text.go
│ │ │ └── xml.go
│ │ ├── response_writer.go
│ │ ├── routergroup.go
│ │ ├── sessions/
│ │ │ ├── context/
│ │ │ │ └── context.go
│ │ │ ├── cookie/
│ │ │ │ └── cookie.go
│ │ │ ├── memstore/
│ │ │ │ ├── cache.go
│ │ │ │ ├── memstore.go
│ │ │ │ └── store.go
│ │ │ ├── securecookie/
│ │ │ │ └── securecookie.go
│ │ │ ├── session_options_go1.10.go
│ │ │ ├── session_options_go1.11.go
│ │ │ ├── sessions/
│ │ │ │ ├── cookie.go
│ │ │ │ ├── cookie_go111.go
│ │ │ │ ├── doc.go
│ │ │ │ ├── lex.go
│ │ │ │ ├── options.go
│ │ │ │ ├── options_go111.go
│ │ │ │ ├── sessions.go
│ │ │ │ └── store.go
│ │ │ └── sessions.go
│ │ ├── sse/
│ │ │ ├── sse-decoder.go
│ │ │ ├── sse-encoder.go
│ │ │ └── writer.go
│ │ ├── tree.go
│ │ ├── utils.go
│ │ ├── validator/
│ │ │ ├── baked_in.go
│ │ │ ├── cache.go
│ │ │ ├── country_codes.go
│ │ │ ├── currency_codes.go
│ │ │ ├── errors.go
│ │ │ ├── field_level.go
│ │ │ ├── options.go
│ │ │ ├── postcode_regexes.go
│ │ │ ├── regexes.go
│ │ │ ├── struct_level.go
│ │ │ ├── util.go
│ │ │ ├── validator.go
│ │ │ └── validator_instance.go
│ │ └── version.go
│ ├── go.mod
│ ├── gorm/
│ │ ├── association.go
│ │ ├── callbacks/
│ │ │ ├── associations.go
│ │ │ ├── callbacks.go
│ │ │ ├── callmethod.go
│ │ │ ├── create.go
│ │ │ ├── delete.go
│ │ │ ├── helper.go
│ │ │ ├── interfaces.go
│ │ │ ├── preload.go
│ │ │ ├── query.go
│ │ │ ├── raw.go
│ │ │ ├── row.go
│ │ │ ├── transaction.go
│ │ │ └── update.go
│ │ ├── callbacks.go
│ │ ├── chainable_api.go
│ │ ├── clause/
│ │ │ ├── clause.go
│ │ │ ├── delete.go
│ │ │ ├── expression.go
│ │ │ ├── from.go
│ │ │ ├── group_by.go
│ │ │ ├── insert.go
│ │ │ ├── joins.go
│ │ │ ├── limit.go
│ │ │ ├── locking.go
│ │ │ ├── on_conflict.go
│ │ │ ├── order_by.go
│ │ │ ├── returning.go
│ │ │ ├── select.go
│ │ │ ├── set.go
│ │ │ ├── update.go
│ │ │ ├── values.go
│ │ │ ├── where.go
│ │ │ └── with.go
│ │ ├── driver/
│ │ │ ├── mysql/
│ │ │ │ ├── error_translator.go
│ │ │ │ ├── migrator.go
│ │ │ │ └── mysql.go
│ │ │ └── pgsql/
│ │ │ ├── error_translator.go
│ │ │ ├── migrator.go
│ │ │ └── postgres.go
│ │ ├── errors.go
│ │ ├── finisher_api.go
│ │ ├── gorm.go
│ │ ├── inflection/
│ │ │ └── inflections.go
│ │ ├── interfaces.go
│ │ ├── logger/
│ │ │ ├── logger.go
│ │ │ └── sql.go
│ │ ├── migrator/
│ │ │ ├── column_type.go
│ │ │ ├── index.go
│ │ │ ├── migrator.go
│ │ │ └── table_type.go
│ │ ├── migrator.go
│ │ ├── model.go
│ │ ├── now/
│ │ │ ├── main.go
│ │ │ ├── now.go
│ │ │ └── time.go
│ │ ├── prepare_stmt.go
│ │ ├── scan.go
│ │ ├── schema/
│ │ │ ├── constraint.go
│ │ │ ├── field.go
│ │ │ ├── index.go
│ │ │ ├── interfaces.go
│ │ │ ├── naming.go
│ │ │ ├── pool.go
│ │ │ ├── relationship.go
│ │ │ ├── schema.go
│ │ │ ├── serializer.go
│ │ │ └── utils.go
│ │ ├── soft_delete.go
│ │ ├── statement.go
│ │ └── utils/
│ │ ├── tests/
│ │ │ ├── dummy_dialecter.go
│ │ │ ├── models.go
│ │ │ └── utils.go
│ │ └── utils.go
│ ├── main.go
│ ├── mysql/
│ │ ├── atomic_bool.go
│ │ ├── atomic_bool_go118.go
│ │ ├── auth.go
│ │ ├── buffer.go
│ │ ├── collations.go
│ │ ├── conncheck.go
│ │ ├── conncheck_dummy.go
│ │ ├── connection.go
│ │ ├── connector.go
│ │ ├── const.go
│ │ ├── driver.go
│ │ ├── dsn.go
│ │ ├── errors.go
│ │ ├── fields.go
│ │ ├── infile.go
│ │ ├── nulltime.go
│ │ ├── packets.go
│ │ ├── result.go
│ │ ├── rows.go
│ │ ├── statement.go
│ │ ├── transaction.go
│ │ └── utils.go
│ ├── pgsql/
│ │ ├── array.go
│ │ ├── buf.go
│ │ ├── conn.go
│ │ ├── conn_go115.go
│ │ ├── conn_go18.go
│ │ ├── connector.go
│ │ ├── copy.go
│ │ ├── encode.go
│ │ ├── error.go
│ │ ├── hstore/
│ │ │ └── hstore.go
│ │ ├── krb.go
│ │ ├── notice.go
│ │ ├── notify.go
│ │ ├── oid/
│ │ │ ├── doc.go
│ │ │ ├── gen.go
│ │ │ └── types.go
│ │ ├── rows.go
│ │ ├── scram/
│ │ │ └── scram.go
│ │ ├── ssl.go
│ │ ├── ssl_permissions.go
│ │ ├── ssl_windows.go
│ │ ├── url.go
│ │ ├── user_other.go
│ │ ├── user_posix.go
│ │ ├── user_windows.go
│ │ └── uuid.go
│ ├── pty/
│ │ ├── asm_solaris_amd64.s
│ │ ├── cmd_windows.go
│ │ ├── doc.go
│ │ ├── ioctl.go
│ │ ├── ioctl_bsd.go
│ │ ├── ioctl_inner.go
│ │ ├── ioctl_legacy.go
│ │ ├── ioctl_solaris.go
│ │ ├── ioctl_unsupported.go
│ │ ├── pty_darwin.go
│ │ ├── pty_dragonfly.go
│ │ ├── pty_freebsd.go
│ │ ├── pty_linux.go
│ │ ├── pty_netbsd.go
│ │ ├── pty_openbsd.go
│ │ ├── pty_solaris.go
│ │ ├── pty_unsupported.go
│ │ ├── pty_windows.go
│ │ ├── run.go
│ │ ├── run_unix.go
│ │ ├── run_windows.go
│ │ ├── types.go
│ │ ├── types_dragonfly.go
│ │ ├── types_freebsd.go
│ │ ├── types_netbsd.go
│ │ ├── types_openbsd.go
│ │ ├── winsize.go
│ │ ├── winsize_unix.go
│ │ ├── winsize_windows.go
│ │ ├── ztypes_386.go
│ │ ├── ztypes_amd64.go
│ │ ├── ztypes_arm.go
│ │ ├── ztypes_arm64.go
│ │ ├── ztypes_dragonfly_amd64.go
│ │ ├── ztypes_freebsd_386.go
│ │ ├── ztypes_freebsd_amd64.go
│ │ ├── ztypes_freebsd_arm.go
│ │ ├── ztypes_freebsd_arm64.go
│ │ ├── ztypes_freebsd_ppc64.go
│ │ ├── ztypes_freebsd_riscv64.go
│ │ ├── ztypes_loong64.go
│ │ ├── ztypes_mipsx.go
│ │ ├── ztypes_netbsd_32bit_int.go
│ │ ├── ztypes_openbsd_32bit_int.go
│ │ ├── ztypes_ppc.go
│ │ ├── ztypes_ppc64.go
│ │ ├── ztypes_ppc64le.go
│ │ ├── ztypes_riscvx.go
│ │ ├── ztypes_s390x.go
│ │ └── ztypes_sparcx.go
│ ├── readme.md
│ ├── sftp/
│ │ ├── allocator.go
│ │ ├── attrs.go
│ │ ├── attrs_stubs.go
│ │ ├── attrs_unix.go
│ │ ├── client.go
│ │ ├── conn.go
│ │ ├── debug.go
│ │ ├── fuzz.go
│ │ ├── internal/
│ │ │ ├── encoding/
│ │ │ │ └── ssh/
│ │ │ │ └── filexfer/
│ │ │ │ ├── attrs.go
│ │ │ │ ├── buffer.go
│ │ │ │ ├── extended_packets.go
│ │ │ │ ├── extensions.go
│ │ │ │ ├── filexfer.go
│ │ │ │ ├── fx.go
│ │ │ │ ├── fxp.go
│ │ │ │ ├── handle_packets.go
│ │ │ │ ├── init_packets.go
│ │ │ │ ├── open_packets.go
│ │ │ │ ├── openssh/
│ │ │ │ │ ├── fsync.go
│ │ │ │ │ ├── hardlink.go
│ │ │ │ │ ├── openssh.go
│ │ │ │ │ ├── posix-rename.go
│ │ │ │ │ └── statvfs.go
│ │ │ │ ├── packets.go
│ │ │ │ ├── path_packets.go
│ │ │ │ ├── permissions.go
│ │ │ │ └── response_packets.go
│ │ │ └── sftpfs/
│ │ │ ├── filesystem.go
│ │ │ └── walk.go
│ │ ├── ls_formatting.go
│ │ ├── ls_plan9.go
│ │ ├── ls_stub.go
│ │ ├── ls_unix.go
│ │ ├── match.go
│ │ ├── packet-manager.go
│ │ ├── packet-typing.go
│ │ ├── packet.go
│ │ ├── pool.go
│ │ ├── release.go
│ │ ├── request-attrs.go
│ │ ├── request-errors.go
│ │ ├── request-example.go
│ │ ├── request-interfaces.go
│ │ ├── request-plan9.go
│ │ ├── request-server.go
│ │ ├── request-unix.go
│ │ ├── request.go
│ │ ├── request_windows.go
│ │ ├── server.go
│ │ ├── server_plan9.go
│ │ ├── server_statvfs_darwin.go
│ │ ├── server_statvfs_impl.go
│ │ ├── server_statvfs_linux.go
│ │ ├── server_statvfs_plan9.go
│ │ ├── server_statvfs_stubs.go
│ │ ├── server_unix.go
│ │ ├── server_windows.go
│ │ ├── sftp.go
│ │ ├── stat_plan9.go
│ │ ├── stat_posix.go
│ │ ├── syscall_fixed.go
│ │ └── syscall_good.go
│ ├── sqlite/
│ │ ├── ddlmod.go
│ │ ├── errors.go
│ │ ├── migrator.go
│ │ └── sqlite.go
│ ├── sys/
│ │ ├── cpu/
│ │ │ ├── asm_aix_ppc64.s
│ │ │ ├── byteorder.go
│ │ │ ├── cpu.go
│ │ │ ├── cpu_aix.go
│ │ │ ├── cpu_arm.go
│ │ │ ├── cpu_arm64.go
│ │ │ ├── cpu_arm64.s
│ │ │ ├── cpu_gc_arm64.go
│ │ │ ├── cpu_gc_s390x.go
│ │ │ ├── cpu_gc_x86.go
│ │ │ ├── cpu_gccgo_arm64.go
│ │ │ ├── cpu_gccgo_s390x.go
│ │ │ ├── cpu_gccgo_x86.c
│ │ │ ├── cpu_gccgo_x86.go
│ │ │ ├── cpu_linux.go
│ │ │ ├── cpu_linux_arm.go
│ │ │ ├── cpu_linux_arm64.go
│ │ │ ├── cpu_linux_mips64x.go
│ │ │ ├── cpu_linux_noinit.go
│ │ │ ├── cpu_linux_ppc64x.go
│ │ │ ├── cpu_linux_s390x.go
│ │ │ ├── cpu_loong64.go
│ │ │ ├── cpu_mips64x.go
│ │ │ ├── cpu_mipsx.go
│ │ │ ├── cpu_netbsd_arm64.go
│ │ │ ├── cpu_openbsd_arm64.go
│ │ │ ├── cpu_openbsd_arm64.s
│ │ │ ├── cpu_other_arm.go
│ │ │ ├── cpu_other_arm64.go
│ │ │ ├── cpu_other_mips64x.go
│ │ │ ├── cpu_other_ppc64x.go
│ │ │ ├── cpu_other_riscv64.go
│ │ │ ├── cpu_ppc64x.go
│ │ │ ├── cpu_riscv64.go
│ │ │ ├── cpu_s390x.go
│ │ │ ├── cpu_s390x.s
│ │ │ ├── cpu_wasm.go
│ │ │ ├── cpu_x86.go
│ │ │ ├── cpu_x86.s
│ │ │ ├── cpu_zos.go
│ │ │ ├── cpu_zos_s390x.go
│ │ │ ├── endian_big.go
│ │ │ ├── endian_little.go
│ │ │ ├── hwcap_linux.go
│ │ │ ├── parse.go
│ │ │ ├── proc_cpuinfo_linux.go
│ │ │ ├── runtime_auxv.go
│ │ │ ├── runtime_auxv_go121.go
│ │ │ ├── syscall_aix_gccgo.go
│ │ │ └── syscall_aix_ppc64_gc.go
│ │ ├── execabs/
│ │ │ ├── execabs.go
│ │ │ ├── execabs_go118.go
│ │ │ └── execabs_go119.go
│ │ ├── plan9/
│ │ │ ├── asm.s
│ │ │ ├── asm_plan9_386.s
│ │ │ ├── asm_plan9_amd64.s
│ │ │ ├── asm_plan9_arm.s
│ │ │ ├── const_plan9.go
│ │ │ ├── dir_plan9.go
│ │ │ ├── env_plan9.go
│ │ │ ├── errors_plan9.go
│ │ │ ├── mkall.sh
│ │ │ ├── mkerrors.sh
│ │ │ ├── mksyscall.go
│ │ │ ├── mksysnum_plan9.sh
│ │ │ ├── pwd_go15_plan9.go
│ │ │ ├── pwd_plan9.go
│ │ │ ├── race.go
│ │ │ ├── race0.go
│ │ │ ├── str.go
│ │ │ ├── syscall.go
│ │ │ ├── syscall_plan9.go
│ │ │ ├── zsyscall_plan9_386.go
│ │ │ ├── zsyscall_plan9_amd64.go
│ │ │ ├── zsyscall_plan9_arm.go
│ │ │ └── zsysnum_plan9.go
│ │ ├── unix/
│ │ │ ├── README.md
│ │ │ ├── affinity_linux.go
│ │ │ ├── aliases.go
│ │ │ ├── asm_aix_ppc64.s
│ │ │ ├── asm_bsd_386.s
│ │ │ ├── asm_bsd_amd64.s
│ │ │ ├── asm_bsd_arm.s
│ │ │ ├── asm_bsd_arm64.s
│ │ │ ├── asm_bsd_ppc64.s
│ │ │ ├── asm_bsd_riscv64.s
│ │ │ ├── asm_linux_386.s
│ │ │ ├── asm_linux_amd64.s
│ │ │ ├── asm_linux_arm.s
│ │ │ ├── asm_linux_arm64.s
│ │ │ ├── asm_linux_loong64.s
│ │ │ ├── asm_linux_mips64x.s
│ │ │ ├── asm_linux_mipsx.s
│ │ │ ├── asm_linux_ppc64x.s
│ │ │ ├── asm_linux_riscv64.s
│ │ │ ├── asm_linux_s390x.s
│ │ │ ├── asm_openbsd_mips64.s
│ │ │ ├── asm_solaris_amd64.s
│ │ │ ├── asm_zos_s390x.s
│ │ │ ├── bluetooth_linux.go
│ │ │ ├── cap_freebsd.go
│ │ │ ├── constants.go
│ │ │ ├── dev_aix_ppc.go
│ │ │ ├── dev_aix_ppc64.go
│ │ │ ├── dev_darwin.go
│ │ │ ├── dev_dragonfly.go
│ │ │ ├── dev_freebsd.go
│ │ │ ├── dev_linux.go
│ │ │ ├── dev_netbsd.go
│ │ │ ├── dev_openbsd.go
│ │ │ ├── dev_zos.go
│ │ │ ├── dirent.go
│ │ │ ├── endian_big.go
│ │ │ ├── endian_little.go
│ │ │ ├── env_unix.go
│ │ │ ├── epoll_zos.go
│ │ │ ├── fcntl.go
│ │ │ ├── fcntl_darwin.go
│ │ │ ├── fcntl_linux_32bit.go
│ │ │ ├── fdset.go
│ │ │ ├── fstatfs_zos.go
│ │ │ ├── gccgo.go
│ │ │ ├── gccgo_c.c
│ │ │ ├── gccgo_linux_amd64.go
│ │ │ ├── ifreq_linux.go
│ │ │ ├── internal/
│ │ │ │ └── mkmerge/
│ │ │ │ └── mkmerge.go
│ │ │ ├── ioctl_linux.go
│ │ │ ├── ioctl_signed.go
│ │ │ ├── ioctl_unsigned.go
│ │ │ ├── ioctl_zos.go
│ │ │ ├── linux/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── mkall.go
│ │ │ │ ├── mksysnum.go
│ │ │ │ └── types.go
│ │ │ ├── mkall.sh
│ │ │ ├── mkasm.go
│ │ │ ├── mkerrors.sh
│ │ │ ├── mkpost.go
│ │ │ ├── mksyscall.go
│ │ │ ├── mksyscall_aix_ppc.go
│ │ │ ├── mksyscall_aix_ppc64.go
│ │ │ ├── mksyscall_solaris.go
│ │ │ ├── mksysctl_openbsd.go
│ │ │ ├── mksysnum.go
│ │ │ ├── mmap_nomremap.go
│ │ │ ├── mremap.go
│ │ │ ├── pagesize_unix.go
│ │ │ ├── pledge_openbsd.go
│ │ │ ├── ptrace_darwin.go
│ │ │ ├── ptrace_ios.go
│ │ │ ├── race.go
│ │ │ ├── race0.go
│ │ │ ├── readdirent_getdents.go
│ │ │ ├── readdirent_getdirentries.go
│ │ │ ├── sockcmsg_dragonfly.go
│ │ │ ├── sockcmsg_linux.go
│ │ │ ├── sockcmsg_unix.go
│ │ │ ├── sockcmsg_unix_other.go
│ │ │ ├── syscall.go
│ │ │ ├── syscall_aix.go
│ │ │ ├── syscall_aix_ppc.go
│ │ │ ├── syscall_aix_ppc64.go
│ │ │ ├── syscall_bsd.go
│ │ │ ├── syscall_darwin.go
│ │ │ ├── syscall_darwin_amd64.go
│ │ │ ├── syscall_darwin_arm64.go
│ │ │ ├── syscall_darwin_libSystem.go
│ │ │ ├── syscall_dragonfly.go
│ │ │ ├── syscall_dragonfly_amd64.go
│ │ │ ├── syscall_freebsd.go
│ │ │ ├── syscall_freebsd_386.go
│ │ │ ├── syscall_freebsd_amd64.go
│ │ │ ├── syscall_freebsd_arm.go
│ │ │ ├── syscall_freebsd_arm64.go
│ │ │ ├── syscall_freebsd_riscv64.go
│ │ │ ├── syscall_hurd.go
│ │ │ ├── syscall_hurd_386.go
│ │ │ ├── syscall_illumos.go
│ │ │ ├── syscall_linux.go
│ │ │ ├── syscall_linux_386.go
│ │ │ ├── syscall_linux_alarm.go
│ │ │ ├── syscall_linux_amd64.go
│ │ │ ├── syscall_linux_amd64_gc.go
│ │ │ ├── syscall_linux_arm.go
│ │ │ ├── syscall_linux_arm64.go
│ │ │ ├── syscall_linux_gc.go
│ │ │ ├── syscall_linux_gc_386.go
│ │ │ ├── syscall_linux_gc_arm.go
│ │ │ ├── syscall_linux_gccgo_386.go
│ │ │ ├── syscall_linux_gccgo_arm.go
│ │ │ ├── syscall_linux_loong64.go
│ │ │ ├── syscall_linux_mips64x.go
│ │ │ ├── syscall_linux_mipsx.go
│ │ │ ├── syscall_linux_ppc.go
│ │ │ ├── syscall_linux_ppc64x.go
│ │ │ ├── syscall_linux_riscv64.go
│ │ │ ├── syscall_linux_s390x.go
│ │ │ ├── syscall_linux_sparc64.go
│ │ │ ├── syscall_netbsd.go
│ │ │ ├── syscall_netbsd_386.go
│ │ │ ├── syscall_netbsd_amd64.go
│ │ │ ├── syscall_netbsd_arm.go
│ │ │ ├── syscall_netbsd_arm64.go
│ │ │ ├── syscall_openbsd.go
│ │ │ ├── syscall_openbsd_386.go
│ │ │ ├── syscall_openbsd_amd64.go
│ │ │ ├── syscall_openbsd_arm.go
│ │ │ ├── syscall_openbsd_arm64.go
│ │ │ ├── syscall_openbsd_libc.go
│ │ │ ├── syscall_openbsd_mips64.go
│ │ │ ├── syscall_openbsd_ppc64.go
│ │ │ ├── syscall_openbsd_riscv64.go
│ │ │ ├── syscall_solaris.go
│ │ │ ├── syscall_solaris_amd64.go
│ │ │ ├── syscall_unix.go
│ │ │ ├── syscall_unix_gc.go
│ │ │ ├── syscall_unix_gc_ppc64x.go
│ │ │ ├── syscall_zos_s390x.go
│ │ │ ├── sysvshm_linux.go
│ │ │ ├── sysvshm_unix.go
│ │ │ ├── sysvshm_unix_other.go
│ │ │ ├── timestruct.go
│ │ │ ├── types_aix.go
│ │ │ ├── types_darwin.go
│ │ │ ├── types_dragonfly.go
│ │ │ ├── types_freebsd.go
│ │ │ ├── types_netbsd.go
│ │ │ ├── types_openbsd.go
│ │ │ ├── types_solaris.go
│ │ │ ├── unveil_openbsd.go
│ │ │ ├── xattr_bsd.go
│ │ │ ├── zerrors_aix_ppc.go
│ │ │ ├── zerrors_aix_ppc64.go
│ │ │ ├── zerrors_darwin_amd64.go
│ │ │ ├── zerrors_darwin_arm64.go
│ │ │ ├── zerrors_dragonfly_amd64.go
│ │ │ ├── zerrors_freebsd_386.go
│ │ │ ├── zerrors_freebsd_amd64.go
│ │ │ ├── zerrors_freebsd_arm.go
│ │ │ ├── zerrors_freebsd_arm64.go
│ │ │ ├── zerrors_freebsd_riscv64.go
│ │ │ ├── zerrors_linux.go
│ │ │ ├── zerrors_linux_386.go
│ │ │ ├── zerrors_linux_amd64.go
│ │ │ ├── zerrors_linux_arm.go
│ │ │ ├── zerrors_linux_arm64.go
│ │ │ ├── zerrors_linux_loong64.go
│ │ │ ├── zerrors_linux_mips.go
│ │ │ ├── zerrors_linux_mips64.go
│ │ │ ├── zerrors_linux_mips64le.go
│ │ │ ├── zerrors_linux_mipsle.go
│ │ │ ├── zerrors_linux_ppc.go
│ │ │ ├── zerrors_linux_ppc64.go
│ │ │ ├── zerrors_linux_ppc64le.go
│ │ │ ├── zerrors_linux_riscv64.go
│ │ │ ├── zerrors_linux_s390x.go
│ │ │ ├── zerrors_linux_sparc64.go
│ │ │ ├── zerrors_netbsd_386.go
│ │ │ ├── zerrors_netbsd_amd64.go
│ │ │ ├── zerrors_netbsd_arm.go
│ │ │ ├── zerrors_netbsd_arm64.go
│ │ │ ├── zerrors_openbsd_386.go
│ │ │ ├── zerrors_openbsd_amd64.go
│ │ │ ├── zerrors_openbsd_arm.go
│ │ │ ├── zerrors_openbsd_arm64.go
│ │ │ ├── zerrors_openbsd_mips64.go
│ │ │ ├── zerrors_openbsd_ppc64.go
│ │ │ ├── zerrors_openbsd_riscv64.go
│ │ │ ├── zerrors_solaris_amd64.go
│ │ │ ├── zerrors_zos_s390x.go
│ │ │ ├── zptrace_armnn_linux.go
│ │ │ ├── zptrace_linux_arm64.go
│ │ │ ├── zptrace_mipsnn_linux.go
│ │ │ ├── zptrace_mipsnnle_linux.go
│ │ │ ├── zptrace_x86_linux.go
│ │ │ ├── zsyscall_aix_ppc.go
│ │ │ ├── zsyscall_aix_ppc64.go
│ │ │ ├── zsyscall_aix_ppc64_gc.go
│ │ │ ├── zsyscall_aix_ppc64_gccgo.go
│ │ │ ├── zsyscall_darwin_amd64.go
│ │ │ ├── zsyscall_darwin_amd64.s
│ │ │ ├── zsyscall_darwin_arm64.go
│ │ │ ├── zsyscall_darwin_arm64.s
│ │ │ ├── zsyscall_dragonfly_amd64.go
│ │ │ ├── zsyscall_freebsd_386.go
│ │ │ ├── zsyscall_freebsd_amd64.go
│ │ │ ├── zsyscall_freebsd_arm.go
│ │ │ ├── zsyscall_freebsd_arm64.go
│ │ │ ├── zsyscall_freebsd_riscv64.go
│ │ │ ├── zsyscall_illumos_amd64.go
│ │ │ ├── zsyscall_linux.go
│ │ │ ├── zsyscall_linux_386.go
│ │ │ ├── zsyscall_linux_amd64.go
│ │ │ ├── zsyscall_linux_arm.go
│ │ │ ├── zsyscall_linux_arm64.go
│ │ │ ├── zsyscall_linux_loong64.go
│ │ │ ├── zsyscall_linux_mips.go
│ │ │ ├── zsyscall_linux_mips64.go
│ │ │ ├── zsyscall_linux_mips64le.go
│ │ │ ├── zsyscall_linux_mipsle.go
│ │ │ ├── zsyscall_linux_ppc.go
│ │ │ ├── zsyscall_linux_ppc64.go
│ │ │ ├── zsyscall_linux_ppc64le.go
│ │ │ ├── zsyscall_linux_riscv64.go
│ │ │ ├── zsyscall_linux_s390x.go
│ │ │ ├── zsyscall_linux_sparc64.go
│ │ │ ├── zsyscall_netbsd_386.go
│ │ │ ├── zsyscall_netbsd_amd64.go
│ │ │ ├── zsyscall_netbsd_arm.go
│ │ │ ├── zsyscall_netbsd_arm64.go
│ │ │ ├── zsyscall_openbsd_386.go
│ │ │ ├── zsyscall_openbsd_386.s
│ │ │ ├── zsyscall_openbsd_amd64.go
│ │ │ ├── zsyscall_openbsd_amd64.s
│ │ │ ├── zsyscall_openbsd_arm.go
│ │ │ ├── zsyscall_openbsd_arm.s
│ │ │ ├── zsyscall_openbsd_arm64.go
│ │ │ ├── zsyscall_openbsd_arm64.s
│ │ │ ├── zsyscall_openbsd_mips64.go
│ │ │ ├── zsyscall_openbsd_mips64.s
│ │ │ ├── zsyscall_openbsd_ppc64.go
│ │ │ ├── zsyscall_openbsd_ppc64.s
│ │ │ ├── zsyscall_openbsd_riscv64.go
│ │ │ ├── zsyscall_openbsd_riscv64.s
│ │ │ ├── zsyscall_solaris_amd64.go
│ │ │ ├── zsyscall_zos_s390x.go
│ │ │ ├── zsysctl_openbsd_386.go
│ │ │ ├── zsysctl_openbsd_amd64.go
│ │ │ ├── zsysctl_openbsd_arm.go
│ │ │ ├── zsysctl_openbsd_arm64.go
│ │ │ ├── zsysctl_openbsd_mips64.go
│ │ │ ├── zsysctl_openbsd_ppc64.go
│ │ │ ├── zsysctl_openbsd_riscv64.go
│ │ │ ├── zsysnum_darwin_amd64.go
│ │ │ ├── zsysnum_darwin_arm64.go
│ │ │ ├── zsysnum_dragonfly_amd64.go
│ │ │ ├── zsysnum_freebsd_386.go
│ │ │ ├── zsysnum_freebsd_amd64.go
│ │ │ ├── zsysnum_freebsd_arm.go
│ │ │ ├── zsysnum_freebsd_arm64.go
│ │ │ ├── zsysnum_freebsd_riscv64.go
│ │ │ ├── zsysnum_linux_386.go
│ │ │ ├── zsysnum_linux_amd64.go
│ │ │ ├── zsysnum_linux_arm.go
│ │ │ ├── zsysnum_linux_arm64.go
│ │ │ ├── zsysnum_linux_loong64.go
│ │ │ ├── zsysnum_linux_mips.go
│ │ │ ├── zsysnum_linux_mips64.go
│ │ │ ├── zsysnum_linux_mips64le.go
│ │ │ ├── zsysnum_linux_mipsle.go
│ │ │ ├── zsysnum_linux_ppc.go
│ │ │ ├── zsysnum_linux_ppc64.go
│ │ │ ├── zsysnum_linux_ppc64le.go
│ │ │ ├── zsysnum_linux_riscv64.go
│ │ │ ├── zsysnum_linux_s390x.go
│ │ │ ├── zsysnum_linux_sparc64.go
│ │ │ ├── zsysnum_netbsd_386.go
│ │ │ ├── zsysnum_netbsd_amd64.go
│ │ │ ├── zsysnum_netbsd_arm.go
│ │ │ ├── zsysnum_netbsd_arm64.go
│ │ │ ├── zsysnum_openbsd_386.go
│ │ │ ├── zsysnum_openbsd_amd64.go
│ │ │ ├── zsysnum_openbsd_arm.go
│ │ │ ├── zsysnum_openbsd_arm64.go
│ │ │ ├── zsysnum_openbsd_mips64.go
│ │ │ ├── zsysnum_openbsd_ppc64.go
│ │ │ ├── zsysnum_openbsd_riscv64.go
│ │ │ ├── zsysnum_zos_s390x.go
│ │ │ ├── ztypes_aix_ppc.go
│ │ │ ├── ztypes_aix_ppc64.go
│ │ │ ├── ztypes_darwin_amd64.go
│ │ │ ├── ztypes_darwin_arm64.go
│ │ │ ├── ztypes_dragonfly_amd64.go
│ │ │ ├── ztypes_freebsd_386.go
│ │ │ ├── ztypes_freebsd_amd64.go
│ │ │ ├── ztypes_freebsd_arm.go
│ │ │ ├── ztypes_freebsd_arm64.go
│ │ │ ├── ztypes_freebsd_riscv64.go
│ │ │ ├── ztypes_linux.go
│ │ │ ├── ztypes_linux_386.go
│ │ │ ├── ztypes_linux_amd64.go
│ │ │ ├── ztypes_linux_arm.go
│ │ │ ├── ztypes_linux_arm64.go
│ │ │ ├── ztypes_linux_loong64.go
│ │ │ ├── ztypes_linux_mips.go
│ │ │ ├── ztypes_linux_mips64.go
│ │ │ ├── ztypes_linux_mips64le.go
│ │ │ ├── ztypes_linux_mipsle.go
│ │ │ ├── ztypes_linux_ppc.go
│ │ │ ├── ztypes_linux_ppc64.go
│ │ │ ├── ztypes_linux_ppc64le.go
│ │ │ ├── ztypes_linux_riscv64.go
│ │ │ ├── ztypes_linux_s390x.go
│ │ │ ├── ztypes_linux_sparc64.go
│ │ │ ├── ztypes_netbsd_386.go
│ │ │ ├── ztypes_netbsd_amd64.go
│ │ │ ├── ztypes_netbsd_arm.go
│ │ │ ├── ztypes_netbsd_arm64.go
│ │ │ ├── ztypes_openbsd_386.go
│ │ │ ├── ztypes_openbsd_amd64.go
│ │ │ ├── ztypes_openbsd_arm.go
│ │ │ ├── ztypes_openbsd_arm64.go
│ │ │ ├── ztypes_openbsd_mips64.go
│ │ │ ├── ztypes_openbsd_ppc64.go
│ │ │ ├── ztypes_openbsd_riscv64.go
│ │ │ ├── ztypes_solaris_amd64.go
│ │ │ └── ztypes_zos_s390x.go
│ │ ├── websocket/
│ │ │ ├── client.go
│ │ │ ├── dial.go
│ │ │ ├── hybi.go
│ │ │ ├── server.go
│ │ │ └── websocket.go
│ │ └── windows/
│ │ ├── aliases.go
│ │ ├── dll_windows.go
│ │ ├── empty.s
│ │ ├── env_windows.go
│ │ ├── eventlog.go
│ │ ├── exec_windows.go
│ │ ├── memory_windows.go
│ │ ├── mkerrors.bash
│ │ ├── mkknownfolderids.bash
│ │ ├── mksyscall.go
│ │ ├── mkwinsyscall/
│ │ │ └── mkwinsyscall.go
│ │ ├── race.go
│ │ ├── race0.go
│ │ ├── registry/
│ │ │ ├── key.go
│ │ │ ├── mksyscall.go
│ │ │ ├── syscall.go
│ │ │ ├── value.go
│ │ │ └── zsyscall_windows.go
│ │ ├── security_windows.go
│ │ ├── service.go
│ │ ├── setupapi_windows.go
│ │ ├── str.go
│ │ ├── svc/
│ │ │ ├── debug/
│ │ │ │ ├── log.go
│ │ │ │ └── service.go
│ │ │ ├── eventlog/
│ │ │ │ ├── install.go
│ │ │ │ └── log.go
│ │ │ ├── mgr/
│ │ │ │ ├── config.go
│ │ │ │ ├── mgr.go
│ │ │ │ ├── recovery.go
│ │ │ │ └── service.go
│ │ │ ├── security.go
│ │ │ └── service.go
│ │ ├── syscall.go
│ │ ├── syscall_windows.go
│ │ ├── types_windows.go
│ │ ├── types_windows_386.go
│ │ ├── types_windows_amd64.go
│ │ ├── types_windows_arm.go
│ │ ├── types_windows_arm64.go
│ │ ├── zerrors_windows.go
│ │ ├── zknownfolderids_windows.go
│ │ └── zsyscall_windows.go
│ ├── term/
│ │ ├── term.go
│ │ ├── term_plan9.go
│ │ ├── term_unix.go
│ │ ├── term_unix_bsd.go
│ │ ├── term_unix_other.go
│ │ ├── term_unsupported.go
│ │ ├── term_windows.go
│ │ └── terminal.go
│ ├── toml/
│ │ ├── README.md
│ │ ├── decode.go
│ │ ├── errors.go
│ │ ├── internal/
│ │ │ ├── characters/
│ │ │ │ ├── ascii.go
│ │ │ │ └── utf8.go
│ │ │ ├── cli/
│ │ │ │ └── cli.go
│ │ │ ├── danger/
│ │ │ │ ├── danger.go
│ │ │ │ └── typeid.go
│ │ │ ├── testsuite/
│ │ │ │ ├── add.go
│ │ │ │ ├── json.go
│ │ │ │ ├── parser.go
│ │ │ │ ├── rm.go
│ │ │ │ └── testsuite.go
│ │ │ └── tracker/
│ │ │ ├── key.go
│ │ │ ├── seen.go
│ │ │ └── tracker.go
│ │ ├── localtime.go
│ │ ├── marshaler.go
│ │ ├── strict.go
│ │ ├── types.go
│ │ ├── unmarshaler.go
│ │ └── unstable/
│ │ ├── ast.go
│ │ ├── builder.go
│ │ ├── doc.go
│ │ ├── kind.go
│ │ ├── parser.go
│ │ ├── scanner.go
│ │ └── unmarshaler.go
│ ├── webroot/
│ │ ├── assets/
│ │ │ ├── About-BpAaEtx1.js
│ │ │ ├── About-CLFeE-IU.css
│ │ │ ├── Manage-BTEK3ejV.css
│ │ │ ├── Manage-D_HsZWaT.js
│ │ │ ├── NotFound-Ts0Rt7lc.js
│ │ │ ├── SysInit-Lho0-Z3X.css
│ │ │ ├── SysInit-UcmoR0-x.js
│ │ │ ├── el-card-fwQOLwdi.css
│ │ │ ├── index-D6GWZ696.css
│ │ │ └── index-jH42E5tC.js
│ │ ├── index.html
│ │ └── readme.md
│ └── websocket/
│ ├── client.go
│ ├── compression.go
│ ├── conn.go
│ ├── doc.go
│ ├── join.go
│ ├── json.go
│ ├── mask.go
│ ├── mask_safe.go
│ ├── prepared.go
│ ├── proxy.go
│ ├── server.go
│ └── util.go
├── postman.json
├── sshd.dockerfile
└── webssh/
├── .gitignore
├── README.md
├── auto-imports.d.ts
├── components.d.ts
├── env.d.ts
├── index.html
├── package.json
├── src/
│ ├── App.vue
│ ├── components/
│ │ ├── Account.vue
│ │ ├── Connect.vue
│ │ ├── LoginAudit.vue
│ │ ├── NetFilter.vue
│ │ ├── SshdCert.vue
│ │ └── SshdUser.vue
│ ├── main.ts
│ ├── router/
│ │ └── index.ts
│ ├── stores/
│ │ └── store.ts
│ └── views/
│ ├── About.vue
│ ├── Empty.vue
│ ├── Home.vue
│ ├── Login.vue
│ ├── Manage.vue
│ ├── NotFound.vue
│ └── SysInit.vue
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
Showing preview only (9,216K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (107986 symbols across 865 files)
FILE: gossh/app/config/config.go
type AppConfig (line 13) | type AppConfig struct
method write (line 31) | func (c *AppConfig) write() error {
function InitConfig (line 77) | func InitConfig() {
function RewriteConfig (line 144) | func RewriteConfig(conf AppConfig) error {
FILE: gossh/app/middleware/db_check.go
function DbCheck (line 9) | func DbCheck() gin.HandlerFunc {
FILE: gossh/app/middleware/jwt_auth.go
type JwtClaims (line 15) | type JwtClaims struct
function GenerateToken (line 24) | func GenerateToken(id uint) (string, error) {
function ParseToken (line 46) | func ParseToken(tokenString string) (*JwtClaims, error) {
function RenewToken (line 55) | func RenewToken(claims *JwtClaims) (string, error) {
function withinLimit (line 64) | func withinLimit(s, l int64) bool {
function JWTAuth (line 68) | func JWTAuth() gin.HandlerFunc {
FILE: gossh/app/middleware/net_filter.go
function check (line 12) | func check(ip net.IP) bool {
function NetFilter (line 67) | func NetFilter() gin.HandlerFunc {
FILE: gossh/app/middleware/perm_check.go
function PremCheck (line 83) | func PremCheck(engine *gin.Engine) gin.HandlerFunc {
FILE: gossh/app/middleware/sys_init.go
function SysInit (line 8) | func SysInit() gin.HandlerFunc {
FILE: gossh/app/model/cmd_note.go
type CmdNote (line 3) | type CmdNote struct
method Create (line 13) | func (c CmdNote) Create(cmd *CmdNote) error {
method FindByName (line 17) | func (c CmdNote) FindByName(name string) (CmdNote, error) {
method FindByID (line 23) | func (c CmdNote) FindByID(id uint, uid uint) (CmdNote, error) {
method FindAll (line 29) | func (c CmdNote) FindAll(offset, limit int, uid uint) ([]CmdNote, erro...
method UpdateById (line 35) | func (c CmdNote) UpdateById(id, uid uint, cmd *CmdNote) error {
method DeleteByID (line 39) | func (c CmdNote) DeleteByID(id, uid uint) error {
FILE: gossh/app/model/datetime.go
constant TimeFormat (line 10) | TimeFormat = "2006-01-02 15:04:05"
type DateTime (line 13) | type DateTime
method MarshalJSON (line 24) | func (t DateTime) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 28) | func (t *DateTime) UnmarshalJSON(b []byte) error {
method Value (line 36) | func (t DateTime) Value() (driver.Value, error) {
method Scan (line 43) | func (t *DateTime) Scan(v any) error {
method ToTime (line 52) | func (t *DateTime) ToTime() time.Time {
method String (line 56) | func (t DateTime) String() string {
function NewDateTime (line 15) | func NewDateTime(str string) (DateTime, error) {
FILE: gossh/app/model/db_init.go
function InitDatabase (line 22) | func InitDatabase() {
function GetSqliteDb (line 33) | func GetSqliteDb(dsn string) (*gorm.DB, error) {
function DbMigrate (line 63) | func DbMigrate(dbType, dsn string) error {
FILE: gossh/app/model/login_audit.go
type LoginAudit (line 3) | type LoginAudit struct
method Create (line 17) | func (c LoginAudit) Create(audit *LoginAudit) error {
method Search (line 21) | func (c LoginAudit) Search(
method FindByID (line 48) | func (c LoginAudit) FindByID(id uint) (LoginAudit, error) {
method DeleteByID (line 54) | func (c LoginAudit) DeleteByID(id uint) error {
FILE: gossh/app/model/net_filter.go
type NetFilter (line 5) | type NetFilter struct
method Create (line 17) | func (c NetFilter) Create(filter *NetFilter) error {
method FindByName (line 21) | func (c NetFilter) FindByName(name string) (NetFilter, error) {
method FindByID (line 27) | func (c NetFilter) FindByID(id uint) (NetFilter, error) {
method FindAll (line 33) | func (c NetFilter) FindAll(offset, limit int) ([]NetFilter, error) {
method FindAllPolicy (line 39) | func (c NetFilter) FindAllPolicy(policy string) ([]NetFilter, error) {
method UpdateById (line 45) | func (c NetFilter) UpdateById(id uint, filter *NetFilter) error {
method DeleteByID (line 49) | func (c NetFilter) DeleteByID(id uint) error {
FILE: gossh/app/model/policy_conf.go
type PolicyConf (line 3) | type PolicyConf struct
method Create (line 11) | func (c PolicyConf) Create(conf *PolicyConf) error {
method FindByID (line 15) | func (c PolicyConf) FindByID(id uint) (PolicyConf, error) {
method FindAll (line 21) | func (c PolicyConf) FindAll(offset, limit int) ([]PolicyConf, error) {
method UpdateById (line 27) | func (c PolicyConf) UpdateById(id uint, conf *PolicyConf) error {
method DeleteByID (line 31) | func (c PolicyConf) DeleteByID(id uint) error {
FILE: gossh/app/model/ssh_conf.go
type SshConf (line 10) | type SshConf struct
method Create (line 37) | func (c *SshConf) Create(conf *SshConf) error {
method FindByID (line 41) | func (c *SshConf) FindByID(id uint, uid uint) (SshConf, error) {
method FindAll (line 47) | func (c *SshConf) FindAll(offset, limit int, uid uint) ([]SshConf, err...
method UpdateById (line 53) | func (_ *SshConf) UpdateById(id, uid uint, conf *SshConf) error {
method DeleteByID (line 57) | func (c *SshConf) DeleteByID(id, uid uint) error {
method BeforeCreate (line 62) | func (c *SshConf) BeforeCreate(_ *gorm.DB) error {
method BeforeUpdate (line 68) | func (c *SshConf) BeforeUpdate(_ *gorm.DB) error {
method AfterFind (line 74) | func (c *SshConf) AfterFind(_ *gorm.DB) error {
method sshConfEncrypt (line 91) | func (c *SshConf) sshConfEncrypt() (*SshConf, error) {
FILE: gossh/app/model/sshd_cert.go
type SshdCert (line 5) | type SshdCert struct
method Create (line 17) | func (c *SshdCert) Create(user *SshdCert) error {
method FindByName (line 21) | func (c *SshdCert) FindByName(name string) (SshdCert, error) {
method FindByID (line 27) | func (c *SshdCert) FindByID(id uint) (SshdCert, error) {
method FindAll (line 33) | func (c *SshdCert) FindAll(limit, offset int) ([]SshdCert, error) {
method GetAuthorizedKeys (line 39) | func (c *SshdCert) GetAuthorizedKeys() (string, error) {
method UpdateById (line 53) | func (c *SshdCert) UpdateById(id uint, user *SshdCert) error {
method DeleteByID (line 57) | func (c *SshdCert) DeleteByID(id uint) error {
FILE: gossh/app/model/sshd_conf.go
type SshdConf (line 9) | type SshdConf struct
method Create (line 25) | func (c *SshdConf) Create(conf *SshdConf) error {
method FindByName (line 29) | func (c *SshdConf) FindByName(name string) (SshdConf, error) {
method FindByID (line 35) | func (c *SshdConf) FindByID(id uint) (SshdConf, error) {
method UpdateByName (line 41) | func (c *SshdConf) UpdateByName(name string, conf *SshdConf) error {
method DeleteByName (line 45) | func (c *SshdConf) DeleteByName(name string) error {
method BeforeCreate (line 50) | func (c *SshdConf) BeforeCreate(_ *gorm.DB) error {
method BeforeUpdate (line 57) | func (c *SshdConf) BeforeUpdate(_ *gorm.DB) error {
method AfterFind (line 64) | func (c *SshdConf) AfterFind(_ *gorm.DB) error {
FILE: gossh/app/model/sshd_user.go
type SshdUser (line 12) | type SshdUser struct
method Create (line 25) | func (c *SshdUser) Create(user *SshdUser) error {
method FindByNameAndPwd (line 29) | func (c *SshdUser) FindByNameAndPwd(name, pwd string) (SshdUser, error) {
method FindByName (line 45) | func (c *SshdUser) FindByName(name string) (SshdUser, error) {
method FindByID (line 51) | func (c *SshdUser) FindByID(id uint) (SshdUser, error) {
method FindAll (line 57) | func (c *SshdUser) FindAll(limit, offset int) ([]SshdUser, error) {
method UpdateById (line 63) | func (c *SshdUser) UpdateById(id uint, user *SshdUser) error {
method DeleteByID (line 67) | func (c *SshdUser) DeleteByID(id uint) error {
method BeforeCreate (line 72) | func (c *SshdUser) BeforeCreate(_ *gorm.DB) error {
method BeforeUpdate (line 79) | func (c *SshdUser) BeforeUpdate(_ *gorm.DB) error {
method AfterFind (line 86) | func (c *SshdUser) AfterFind(_ *gorm.DB) error {
FILE: gossh/app/model/web_user.go
type WebUser (line 10) | type WebUser struct
method Create (line 24) | func (c *WebUser) Create(user *WebUser) error {
method FindByNameAndPwd (line 28) | func (c *WebUser) FindByNameAndPwd(name, pwd string) (WebUser, error) {
method FindByName (line 40) | func (c *WebUser) FindByName(name string) (WebUser, error) {
method FindByID (line 46) | func (c *WebUser) FindByID(id uint) (WebUser, error) {
method FindAll (line 52) | func (c *WebUser) FindAll(limit, offset int) ([]WebUser, error) {
method UpdateById (line 58) | func (c *WebUser) UpdateById(id uint, user *WebUser) error {
method UpdatePassword (line 62) | func (c *WebUser) UpdatePassword(id uint, user *WebUser) error {
method DeleteByID (line 66) | func (c *WebUser) DeleteByID(id uint) error {
method BeforeCreate (line 71) | func (c *WebUser) BeforeCreate(_ *gorm.DB) error {
method BeforeUpdate (line 78) | func (c *WebUser) BeforeUpdate(_ *gorm.DB) error {
method AfterFind (line 85) | func (c *WebUser) AfterFind(_ *gorm.DB) error {
FILE: gossh/app/service/cmd_note.go
function CmdNoteCreate (line 9) | func CmdNoteCreate(c *gin.Context) {
function CmdNoteFindByID (line 24) | func CmdNoteFindByID(c *gin.Context) {
function CmdNoteFindAll (line 39) | func CmdNoteFindAll(c *gin.Context) {
function CmdNoteUpdateById (line 60) | func CmdNoteUpdateById(c *gin.Context) {
function CmdNoteDeleteById (line 74) | func CmdNoteDeleteById(c *gin.Context) {
FILE: gossh/app/service/db_conn.go
type DbConnConf (line 15) | type DbConnConf struct
function DbConnCheck (line 20) | func DbConnCheck(c *gin.Context) {
function DbConnTestCheck (line 39) | func DbConnTestCheck(dbConf DbConnConf) error {
FILE: gossh/app/service/login_audit.go
function AuditFindByID (line 9) | func AuditFindByID(c *gin.Context) {
function LoginAuditSearch (line 24) | func LoginAuditSearch(c *gin.Context) {
function LoginAuditDeleteById (line 51) | func LoginAuditDeleteById(c *gin.Context) {
FILE: gossh/app/service/net_filter.go
function NetFilterCreate (line 9) | func NetFilterCreate(c *gin.Context) {
function NetFilterFindByID (line 24) | func NetFilterFindByID(c *gin.Context) {
function NetFilterFindAll (line 39) | func NetFilterFindAll(c *gin.Context) {
function NetFilterUpdateById (line 61) | func NetFilterUpdateById(c *gin.Context) {
function NetFilterDeleteById (line 75) | func NetFilterDeleteById(c *gin.Context) {
FILE: gossh/app/service/policy_conf.go
function PolicyConfCreate (line 9) | func PolicyConfCreate(c *gin.Context) {
function PolicyConfFindByID (line 24) | func PolicyConfFindByID(c *gin.Context) {
function PolicyConfFindAll (line 39) | func PolicyConfFindAll(c *gin.Context) {
function PolicyConfUpdateById (line 61) | func PolicyConfUpdateById(c *gin.Context) {
function PolicyConfDeleteById (line 81) | func PolicyConfDeleteById(c *gin.Context) {
FILE: gossh/app/service/service_init.go
function DeleteOnlineClient (line 14) | func DeleteOnlineClient(sessionId string) {
function cleanNoActiveSession (line 82) | func cleanNoActiveSession() {
function initApp (line 103) | func initApp() {
function InitSessionClean (line 118) | func InitSessionClean() {
FILE: gossh/app/service/ssh_conf.go
function ConfCreate (line 9) | func ConfCreate(c *gin.Context) {
function ConfFindByID (line 24) | func ConfFindByID(c *gin.Context) {
function ConfFindAll (line 39) | func ConfFindAll(c *gin.Context) {
function ConfUpdateById (line 60) | func ConfUpdateById(c *gin.Context) {
function ConfDeleteById (line 75) | func ConfDeleteById(c *gin.Context) {
FILE: gossh/app/service/ssh_conn.go
type SshConn (line 20) | type SshConn struct
method MarshalJSON (line 49) | func (s *SshConn) MarshalJSON() ([]byte, error) {
method connect (line 75) | func (s *SshConn) connect(clientIp string) error {
method RunTerminal (line 151) | func (s *SshConn) RunTerminal(shell string, stdout, stderr io.Writer, ...
method ResizeWindow (line 189) | func (s *SshConn) ResizeWindow(c *gin.Context) {
function ResizeWindow (line 234) | func ResizeWindow(c *gin.Context) {
function NewSshConn (line 239) | func NewSshConn(c *gin.Context) {
type WebSocketReadWriter (line 320) | type WebSocketReadWriter struct
method Read (line 324) | func (w *WebSocketReadWriter) Read(p []byte) (n int, err error) {
method Write (line 333) | func (w *WebSocketReadWriter) Write(p []byte) (n int, err error) {
function CreateSessionId (line 341) | func CreateSessionId(c *gin.Context) {
function Disconnect (line 369) | func Disconnect(c *gin.Context) {
function ExecCommand (line 394) | func ExecCommand(c *gin.Context) {
FILE: gossh/app/service/ssh_sftp.go
function getSshConn (line 16) | func getSshConn(sessionId string) (*SshConn, error) {
function SftpList (line 31) | func SftpList(c *gin.Context) {
function SftpDownLoad (line 112) | func SftpDownLoad(c *gin.Context) {
function SftpUpload (line 164) | func SftpUpload(c *gin.Context) {
function SftpDelete (line 214) | func SftpDelete(c *gin.Context) {
function SftpCreateDir (line 250) | func SftpCreateDir(c *gin.Context) {
FILE: gossh/app/service/ssh_status.go
type SshConnById (line 12) | type SshConnById
method Len (line 14) | func (a SshConnById) Len() int { return len(a) }
method Swap (line 15) | func (a SshConnById) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
method Less (line 16) | func (a SshConnById) Less(i, j int) bool { return a[i].SessionId < a[j...
function GetOnlineClient (line 18) | func GetOnlineClient(c *gin.Context) {
function RefreshConnTime (line 55) | func RefreshConnTime(c *gin.Context) {
FILE: gossh/app/service/sshd_cert.go
function SshdCertCreate (line 10) | func SshdCertCreate(c *gin.Context) {
function CheckSshdCertNameExists (line 27) | func CheckSshdCertNameExists(c *gin.Context) {
function SshdCertFindByID (line 54) | func SshdCertFindByID(c *gin.Context) {
function SshdCertFindAll (line 72) | func SshdCertFindAll(c *gin.Context) {
function SshdCertUpdateById (line 97) | func SshdCertUpdateById(c *gin.Context) {
function SshdCertDeleteById (line 114) | func SshdCertDeleteById(c *gin.Context) {
function GetSshdCertAuthorizedKeys (line 132) | func GetSshdCertAuthorizedKeys(c *gin.Context) {
FILE: gossh/app/service/sshd_server.go
type Server (line 33) | type Server struct
method Start (line 48) | func (s *Server) Start() error {
method handleConn (line 64) | func (s *Server) handleConn(tcpConn net.Conn) {
method handleChannels (line 83) | func (s *Server) handleChannels(chans <-chan ssh.NewChannel) {
method handleChannel (line 90) | func (s *Server) handleChannel(newChannel ssh.NewChannel) {
method handleRequests (line 110) | func (s *Server) handleRequests(connection ssh.Channel, requests <-cha...
method keepAlive (line 194) | func (s *Server) keepAlive(connection ssh.Channel, interval time.Durat...
method attachShell (line 216) | func (s *Server) attachShell(connection ssh.Channel, env []string, res...
method loadCertAuthFile (line 276) | func (s *Server) loadCertAuthFile() (map[string]string, error) {
method computeSSHConfig (line 292) | func (s *Server) computeSSHConfig() (*ssh.ServerConfig, error) {
method matchKeys (line 358) | func (s *Server) matchKeys(key ssh.PublicKey, keys map[string]string) ...
function NewServer (line 38) | func NewServer(c *model.SshdConf) (*Server, error) {
function appendEnv (line 367) | func appendEnv(env []string, kv string) []string {
function parseDims (line 380) | func parseDims(b []byte) (uint32, uint32) {
function SetWindowSize (line 387) | func SetWindowSize(t pty.Pty, w, h uint32) {
function generateKey (line 392) | func generateKey(seed string) ([]byte, error) {
function parseKeys (line 411) | func parseKeys(b []byte) (map[string]string, error) {
function fingerprint (line 427) | func fingerprint(k ssh.PublicKey) string {
function newDetermRand (line 436) | func newDetermRand(seed []byte) io.Reader {
type determRand (line 450) | type determRand struct
method Read (line 454) | func (d *determRand) Read(b []byte) (int, error) {
function hash (line 469) | func hash(input []byte) (next []byte, output []byte) {
function ExecuteForChannel (line 475) | func ExecuteForChannel(shellCmd string, ch ssh.Channel) uint32 {
function startSshServer (line 541) | func startSshServer() {
function InitSshServer (line 569) | func InitSshServer() {
FILE: gossh/app/service/sshd_user.go
function SshdUserCreate (line 10) | func SshdUserCreate(c *gin.Context) {
function CheckSshdUserNameExists (line 27) | func CheckSshdUserNameExists(c *gin.Context) {
function SshdUserFindByID (line 54) | func SshdUserFindByID(c *gin.Context) {
function SshdUserFindAll (line 72) | func SshdUserFindAll(c *gin.Context) {
function SshdUserUpdateById (line 97) | func SshdUserUpdateById(c *gin.Context) {
function SshdUserDeleteById (line 114) | func SshdUserDeleteById(c *gin.Context) {
FILE: gossh/app/service/sys_init.go
function GetRunConf (line 12) | func GetRunConf(c *gin.Context) {
function SetRunConf (line 16) | func SetRunConf(c *gin.Context) {
function GetIsInit (line 34) | func GetIsInit(c *gin.Context) {
type InitConfig (line 42) | type InitConfig struct
function SysInit (line 54) | func SysInit(c *gin.Context) {
FILE: gossh/app/service/web_user.go
function UserCreate (line 15) | func UserCreate(c *gin.Context) {
function ModifyPasswd (line 33) | func ModifyPasswd(c *gin.Context) {
function CheckUserNameExists (line 65) | func CheckUserNameExists(c *gin.Context) {
function UserFindByID (line 92) | func UserFindByID(c *gin.Context) {
function UserFindAll (line 109) | func UserFindAll(c *gin.Context) {
function UserUpdateById (line 134) | func UserUpdateById(c *gin.Context) {
function UserDeleteById (line 168) | func UserDeleteById(c *gin.Context) {
function UserLogin (line 198) | func UserLogin(c *gin.Context) {
FILE: gossh/app/utils/crypto.go
function AesEncrypt (line 16) | func AesEncrypt(orig string, key string) (string, error) {
function AesDecrypt (line 55) | func AesDecrypt(crypt string, key string) (string, error) {
function EncryptString (line 94) | func EncryptString(plaintext, key string) (string, error) {
function DecryptString (line 133) | func DecryptString(encrypted, key string) (string, error) {
FILE: gossh/app/utils/utils.go
function RandString (line 10) | func RandString(length int) string {
function TruncateString (line 21) | func TruncateString(s string, length int) string {
FILE: gossh/crypto/blowfish/block.go
function getNextWord (line 9) | func getNextWord(b []byte, pos *int) uint32 {
function ExpandKey (line 28) | func ExpandKey(key []byte, c *Cipher) {
function expandKeyWithSalt (line 71) | func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
function encryptBlock (line 115) | func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
function decryptBlock (line 138) | func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
FILE: gossh/crypto/blowfish/cipher.go
constant BlockSize (line 22) | BlockSize = 8
type Cipher (line 25) | type Cipher struct
method BlockSize (line 68) | func (c *Cipher) BlockSize() int { return BlockSize }
method Encrypt (line 75) | func (c *Cipher) Encrypt(dst, src []byte) {
method Decrypt (line 85) | func (c *Cipher) Decrypt(dst, src []byte) {
type KeySizeError (line 30) | type KeySizeError
method Error (line 32) | func (k KeySizeError) Error() string {
function NewCipher (line 38) | func NewCipher(key []byte) (*Cipher, error) {
function NewSaltedCipher (line 52) | func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
function initCipher (line 93) | func initCipher(c *Cipher) {
FILE: gossh/crypto/chacha20/chacha_arm64.go
constant bufSize (line 9) | bufSize = 256
function xorKeyStreamVX (line 12) | func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, c...
method xorKeyStreamBlocks (line 14) | func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
FILE: gossh/crypto/chacha20/chacha_generic.go
constant KeySize (line 20) | KeySize = 32
constant NonceSize (line 27) | NonceSize = 12
constant NonceSizeX (line 31) | NonceSizeX = 24
type Cipher (line 36) | type Cipher struct
method SetCounter (line 152) | func (s *Cipher) SetCounter(counter uint32) {
method XORKeyStream (line 184) | func (s *Cipher) XORKeyStream(dst, src []byte) {
method xorKeyStreamBlocksGeneric (line 256) | func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
function NewUnauthenticatedCipher (line 72) | func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) {
function newUnauthenticatedCipher (line 80) | func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, er...
constant j0 (line 117) | j0 uint32 = 0x61707865
constant j1 (line 118) | j1 uint32 = 0x3320646e
constant j2 (line 119) | j2 uint32 = 0x79622d32
constant j3 (line 120) | j3 uint32 = 0x6b206574
constant blockSize (line 123) | blockSize = 64
function quarterRound (line 128) | func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
function HChaCha20 (line 344) | func HChaCha20(key, nonce []byte) ([]byte, error) {
function hChaCha20 (line 352) | func hChaCha20(out, key, nonce []byte) ([]byte, error) {
FILE: gossh/crypto/chacha20/chacha_noasm.go
constant bufSize (line 9) | bufSize = blockSize
method xorKeyStreamBlocks (line 11) | func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) {
FILE: gossh/crypto/chacha20/chacha_ppc64le.go
constant bufSize (line 9) | bufSize = 256
function chaCha20_ctr32_vsx (line 12) | func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter...
method xorKeyStreamBlocks (line 14) | func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
FILE: gossh/crypto/chacha20/chacha_s390x.go
constant bufSize (line 13) | bufSize = 256
function xorKeyStreamVX (line 19) | func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, c...
method xorKeyStreamBlocks (line 21) | func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
FILE: gossh/crypto/chacha20/xor.go
constant unaligned (line 10) | unaligned = runtime.GOARCH == "386" ||
function addXor (line 18) | func addXor(dst, src []byte, a, b uint32) {
FILE: gossh/crypto/chacha20poly1305/chacha20poly1305.go
constant KeySize (line 17) | KeySize = 32
constant NonceSize (line 24) | NonceSize = 12
constant NonceSizeX (line 28) | NonceSizeX = 24
constant Overhead (line 32) | Overhead = 16
type chacha20poly1305 (line 35) | type chacha20poly1305 struct
method NonceSize (line 49) | func (c *chacha20poly1305) NonceSize() int {
method Overhead (line 53) | func (c *chacha20poly1305) Overhead() int {
method Seal (line 57) | func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData ...
method Open (line 71) | func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData...
function New (line 40) | func New(key []byte) (cipher.AEAD, error) {
function sliceForAppend (line 89) | func sliceForAppend(in []byte, n int) (head, tail []byte) {
FILE: gossh/crypto/chacha20poly1305/chacha20poly1305_amd64.go
function chacha20Poly1305Open (line 17) | func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
function chacha20Poly1305Seal (line 20) | func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
function setupState (line 28) | func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
method seal (line 49) | func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []...
method open (line 65) | func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData [...
FILE: gossh/crypto/chacha20poly1305/chacha20poly1305_generic.go
function writeWithPadding (line 15) | func writeWithPadding(p *poly1305.MAC, b []byte) {
function writeUint64 (line 24) | func writeUint64(p *poly1305.MAC, n int) {
method sealGeneric (line 30) | func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additional...
method openGeneric (line 53) | func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additiona...
FILE: gossh/crypto/chacha20poly1305/chacha20poly1305_noasm.go
method seal (line 9) | func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []...
method open (line 13) | func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData [...
FILE: gossh/crypto/chacha20poly1305/xchacha20poly1305.go
type xchacha20poly1305 (line 14) | type xchacha20poly1305 struct
method NonceSize (line 33) | func (*xchacha20poly1305) NonceSize() int {
method Overhead (line 37) | func (*xchacha20poly1305) Overhead() int {
method Seal (line 41) | func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData...
method Open (line 66) | func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalDat...
function NewX (line 24) | func NewX(key []byte) (cipher.AEAD, error) {
FILE: gossh/crypto/curve25519/curve25519.go
function ScalarMult (line 18) | func ScalarMult(dst, scalar, point *[32]byte) {
function ScalarBaseMult (line 27) | func ScalarBaseMult(dst, scalar *[32]byte) {
constant ScalarSize (line 33) | ScalarSize = 32
constant PointSize (line 35) | PointSize = 32
function init (line 43) | func init() { Basepoint = basePoint[:] }
function X25519 (line 54) | func X25519(scalar, point []byte) ([]byte, error) {
FILE: gossh/crypto/curve25519/curve25519_compat.go
function scalarMult (line 17) | func scalarMult(dst, scalar, point *[32]byte) {
function scalarBaseMult (line 69) | func scalarBaseMult(dst, scalar *[32]byte) {
function x25519 (line 74) | func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
function checkBasepoint (line 96) | func checkBasepoint() {
FILE: gossh/crypto/curve25519/curve25519_go120.go
function x25519 (line 11) | func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
function scalarMult (line 29) | func scalarMult(dst, scalar, point *[32]byte) {
function scalarBaseMult (line 39) | func scalarBaseMult(dst, scalar *[32]byte) {
FILE: gossh/crypto/curve25519/internal/field/fe.go
type Element (line 22) | type Element struct
method Zero (line 39) | func (v *Element) Zero() *Element {
method One (line 47) | func (v *Element) One() *Element {
method reduce (line 53) | func (v *Element) reduce() *Element {
method Add (line 86) | func (v *Element) Add(a, b *Element) *Element {
method Subtract (line 100) | func (v *Element) Subtract(a, b *Element) *Element {
method Negate (line 112) | func (v *Element) Negate(a *Element) *Element {
method Invert (line 119) | func (v *Element) Invert(z *Element) *Element {
method Set (line 184) | func (v *Element) Set(a *Element) *Element {
method SetBytes (line 194) | func (v *Element) SetBytes(x []byte) *Element {
method Bytes (line 220) | func (v *Element) Bytes() []byte {
method bytes (line 227) | func (v *Element) bytes(out *[32]byte) []byte {
method Equal (line 248) | func (v *Element) Equal(u *Element) int {
method Select (line 257) | func (v *Element) Select(a, b *Element, cond int) *Element {
method Swap (line 268) | func (v *Element) Swap(u *Element, cond int) {
method IsNegative (line 288) | func (v *Element) IsNegative() int {
method Absolute (line 293) | func (v *Element) Absolute(u *Element) *Element {
method Multiply (line 298) | func (v *Element) Multiply(x, y *Element) *Element {
method Square (line 304) | func (v *Element) Square(x *Element) *Element {
method Mult32 (line 310) | func (v *Element) Mult32(x *Element, y uint32) *Element {
method Pow22523 (line 335) | func (v *Element) Pow22523(x *Element) *Element {
method SqrtRatio (line 394) | func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) {
constant maskLow51Bits (line 34) | maskLow51Bits uint64 = (1 << 51) - 1
function mask64Bits (line 254) | func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) }
function mul51 (line 327) | func mul51(a uint64, b uint32) (lo uint64, hi uint64) {
FILE: gossh/crypto/curve25519/internal/field/fe_amd64.go
function feMul (line 10) | func feMul(out *Element, a *Element, b *Element)
function feSquare (line 15) | func feSquare(out *Element, a *Element)
FILE: gossh/crypto/curve25519/internal/field/fe_amd64_noasm.go
function feMul (line 9) | func feMul(v, x, y *Element) { feMulGeneric(v, x, y) }
function feSquare (line 11) | func feSquare(v, x *Element) { feSquareGeneric(v, x) }
FILE: gossh/crypto/curve25519/internal/field/fe_arm64.go
function carryPropagate (line 10) | func carryPropagate(v *Element)
method carryPropagate (line 12) | func (v *Element) carryPropagate() *Element {
FILE: gossh/crypto/curve25519/internal/field/fe_arm64_noasm.go
method carryPropagate (line 9) | func (v *Element) carryPropagate() *Element {
FILE: gossh/crypto/curve25519/internal/field/fe_generic.go
type uint128 (line 11) | type uint128 struct
function mul64 (line 16) | func mul64(a, b uint64) uint128 {
function addMul64 (line 22) | func addMul64(v uint128, a, b uint64) uint128 {
function shiftRightBy51 (line 30) | func shiftRightBy51(a uint128) uint64 {
function feMulGeneric (line 34) | func feMulGeneric(v, a, b *Element) {
function feSquareGeneric (line 165) | func feSquareGeneric(v, a *Element) {
method carryPropagateGeneric (line 250) | func (v *Element) carryPropagateGeneric() *Element {
FILE: gossh/crypto/internal/alias/alias.go
function AnyOverlap (line 14) | func AnyOverlap(x, y []byte) bool {
function InexactOverlap (line 26) | func InexactOverlap(x, y []byte) bool {
FILE: gossh/crypto/internal/alias/alias_purego.go
function AnyOverlap (line 17) | func AnyOverlap(x, y []byte) bool {
function InexactOverlap (line 29) | func InexactOverlap(x, y []byte) bool {
FILE: gossh/crypto/internal/poly1305/mac_noasm.go
type mac (line 9) | type mac struct
FILE: gossh/crypto/internal/poly1305/poly1305.go
constant TagSize (line 23) | TagSize = 16
function Sum (line 28) | func Sum(out *[16]byte, m []byte, key *[32]byte) {
function Verify (line 35) | func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
function New (line 50) | func New(key *[32]byte) *MAC {
type MAC (line 63) | type MAC struct
method Size (line 70) | func (h *MAC) Size() int { return TagSize }
method Write (line 76) | func (h *MAC) Write(p []byte) (n int, err error) {
method Sum (line 85) | func (h *MAC) Sum(b []byte) []byte {
method Verify (line 94) | func (h *MAC) Verify(expected []byte) bool {
FILE: gossh/crypto/internal/poly1305/sum_amd64.go
function update (line 10) | func update(state *macState, msg []byte)
type mac (line 17) | type mac struct
method Write (line 19) | func (h *mac) Write(p []byte) (int, error) {
method Sum (line 41) | func (h *mac) Sum(out *[16]byte) {
FILE: gossh/crypto/internal/poly1305/sum_generic.go
function sumGeneric (line 31) | func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) {
function newMACGeneric (line 37) | func newMACGeneric(key *[32]byte) macGeneric {
type macState (line 45) | type macState struct
type macGeneric (line 55) | type macGeneric struct
method Write (line 64) | func (h *macGeneric) Write(p []byte) (int, error) {
method Sum (line 89) | func (h *macGeneric) Sum(out *[TagSize]byte) {
constant rMask0 (line 101) | rMask0 = 0x0FFFFFFC0FFFFFFF
constant rMask1 (line 102) | rMask1 = 0x0FFFFFFC0FFFFFFC
function initialize (line 106) | func initialize(key *[32]byte, m *macState) {
type uint128 (line 115) | type uint128 struct
function mul64 (line 119) | func mul64(a, b uint64) uint128 {
function add128 (line 124) | func add128(a, b uint128) uint128 {
function shiftRightBy2 (line 133) | func shiftRightBy2(a uint128) uint128 {
function updateGeneric (line 146) | func updateGeneric(state *macState, msg []byte) {
constant maskLow2Bits (line 268) | maskLow2Bits uint64 = 0x0000000000000003
constant maskNotLow2Bits (line 269) | maskNotLow2Bits uint64 = ^maskLow2Bits
function select64 (line 273) | func select64(v, x, y uint64) uint64 { return ^(v-1)&x | (v-1)&y }
constant p0 (line 277) | p0 = 0xFFFFFFFFFFFFFFFB
constant p1 (line 278) | p1 = 0xFFFFFFFFFFFFFFFF
constant p2 (line 279) | p2 = 0x0000000000000003
function finalize (line 285) | func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
FILE: gossh/crypto/internal/poly1305/sum_ppc64le.go
function update (line 10) | func update(state *macState, msg []byte)
type mac (line 17) | type mac struct
method Write (line 19) | func (h *mac) Write(p []byte) (int, error) {
method Sum (line 41) | func (h *mac) Sum(out *[16]byte) {
FILE: gossh/crypto/internal/poly1305/sum_s390x.go
function updateVX (line 18) | func updateVX(state *macState, msg []byte)
type mac (line 27) | type mac struct
method Write (line 34) | func (h *mac) Write(p []byte) (int, error) {
method Sum (line 64) | func (h *mac) Sum(out *[TagSize]byte) {
FILE: gossh/crypto/internal/testenv/exec.go
function CommandContext (line 25) | func CommandContext(t testing.TB, ctx context.Context, name string, args...
function Command (line 117) | func Command(t testing.TB, name string, args ...string) *exec.Cmd {
FILE: gossh/crypto/ssh/agent/client.go
type SignatureFlags (line 35) | type SignatureFlags
constant SignatureFlagReserved (line 39) | SignatureFlagReserved SignatureFlags = 1 << iota
constant SignatureFlagRsaSha256 (line 40) | SignatureFlagRsaSha256
constant SignatureFlagRsaSha512 (line 41) | SignatureFlagRsaSha512
type Agent (line 45) | type Agent interface
type ExtendedAgent (line 72) | type ExtendedAgent interface
type ConstraintExtension (line 93) | type ConstraintExtension struct
type AddedKey (line 104) | type AddedKey struct
constant agentRequestV1Identities (line 127) | agentRequestV1Identities = 1
constant agentRemoveAllV1Identities (line 128) | agentRemoveAllV1Identities = 9
constant agentAddIdentity (line 131) | agentAddIdentity = 17
constant agentRemoveIdentity (line 132) | agentRemoveIdentity = 18
constant agentRemoveAllIdentities (line 133) | agentRemoveAllIdentities = 19
constant agentAddIDConstrained (line 134) | agentAddIDConstrained = 25
constant agentAddSmartcardKey (line 137) | agentAddSmartcardKey = 20
constant agentRemoveSmartcardKey (line 138) | agentRemoveSmartcardKey = 21
constant agentLock (line 139) | agentLock = 22
constant agentUnlock (line 140) | agentUnlock = 23
constant agentAddSmartcardKeyConstrained (line 141) | agentAddSmartcardKeyConstrained = 26
constant agentConstrainLifetime (line 144) | agentConstrainLifetime = 1
constant agentConstrainConfirm (line 145) | agentConstrainConfirm = 2
constant agentConstrainExtensionV00 (line 149) | agentConstrainExtensionV00 = 3
constant agentConstrainExtension (line 151) | agentConstrainExtension = 255
constant maxAgentResponseBytes (line 156) | maxAgentResponseBytes = 16 << 20
constant agentFailure (line 163) | agentFailure = 5
type failureAgentMsg (line 165) | type failureAgentMsg struct
constant agentSuccess (line 167) | agentSuccess = 6
type successAgentMsg (line 169) | type successAgentMsg struct
constant agentRequestIdentities (line 172) | agentRequestIdentities = 11
type requestIdentitiesAgentMsg (line 174) | type requestIdentitiesAgentMsg struct
constant agentIdentitiesAnswer (line 177) | agentIdentitiesAnswer = 12
type identitiesAnswerAgentMsg (line 179) | type identitiesAnswerAgentMsg struct
constant agentSignRequest (line 185) | agentSignRequest = 13
type signRequestAgentMsg (line 187) | type signRequestAgentMsg struct
constant agentSignResponse (line 196) | agentSignResponse = 14
type signResponseAgentMsg (line 198) | type signResponseAgentMsg struct
type publicKey (line 202) | type publicKey struct
type constrainLifetimeAgentMsg (line 208) | type constrainLifetimeAgentMsg struct
type constrainExtensionAgentMsg (line 212) | type constrainExtensionAgentMsg struct
constant agentExtension (line 221) | agentExtension = 27
constant agentExtensionFailure (line 222) | agentExtensionFailure = 28
type extensionAgentMsg (line 232) | type extensionAgentMsg struct
type Key (line 241) | type Key struct
method String (line 253) | func (k *Key) String() string {
method Type (line 264) | func (k *Key) Type() string {
method Marshal (line 269) | func (k *Key) Marshal() []byte {
method Verify (line 274) | func (k *Key) Verify(data []byte, sig *ssh.Signature) error {
function clientErr (line 247) | func clientErr(err error) error {
type wireKey (line 282) | type wireKey struct
function parseKey (line 287) | func parseKey(in []byte) (out *Key, rest []byte, err error) {
type client (line 311) | type client struct
method call (line 327) | func (c *client) call(req []byte) (reply any, err error) {
method callRaw (line 342) | func (c *client) callRaw(req []byte) (reply []byte, err error) {
method simpleCall (line 369) | func (c *client) simpleCall(req []byte) error {
method RemoveAll (line 380) | func (c *client) RemoveAll() error {
method Remove (line 384) | func (c *client) Remove(key ssh.PublicKey) error {
method Lock (line 391) | func (c *client) Lock(passphrase []byte) error {
method Unlock (line 398) | func (c *client) Unlock(passphrase []byte) error {
method List (line 406) | func (c *client) List() ([]*Key, error) {
method Sign (line 439) | func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature,...
method SignWithFlags (line 443) | func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags S...
method insertKey (line 537) | func (c *client) insertKey(s any, comment string, constraints []byte) ...
method Add (line 653) | func (c *client) Add(key AddedKey) error {
method insertCert (line 671) | func (c *client) insertCert(s any, cert *ssh.Certificate, comment stri...
method Signers (line 754) | func (c *client) Signers() ([]ssh.Signer, error) {
method Extension (line 832) | func (c *client) Extension(extensionType string, contents []byte) ([]b...
function NewClient (line 320) | func NewClient(rw io.ReadWriter) ExtendedAgent {
function unmarshal (line 471) | func unmarshal(packet []byte) (any, error) {
type rsaKeyMsg (line 496) | type rsaKeyMsg struct
type dsaKeyMsg (line 508) | type dsaKeyMsg struct
type ecdsaKeyMsg (line 519) | type ecdsaKeyMsg struct
type ed25519KeyMsg (line 528) | type ed25519KeyMsg struct
type rsaCertMsg (line 615) | type rsaCertMsg struct
type dsaCertMsg (line 626) | type dsaCertMsg struct
type ecdsaCertMsg (line 634) | type ecdsaCertMsg struct
type ed25519CertMsg (line 642) | type ed25519CertMsg struct
type agentKeyringSigner (line 767) | type agentKeyringSigner struct
method PublicKey (line 772) | func (s *agentKeyringSigner) PublicKey() ssh.PublicKey {
method Sign (line 776) | func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.S...
method SignWithAlgorithm (line 781) | func (s *agentKeyringSigner) SignWithAlgorithm(rand io.Reader, data []...
function underlyingAlgo (line 821) | func underlyingAlgo(algo string) string {
FILE: gossh/crypto/ssh/agent/forward.go
function RequestAgentForwarding (line 19) | func RequestAgentForwarding(session *ssh.Session) error {
function ForwardToAgent (line 31) | func ForwardToAgent(client *ssh.Client, keyring Agent) error {
constant channelType (line 53) | channelType = "auth-agent@openssh.com"
function ForwardToRemote (line 57) | func ForwardToRemote(client *ssh.Client, addr string) error {
function forwardUnixSocket (line 81) | func forwardUnixSocket(channel ssh.Channel, addr string) {
FILE: gossh/crypto/ssh/agent/keyring.go
type privKey (line 19) | type privKey struct
type keyring (line 25) | type keyring struct
method RemoveAll (line 42) | func (r *keyring) RemoveAll() error {
method removeLocked (line 55) | func (r *keyring) removeLocked(want []byte) error {
method Remove (line 75) | func (r *keyring) Remove(key ssh.PublicKey) error {
method Lock (line 86) | func (r *keyring) Lock(passphrase []byte) error {
method Unlock (line 99) | func (r *keyring) Unlock(passphrase []byte) error {
method expireKeysLocked (line 117) | func (r *keyring) expireKeysLocked() {
method List (line 126) | func (r *keyring) List() ([]*Key, error) {
method Add (line 149) | func (r *keyring) Add(key AddedKey) error {
method Sign (line 184) | func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature...
method SignWithFlags (line 188) | func (r *keyring) SignWithFlags(key ssh.PublicKey, data []byte, flags ...
method Signers (line 223) | func (r *keyring) Signers() ([]ssh.Signer, error) {
method Extension (line 239) | func (r *keyring) Extension(extensionType string, contents []byte) ([]...
function NewKeyring (line 37) | func NewKeyring() Agent {
FILE: gossh/crypto/ssh/agent/server.go
type server (line 25) | type server struct
method processRequestBytes (line 29) | func (s *server) processRequestBytes(reqData []byte) []byte {
method processRequest (line 76) | func (s *server) processRequest(data []byte) (any, error) {
method insertIdentity (line 493) | func (s *server) insertIdentity(req []byte) error {
function marshalKey (line 46) | func marshalKey(k *Key) []byte {
constant agentV1IdentitiesAnswer (line 58) | agentV1IdentitiesAnswer = 2
type agentV1IdentityMsg (line 60) | type agentV1IdentityMsg struct
type agentRemoveIdentityMsg (line 64) | type agentRemoveIdentityMsg struct
type agentLockMsg (line 68) | type agentLockMsg struct
type agentUnlockMsg (line 72) | type agentUnlockMsg struct
function parseConstraints (line 202) | func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmB...
function setConstraints (line 228) | func setConstraints(key *AddedKey, constraintBytes []byte) error {
function parseRSAKey (line 240) | func parseRSAKey(req []byte) (*AddedKey, error) {
function parseEd25519Key (line 265) | func parseEd25519Key(req []byte) (*AddedKey, error) {
function parseDSAKey (line 279) | func parseDSAKey(req []byte) (*AddedKey, error) {
function unmarshalECDSA (line 303) | func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.I...
function parseEd25519Cert (line 327) | func parseEd25519Cert(req []byte) (*AddedKey, error) {
function parseECDSAKey (line 349) | func parseECDSAKey(req []byte) (*AddedKey, error) {
function parseRSACert (line 367) | func parseRSACert(req []byte) (*AddedKey, error) {
function parseDSACert (line 414) | func parseDSACert(req []byte) (*AddedKey, error) {
function parseECDSACert (line 456) | func parseECDSACert(req []byte) (*AddedKey, error) {
function ServeAgent (line 535) | func ServeAgent(agent Agent, c io.ReadWriter) error {
FILE: gossh/crypto/ssh/buffer.go
type buffer (line 15) | type buffer struct
method write (line 44) | func (b *buffer) write(buf []byte) {
method eof (line 55) | func (b *buffer) eof() {
method Read (line 64) | func (b *buffer) Read(buf []byte) (n int, err error) {
type element (line 26) | type element struct
function newBuffer (line 32) | func newBuffer() *buffer {
FILE: gossh/crypto/ssh/certs.go
constant CertAlgoRSAv01 (line 23) | CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
constant CertAlgoDSAv01 (line 24) | CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
constant CertAlgoECDSA256v01 (line 25) | CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
constant CertAlgoECDSA384v01 (line 26) | CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
constant CertAlgoECDSA521v01 (line 27) | CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
constant CertAlgoSKECDSA256v01 (line 28) | CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
constant CertAlgoED25519v01 (line 29) | CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
constant CertAlgoSKED25519v01 (line 30) | CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
constant CertAlgoRSASHA256v01 (line 35) | CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com"
constant CertAlgoRSASHA512v01 (line 36) | CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com"
constant CertSigAlgoRSAv01 (line 41) | CertSigAlgoRSAv01 = CertAlgoRSAv01
constant CertSigAlgoRSASHA2256v01 (line 43) | CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01
constant CertSigAlgoRSASHA2512v01 (line 45) | CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01
constant UserCert (line 52) | UserCert = 1
constant HostCert (line 53) | HostCert = 2
type Signature (line 57) | type Signature struct
constant CertTimeInfinity (line 65) | CertTimeInfinity = 1<<64 - 1
type Certificate (line 71) | type Certificate struct
method SignCert (line 446) | func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
method bytesForSigning (line 521) | func (cert *Certificate) bytesForSigning() []byte {
method Marshal (line 531) | func (c *Certificate) Marshal() []byte {
method Type (line 563) | func (c *Certificate) Type() string {
method Verify (line 573) | func (c *Certificate) Verify(data []byte, sig *Signature) error {
type genericCertData (line 89) | type genericCertData struct
function marshalStringList (line 103) | func marshalStringList(namelist []string) []byte {
type optionsTuple (line 112) | type optionsTuple struct
type optionsTupleValue (line 117) | type optionsTupleValue struct
function marshalTuples (line 124) | func marshalTuples(tups map[string]string) []byte {
function parseTuples (line 144) | func parseTuples(in []byte) (map[string]string, error) {
function parseCert (line 183) | func parseCert(in []byte, privAlgo string) (*Certificate, error) {
type openSSHCertSigner (line 241) | type openSSHCertSigner struct
method Sign (line 274) | func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signat...
method PublicKey (line 278) | func (s *openSSHCertSigner) PublicKey() PublicKey {
type algorithmOpenSSHCertSigner (line 246) | type algorithmOpenSSHCertSigner struct
method SignWithAlgorithm (line 282) | func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader,...
function NewCertSigner (line 254) | func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
constant sourceAddressCriticalOption (line 286) | sourceAddressCriticalOption = "source-address"
type CertChecker (line 292) | type CertChecker struct
method CheckHostKey (line 334) | func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key P...
method Authenticate (line 360) | func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey...
method CheckCert (line 385) | func (c *CertChecker) CheckCert(principal string, cert *Certificate) e...
function underlyingAlgo (line 503) | func underlyingAlgo(algo string) string {
function certificateAlgo (line 512) | func certificateAlgo(algo string) (certAlgo string, ok bool) {
function parseSignatureBody (line 577) | func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
function parseSignature (line 600) | func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
FILE: gossh/crypto/ssh/channel.go
constant minPacketLength (line 17) | minPacketLength = 9
constant channelMaxPacket (line 21) | channelMaxPacket = 1 << 15
constant channelWindowSize (line 23) | channelWindowSize = 64 * channelMaxPacket
type NewChannel (line 28) | type NewChannel interface
type Channel (line 49) | type Channel interface
type Request (line 84) | type Request struct
method Reply (line 96) | func (r *Request) Reply(ok bool, payload []byte) error {
type RejectionReason (line 110) | type RejectionReason
method String (line 120) | func (r RejectionReason) String() string {
constant Prohibited (line 113) | Prohibited RejectionReason = iota + 1
constant ConnectionFailed (line 114) | ConnectionFailed
constant UnknownChannelType (line 115) | UnknownChannelType
constant ResourceShortage (line 116) | ResourceShortage
function min (line 134) | func min(a uint32, b int) uint32 {
type channelDirection (line 141) | type channelDirection
constant channelInbound (line 144) | channelInbound channelDirection = iota
constant channelOutbound (line 145) | channelOutbound
type channel (line 150) | type channel struct
method writePacket (line 210) | func (ch *channel) writePacket(packet []byte) error {
method sendMessage (line 222) | func (ch *channel) sendMessage(msg any) error {
method WriteExtended (line 234) | func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n ...
method handleData (line 288) | func (ch *channel) handleData(packet []byte) error {
method adjustWindow (line 337) | func (c *channel) adjustWindow(adj uint32) error {
method ReadExtended (line 358) | func (c *channel) ReadExtended(data []byte, extended uint32) (n int, e...
method close (line 382) | func (c *channel) close() {
method responseMessageReceived (line 399) | func (ch *channel) responseMessageReceived() error {
method handlePacket (line 410) | func (ch *channel) handlePacket(packet []byte) error {
method Accept (line 503) | func (ch *channel) Accept() (Channel, <-chan *Request, error) {
method Reject (line 522) | func (ch *channel) Reject(reason RejectionReason, message string) error {
method Read (line 536) | func (ch *channel) Read(data []byte) (int, error) {
method Write (line 543) | func (ch *channel) Write(data []byte) (int, error) {
method CloseWrite (line 550) | func (ch *channel) CloseWrite() error {
method Close (line 559) | func (ch *channel) Close() error {
method Extended (line 570) | func (ch *channel) Extended(code uint32) io.ReadWriter {
method Stderr (line 577) | func (ch *channel) Stderr() io.ReadWriter {
method SendRequest (line 581) | func (ch *channel) SendRequest(name string, wantReply bool, payload []...
method ackRequest (line 621) | func (ch *channel) ackRequest(ok bool) error {
method ChannelType (line 639) | func (ch *channel) ChannelType() string {
method ExtraData (line 643) | func (ch *channel) ExtraData() []byte {
method newChannel (line 469) | func (m *mux) newChannel(chanType string, direction channelDirection, ex...
type extChannel (line 490) | type extChannel struct
method Write (line 495) | func (e *extChannel) Write(data []byte) (n int, err error) {
method Read (line 499) | func (e *extChannel) Read(data []byte) (n int, err error) {
FILE: gossh/crypto/ssh/cipher.go
constant packetSizeMultiple (line 23) | packetSizeMultiple = 16
constant maxPacket (line 34) | maxPacket = 256 * 1024
type noneCipher (line 39) | type noneCipher struct
method XORKeyStream (line 41) | func (c noneCipher) XORKeyStream(dst, src []byte) {
function newAESCTR (line 45) | func newAESCTR(key, iv []byte) (cipher.Stream, error) {
function newRC4 (line 53) | func newRC4(key, iv []byte) (cipher.Stream, error) {
type cipherMode (line 57) | type cipherMode struct
function streamCipherMode (line 63) | func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher....
constant prefixLen (line 134) | prefixLen = 5
type streamPacketCipher (line 137) | type streamPacketCipher struct
method readCipherPacket (line 151) | func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Read...
method writeCipherPacket (line 223) | func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Wri...
type gcmCipher (line 302) | type gcmCipher struct
method writeCipherPacket (line 328) | func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand...
method incIV (line 362) | func (c *gcmCipher) incIV() {
method readCipherPacket (line 371) | func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]by...
function newGCMCipher (line 309) | func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgo...
constant gcmTagSize (line 326) | gcmTagSize = 16
type cbcCipher (line 415) | type cbcCipher struct
method readCipherPacket (line 491) | func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]by...
method readCipherPacketLeaky (line 505) | func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ...
method writeCipherPacket (line 581) | func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand...
function newCBCCipher (line 431) | func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs direction...
function newAESCBCCipher (line 445) | func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (...
function newTripleDESCBCCipher (line 459) | func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorit...
function maxUInt32 (line 473) | func maxUInt32(a, b int) uint32 {
constant cbcMinPacketSizeMultiple (line 481) | cbcMinPacketSizeMultiple = 8
constant cbcMinPacketSize (line 482) | cbcMinPacketSize = 16
constant cbcMinPaddingSize (line 483) | cbcMinPaddingSize = 4
type cbcError (line 487) | type cbcError
method Error (line 489) | func (e cbcError) Error() string { return string(e) }
constant chacha20Poly1305ID (line 637) | chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
type chacha20Poly1305Cipher (line 646) | type chacha20Poly1305Cipher struct
method readCipherPacket (line 666) | func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io....
method writeCipherPacket (line 736) | func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io...
function newChaCha20Cipher (line 652) | func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs di...
FILE: gossh/crypto/ssh/client.go
type Client (line 19) | type Client struct
method HandleChannelOpen (line 32) | func (c *Client) HandleChannelOpen(channelType string) <-chan NewChann...
method NewSession (line 133) | func (c *Client) NewSession() (*Session, error) {
method handleGlobalRequests (line 141) | func (c *Client) handleGlobalRequests(incoming <-chan *Request) {
method handleChannelOpens (line 150) | func (c *Client) handleChannelOpens(in <-chan NewChannel) {
function NewClient (line 53) | func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *C...
function NewClientConn (line 71) | func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn,...
method clientHandshake (line 93) | func (c *connection) clientHandshake(dialAddress string, config *ClientC...
function verifyHostKeySignature (line 118) | func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexR...
function Dial (line 176) | func Dial(network, addr string, config *ClientConfig) (*Client, error) {
type HostKeyCallback (line 193) | type HostKeyCallback
type BannerCallback (line 197) | type BannerCallback
type ClientConfig (line 201) | type ClientConfig struct
function InsecureIgnoreHostKey (line 247) | func InsecureIgnoreHostKey() HostKeyCallback {
type fixedHostKey (line 253) | type fixedHostKey struct
method check (line 257) | func (f *fixedHostKey) check(hostname string, remote net.Addr, key Pub...
function FixedHostKey (line 269) | func FixedHostKey(key PublicKey) HostKeyCallback {
function BannerDisplayStderr (line 276) | func BannerDisplayStderr() BannerCallback {
FILE: gossh/crypto/ssh/client_auth.go
type authResult (line 15) | type authResult
constant authFailure (line 18) | authFailure authResult = iota
constant authPartialSuccess (line 19) | authPartialSuccess
constant authSuccess (line 20) | authSuccess
method clientAuthenticate (line 24) | func (c *connection) clientAuthenticate(config *ClientConfig) error {
function contains (line 116) | func contains(list []string, e string) bool {
type AuthMethod (line 126) | type AuthMethod interface
type noneAuth (line 139) | type noneAuth
method auth (line 141) | func (n *noneAuth) auth(session []byte, user string, c packetConn, ran...
method method (line 153) | func (n *noneAuth) method() string {
type passwordCallback (line 159) | type passwordCallback
method auth (line 161) | func (cb passwordCallback) auth(session []byte, user string, c packetC...
method method (line 191) | func (cb passwordCallback) method() string {
function Password (line 196) | func Password(secret string) AuthMethod {
function PasswordCallback (line 202) | func PasswordCallback(prompt func() (secret string, err error)) AuthMeth...
type publickeyAuthMsg (line 206) | type publickeyAuthMsg struct
type publicKeyCallback (line 222) | type publicKeyCallback
method method (line 224) | func (cb publicKeyCallback) method() string {
method auth (line 298) | func (cb publicKeyCallback) auth(session []byte, user string, c packet...
function pickSignatureAlgorithm (line 228) | func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte)...
function validateKey (line 393) | func validateKey(key PublicKey, algo string, user string, c packetConn) ...
function confirmKeyAck (line 410) | func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, erro...
function PublicKeys (line 442) | func PublicKeys(signers ...Signer) AuthMethod {
function PublicKeysCallback (line 448) | func PublicKeysCallback(getSigners func() (signers []Signer, err error))...
function handleAuthResponse (line 455) | func handleAuthResponse(c packetConn) (authResult, []string, error) {
function handleBannerResponse (line 491) | func handleBannerResponse(c packetConn, packet []byte) error {
type KeyboardInteractiveChallenge (line 516) | type KeyboardInteractiveChallenge
method method (line 524) | func (cb KeyboardInteractiveChallenge) method() string {
method auth (line 528) | func (cb KeyboardInteractiveChallenge) auth(session []byte, user strin...
function KeyboardInteractive (line 520) | func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMet...
type retryableAuthMethod (line 633) | type retryableAuthMethod struct
method auth (line 638) | func (r *retryableAuthMethod) auth(session []byte, user string, c pack...
method method (line 648) | func (r *retryableAuthMethod) method() string {
function RetryableAuthMethod (line 663) | func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
function GSSAPIWithMICAuthMethod (line 671) | func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) A...
type gssAPIWithMICCallback (line 678) | type gssAPIWithMICCallback struct
method auth (line 683) | func (g *gssAPIWithMICCallback) auth(session []byte, user string, c pa...
method method (line 777) | func (g *gssAPIWithMICCallback) method() string {
FILE: gossh/crypto/ssh/common.go
constant compressionNone (line 22) | compressionNone = "none"
constant serviceUserAuth (line 23) | serviceUserAuth = "ssh-userauth"
constant serviceSSH (line 24) | serviceSSH = "ssh-connection"
function algorithmsForKeyFormat (line 112) | func algorithmsForKeyFormat(keyFormat string) []string {
function isRSA (line 125) | func isRSA(algo string) bool {
function isRSACert (line 130) | func isRSACert(algo string) bool {
function unexpectedMessageError (line 152) | func unexpectedMessageError(expected, got uint8) error {
function parseError (line 157) | func parseError(tag uint8) error {
function findCommon (line 161) | func findCommon(what string, client []string, server []string) (common s...
type directionAlgorithms (line 173) | type directionAlgorithms struct
method rekeyBytes (line 180) | func (a *directionAlgorithms) rekeyBytes() int64 {
type algorithms (line 200) | type algorithms struct
function findAgreedAlgorithms (line 207) | func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *k...
constant minRekeyThreshold (line 264) | minRekeyThreshold uint64 = 256
type Config (line 268) | type Config struct
method SetDefaults (line 295) | func (c *Config) SetDefaults() {
function buildDataSignedForAuth (line 348) | func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, al...
function appendU16 (line 371) | func appendU16(buf []byte, n uint16) []byte {
function appendU32 (line 375) | func appendU32(buf []byte, n uint32) []byte {
function appendU64 (line 379) | func appendU64(buf []byte, n uint64) []byte {
function appendInt (line 385) | func appendInt(buf []byte, n int) []byte {
function appendString (line 389) | func appendString(buf []byte, s string) []byte {
function appendBool (line 395) | func appendBool(buf []byte, b bool) []byte {
function newCond (line 404) | func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) }
type window (line 408) | type window struct
method add (line 417) | func (w *window) add(win uint32) bool {
method close (line 438) | func (w *window) close() {
method reserve (line 448) | func (w *window) reserve(win uint32) (uint32, error) {
method waitWriterBlocked (line 470) | func (w *window) waitWriterBlocked() {
FILE: gossh/crypto/ssh/connection.go
type OpenChannelError (line 14) | type OpenChannelError struct
method Error (line 19) | func (e *OpenChannelError) Error() string {
type ConnMetadata (line 24) | type ConnMetadata interface
type Conn (line 50) | type Conn interface
function DiscardRequests (line 79) | func DiscardRequests(in <-chan *Request) {
type connection (line 88) | type connection struct
method Close (line 96) | func (c *connection) Close() error {
type sshConn (line 102) | type sshConn struct
method User (line 117) | func (c *sshConn) User() string {
method RemoteAddr (line 121) | func (c *sshConn) RemoteAddr() net.Addr {
method Close (line 125) | func (c *sshConn) Close() error {
method LocalAddr (line 129) | func (c *sshConn) LocalAddr() net.Addr {
method SessionID (line 133) | func (c *sshConn) SessionID() []byte {
method ClientVersion (line 137) | func (c *sshConn) ClientVersion() []byte {
method ServerVersion (line 141) | func (c *sshConn) ServerVersion() []byte {
function dup (line 111) | func dup(src []byte) []byte {
FILE: gossh/crypto/ssh/handshake.go
constant debugHandshake (line 21) | debugHandshake = false
constant chanSize (line 26) | chanSize = 16
type keyingTransport (line 31) | type keyingTransport interface
type handshakeTransport (line 52) | type handshakeTransport struct
method getSessionID (line 169) | func (t *handshakeTransport) getSessionID() []byte {
method waitSession (line 175) | func (t *handshakeTransport) waitSession() error {
method id (line 187) | func (t *handshakeTransport) id() string {
method printPacket (line 194) | func (t *handshakeTransport) printPacket(p []byte, write bool) {
method readPacket (line 208) | func (t *handshakeTransport) readPacket() ([]byte, error) {
method readLoop (line 216) | func (t *handshakeTransport) readLoop() {
method pushPacket (line 244) | func (t *handshakeTransport) pushPacket(p []byte) error {
method getWriteError (line 251) | func (t *handshakeTransport) getWriteError() error {
method recordWriteError (line 257) | func (t *handshakeTransport) recordWriteError(err error) {
method requestKeyExchange (line 265) | func (t *handshakeTransport) requestKeyExchange() {
method resetWriteThresholds (line 273) | func (t *handshakeTransport) resetWriteThresholds() {
method kexLoop (line 284) | func (t *handshakeTransport) kexLoop() {
method resetReadThresholds (line 388) | func (t *handshakeTransport) resetReadThresholds() {
method readOnePacket (line 399) | func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
method sendKexInit (line 467) | func (t *handshakeTransport) sendKexInit() error {
method writePacket (line 555) | func (t *handshakeTransport) writePacket(p []byte) error {
method Close (line 596) | func (t *handshakeTransport) Close() error {
method enterKeyExchange (line 609) | func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) ...
method server (line 775) | func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshak...
method client (line 785) | func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshak...
type pendingKex (line 119) | type pendingKex struct
function newHandshakeTransport (line 124) | func newHandshakeTransport(conn keyingTransport, config *Config, clientV...
function newClientTransport (line 144) | func newClientTransport(conn keyingTransport, clientVersion, serverVersi...
function newServerTransport (line 160) | func newServerTransport(conn keyingTransport, clientVersion, serverVersi...
constant packetRekeyThreshold (line 386) | packetRekeyThreshold = (1 << 31)
constant kexStrictClient (line 462) | kexStrictClient = "kex-strict-c-v00@openssh.com"
constant kexStrictServer (line 463) | kexStrictServer = "kex-strict-s-v00@openssh.com"
type algorithmSignerWrapper (line 739) | type algorithmSignerWrapper struct
method SignWithAlgorithm (line 743) | func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data...
function pickHostKey (line 750) | func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner {
FILE: gossh/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go
constant blockSize (line 17) | blockSize = 32
function Key (line 21) | func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) {
function bcryptHash (line 74) | func bcryptHash(out, shapass, shasalt []byte) {
FILE: gossh/crypto/ssh/kex.go
constant kexAlgoDH1SHA1 (line 22) | kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
constant kexAlgoDH14SHA1 (line 23) | kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
constant kexAlgoDH14SHA256 (line 24) | kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256"
constant kexAlgoDH16SHA512 (line 25) | kexAlgoDH16SHA512 = "diffie-hellman-group16-sha512"
constant kexAlgoECDH256 (line 26) | kexAlgoECDH256 = "ecdh-sha2-nistp256"
constant kexAlgoECDH384 (line 27) | kexAlgoECDH384 = "ecdh-sha2-nistp384"
constant kexAlgoECDH521 (line 28) | kexAlgoECDH521 = "ecdh-sha2-nistp521"
constant kexAlgoCurve25519SHA256LibSSH (line 29) | kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org"
constant kexAlgoCurve25519SHA256 (line 30) | kexAlgoCurve25519SHA256 = "curve25519-sha256"
constant kexAlgoDHGEXSHA1 (line 35) | kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
constant kexAlgoDHGEXSHA256 (line 36) | kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
type kexResult (line 40) | type kexResult struct
type handshakeMagics (line 65) | type handshakeMagics struct
method write (line 70) | func (m *handshakeMagics) write(w io.Writer) {
type kexAlgorithm (line 78) | type kexAlgorithm interface
type dhGroup (line 90) | type dhGroup struct
method diffieHellman (line 95) | func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (...
method Client (line 102) | func (group *dhGroup) Client(c packetConn, randSource io.Reader, magic...
method Server (line 155) | func (group *dhGroup) Server(c packetConn, randSource io.Reader, magic...
type ecdh (line 221) | type ecdh struct
method Client (line 225) | func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshak...
method Server (line 318) | func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshak...
function unmarshalECKey (line 277) | func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int,...
function validateECPublicKey (line 290) | func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
function ecHash (line 390) | func ecHash(curve elliptic.Curve) crypto.Hash {
function init (line 403) | func init() {
type curve25519sha256 (line 455) | type curve25519sha256 struct
method Client (line 475) | func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magi...
method Server (line 524) | func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magi...
type curve25519KeyPair (line 457) | type curve25519KeyPair struct
method generate (line 462) | func (kp *curve25519KeyPair) generate(rand io.Reader) error {
type dhGEXSHA (line 590) | type dhGEXSHA struct
method Client (line 600) | func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics...
method Server (line 694) | func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics ...
constant dhGroupExchangeMinimumBits (line 595) | dhGroupExchangeMinimumBits = 2048
constant dhGroupExchangePreferredBits (line 596) | dhGroupExchangePreferredBits = 2048
constant dhGroupExchangeMaximumBits (line 597) | dhGroupExchangeMaximumBits = 8192
FILE: gossh/crypto/ssh/keys.go
constant KeyAlgoRSA (line 39) | KeyAlgoRSA = "ssh-rsa"
constant KeyAlgoDSA (line 40) | KeyAlgoDSA = "ssh-dss"
constant KeyAlgoECDSA256 (line 41) | KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
constant KeyAlgoSKECDSA256 (line 42) | KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
constant KeyAlgoECDSA384 (line 43) | KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
constant KeyAlgoECDSA521 (line 44) | KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
constant KeyAlgoED25519 (line 45) | KeyAlgoED25519 = "ssh-ed25519"
constant KeyAlgoSKED25519 (line 46) | KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
constant KeyAlgoRSASHA256 (line 51) | KeyAlgoRSASHA256 = "rsa-sha2-256"
constant KeyAlgoRSASHA512 (line 52) | KeyAlgoRSASHA512 = "rsa-sha2-512"
constant SigAlgoRSA (line 57) | SigAlgoRSA = KeyAlgoRSA
constant SigAlgoRSASHA2256 (line 59) | SigAlgoRSASHA2256 = KeyAlgoRSASHA256
constant SigAlgoRSASHA2512 (line 61) | SigAlgoRSASHA2512 = KeyAlgoRSASHA512
function parsePubKey (line 66) | func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte,...
function parseAuthorizedKey (line 93) | func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err e...
function ParseKnownHosts (line 131) | func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey P...
function ParseAuthorizedKey (line 191) | func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, optio...
function ParsePublicKey (line 273) | func ParsePublicKey(in []byte) (out PublicKey, err error) {
function MarshalAuthorizedKey (line 289) | func MarshalAuthorizedKey(key PublicKey) []byte {
function MarshalPrivateKey (line 302) | func MarshalPrivateKey(key crypto.PrivateKey, comment string) (*pem.Bloc...
function MarshalPrivateKeyWithPassphrase (line 308) | func MarshalPrivateKeyWithPassphrase(key crypto.PrivateKey, comment stri...
type PublicKey (line 315) | type PublicKey interface
type CryptoPublicKey (line 332) | type CryptoPublicKey interface
type Signer (line 339) | type Signer interface
type AlgorithmSigner (line 356) | type AlgorithmSigner interface
type MultiAlgorithmSigner (line 368) | type MultiAlgorithmSigner interface
function NewSignerWithAlgorithms (line 380) | func NewSignerWithAlgorithms(signer AlgorithmSigner, algorithms []string...
type multiAlgorithmSigner (line 407) | type multiAlgorithmSigner struct
method Algorithms (line 412) | func (s *multiAlgorithmSigner) Algorithms() []string {
method isAlgorithmSupported (line 416) | func (s *multiAlgorithmSigner) isAlgorithmSupported(algorithm string) ...
method SignWithAlgorithm (line 428) | func (s *multiAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data ...
type rsaPublicKey (line 435) | type rsaPublicKey
method Type (line 437) | func (r *rsaPublicKey) Type() string {
method Marshal (line 466) | func (r *rsaPublicKey) Marshal() []byte {
method Verify (line 482) | func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
method CryptoPublicKey (line 494) | func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
function parseRSA (line 442) | func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
type dsaPublicKey (line 498) | type dsaPublicKey
method Type (line 500) | func (k *dsaPublicKey) Type() string {
method Marshal (line 541) | func (k *dsaPublicKey) Marshal() []byte {
method Verify (line 558) | func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
method CryptoPublicKey (line 582) | func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
function checkDSAParams (line 504) | func checkDSAParams(param *dsa.Parameters) error {
function parseDSA (line 516) | func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
type dsaPrivateKey (line 586) | type dsaPrivateKey struct
method PublicKey (line 590) | func (k *dsaPrivateKey) PublicKey() PublicKey {
method Sign (line 594) | func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature,...
method Algorithms (line 598) | func (k *dsaPrivateKey) Algorithms() []string {
method SignWithAlgorithm (line 602) | func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte,...
type ecdsaPublicKey (line 628) | type ecdsaPublicKey
method Type (line 630) | func (k *ecdsaPublicKey) Type() string {
method nistID (line 634) | func (k *ecdsaPublicKey) nistID() string {
method Marshal (line 735) | func (k *ecdsaPublicKey) Marshal() []byte {
method Verify (line 753) | func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
method CryptoPublicKey (line 781) | func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
type ed25519PublicKey (line 646) | type ed25519PublicKey
method Type (line 648) | func (k ed25519PublicKey) Type() string {
method Marshal (line 669) | func (k ed25519PublicKey) Marshal() []byte {
method Verify (line 680) | func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error {
method CryptoPublicKey (line 695) | func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
function parseED25519 (line 652) | func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
function supportedEllipticCurve (line 699) | func supportedEllipticCurve(curve elliptic.Curve) bool {
function parseECDSA (line 704) | func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
type skFields (line 787) | type skFields struct
type skECDSAPublicKey (line 796) | type skECDSAPublicKey struct
method Type (line 803) | func (k *skECDSAPublicKey) Type() string {
method nistID (line 807) | func (k *skECDSAPublicKey) nistID() string {
method Marshal (line 839) | func (k *skECDSAPublicKey) Marshal() []byte {
method Verify (line 857) | func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
function parseSKECDSA (line 811) | func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) {
type skEd25519PublicKey (line 907) | type skEd25519PublicKey struct
method Type (line 914) | func (k *skEd25519PublicKey) Type() string {
method Marshal (line 940) | func (k *skEd25519PublicKey) Marshal() []byte {
method Verify (line 953) | func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
function parseSKEd25519 (line 918) | func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) {
function NewSignerFromKey (line 1007) | func NewSignerFromKey(key any) (Signer, error) {
function newDSAPrivateKey (line 1018) | func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
type wrappedSigner (line 1026) | type wrappedSigner struct
method PublicKey (line 1043) | func (s *wrappedSigner) PublicKey() PublicKey {
method Sign (line 1047) | func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature,...
method Algorithms (line 1051) | func (s *wrappedSigner) Algorithms() []string {
method SignWithAlgorithm (line 1055) | func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte,...
function NewSignerFromSigner (line 1034) | func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
function NewPublicKey (line 1115) | func NewPublicKey(key any) (PublicKey, error) {
function ParsePrivateKey (line 1139) | func ParsePrivateKey(pemBytes []byte) (Signer, error) {
function ParsePrivateKeyWithPassphrase (line 1151) | func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer,...
function encryptedBlock (line 1164) | func encryptedBlock(block *pem.Block) bool {
type PassphraseMissingError (line 1170) | type PassphraseMissingError struct
method Error (line 1176) | func (*PassphraseMissingError) Error() string {
function ParseRawPrivateKey (line 1183) | func ParseRawPrivateKey(pemBytes []byte) (any, error) {
function ParseRawPrivateKeyWithPassphrase (line 1213) | func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (any,...
function ParseDSAPrivateKey (line 1260) | func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
function unencryptedOpenSSHKey (line 1290) | func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyB...
function passphraseProtectedOpenSSHKey (line 1300) | func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc {
function unencryptedOpenSSHMarshaler (line 1345) | func unencryptedOpenSSHMarshaler(privKeyBlock []byte) ([]byte, string, s...
function passphraseProtectedOpenSSHMarshaler (line 1350) | func passphraseProtectedOpenSSHMarshaler(passphrase []byte) openSSHEncry...
constant privateKeyAuthMagic (line 1387) | privateKeyAuthMagic = "openssh-key-v1\x00"
type openSSHDecryptFunc (line 1389) | type openSSHDecryptFunc
type openSSHEncryptFunc (line 1390) | type openSSHEncryptFunc
type openSSHEncryptedPrivateKey (line 1392) | type openSSHEncryptedPrivateKey struct
type openSSHPrivateKey (line 1401) | type openSSHPrivateKey struct
type openSSHRSAPrivateKey (line 1408) | type openSSHRSAPrivateKey struct
type openSSHEd25519PrivateKey (line 1419) | type openSSHEd25519PrivateKey struct
type openSSHECDSAPrivateKey (line 1426) | type openSSHECDSAPrivateKey struct
function parseOpenSSHPrivateKey (line 1438) | func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (cry...
function marshalOpenSSHPrivateKey (line 1567) | func marshalOpenSSHPrivateKey(key crypto.PrivateKey, comment string, enc...
function checkOpenSSHKeyPadding (line 1692) | func checkOpenSSHKeyPadding(pad []byte) error {
function generateOpenSSHPadding (line 1701) | func generateOpenSSHPadding(block []byte, blockSize int) []byte {
function FingerprintLegacyMD5 (line 1710) | func FingerprintLegacyMD5(pubKey PublicKey) string {
function FingerprintSHA256 (line 1724) | func FingerprintSHA256(pubKey PublicKey) string {
FILE: gossh/crypto/ssh/knownhosts/knownhosts.go
type addr (line 31) | type addr struct
method String (line 33) | func (a *addr) String() string {
type matcher (line 41) | type matcher interface
type hostPattern (line 45) | type hostPattern struct
method String (line 50) | func (p *hostPattern) String() string {
method match (line 109) | func (p *hostPattern) match(a addr) bool {
type hostPatterns (line 59) | type hostPatterns
method match (line 61) | func (ps hostPatterns) match(a addr) bool {
function wildcardMatch (line 78) | func wildcardMatch(pat []byte, str []byte) bool {
type keyDBLine (line 113) | type keyDBLine struct
method match (line 123) | func (l *keyDBLine) match(a addr) bool {
function serialize (line 119) | func serialize(k ssh.PublicKey) string {
type hostKeyDB (line 127) | type hostKeyDB struct
method IsHostAuthority (line 146) | func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address str...
method IsRevoked (line 162) | func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool {
method parseLine (line 210) | func (db *hostKeyDB) parseLine(line []byte, filename string, linenum i...
method check (line 329) | func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ...
method checkAddr (line 356) | func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error {
method Read (line 392) | func (db *hostKeyDB) Read(r io.Reader, filename string) error {
function newHostKeyDB (line 133) | func newHostKeyDB() *hostKeyDB {
function keyEq (line 141) | func keyEq(a, b ssh.PublicKey) bool {
constant markerCert (line 167) | markerCert = "@cert-authority"
constant markerRevoked (line 168) | markerRevoked = "@revoked"
function nextWord (line 170) | func nextWord(line []byte) (string, []byte) {
function parseLine (line 179) | func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err...
function newHostnameMatcher (line 249) | func newHostnameMatcher(pattern string) (matcher, error) {
type KnownKey (line 289) | type KnownKey struct
method String (line 295) | func (k *KnownKey) String() string {
type KeyError (line 303) | type KeyError struct
method Error (line 311) | func (u *KeyError) Error() string {
type RevokedError (line 319) | type RevokedError struct
method Error (line 323) | func (r *RevokedError) Error() string {
function New (line 417) | func New(files ...string) (ssh.HostKeyCallback, error) {
function Normalize (line 439) | func Normalize(address string) string {
function Line (line 455) | func Line(addresses []string, key ssh.PublicKey) string {
function HashHostname (line 466) | func HashHostname(hostname string) string {
function decodeHash (line 479) | func decodeHash(encoded string) (hashType string, salt, hash []byte, err...
function encodeHash (line 500) | func encodeHash(typ string, salt []byte, hash []byte) string {
function hashHost (line 509) | func hashHost(hostname string, salt []byte) []byte {
type hashedHost (line 515) | type hashedHost struct
method match (line 538) | func (h *hashedHost) match(a addr) bool {
constant sha1HashType (line 520) | sha1HashType = "1"
function newHashedHost (line 522) | func newHashedHost(encoded string) (*hashedHost, error) {
FILE: gossh/crypto/ssh/mac.go
type macMode (line 17) | type macMode struct
type truncatingMAC (line 25) | type truncatingMAC struct
method Write (line 30) | func (t truncatingMAC) Write(data []byte) (int, error) {
method Sum (line 34) | func (t truncatingMAC) Sum(in []byte) []byte {
method Reset (line 39) | func (t truncatingMAC) Reset() {
method Size (line 43) | func (t truncatingMAC) Size() int {
method BlockSize (line 47) | func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
FILE: gossh/crypto/ssh/messages.go
constant msgIgnore (line 22) | msgIgnore = 2
constant msgUnimplemented (line 23) | msgUnimplemented = 3
constant msgDebug (line 24) | msgDebug = 4
constant msgNewKeys (line 25) | msgNewKeys = 21
constant msgDisconnect (line 36) | msgDisconnect = 1
type disconnectMsg (line 40) | type disconnectMsg struct
method Error (line 46) | func (d *disconnectMsg) Error() string {
constant msgKexInit (line 51) | msgKexInit = 20
type kexInitMsg (line 53) | type kexInitMsg struct
constant msgKexDHInit (line 72) | msgKexDHInit = 30
type kexDHInitMsg (line 74) | type kexDHInitMsg struct
constant msgKexECDHInit (line 78) | msgKexECDHInit = 30
type kexECDHInitMsg (line 80) | type kexECDHInitMsg struct
constant msgKexECDHReply (line 84) | msgKexECDHReply = 31
type kexECDHReplyMsg (line 86) | type kexECDHReplyMsg struct
constant msgKexDHReply (line 92) | msgKexDHReply = 31
type kexDHReplyMsg (line 94) | type kexDHReplyMsg struct
constant msgKexDHGexGroup (line 101) | msgKexDHGexGroup = 31
type kexDHGexGroupMsg (line 103) | type kexDHGexGroupMsg struct
constant msgKexDHGexInit (line 108) | msgKexDHGexInit = 32
type kexDHGexInitMsg (line 110) | type kexDHGexInitMsg struct
constant msgKexDHGexReply (line 114) | msgKexDHGexReply = 33
type kexDHGexReplyMsg (line 116) | type kexDHGexReplyMsg struct
constant msgKexDHGexRequest (line 122) | msgKexDHGexRequest = 34
type kexDHGexRequestMsg (line 124) | type kexDHGexRequestMsg struct
constant msgServiceRequest (line 131) | msgServiceRequest = 5
type serviceRequestMsg (line 133) | type serviceRequestMsg struct
constant msgServiceAccept (line 138) | msgServiceAccept = 6
type serviceAcceptMsg (line 140) | type serviceAcceptMsg struct
constant msgExtInfo (line 145) | msgExtInfo = 7
type extInfoMsg (line 147) | type extInfoMsg struct
constant msgUserAuthRequest (line 153) | msgUserAuthRequest = 50
type userAuthRequestMsg (line 155) | type userAuthRequestMsg struct
type userAuthSuccessMsg (line 163) | type userAuthSuccessMsg struct
constant msgUserAuthFailure (line 167) | msgUserAuthFailure = 51
type userAuthFailureMsg (line 169) | type userAuthFailureMsg struct
constant msgUserAuthSuccess (line 175) | msgUserAuthSuccess = 52
constant msgUserAuthBanner (line 178) | msgUserAuthBanner = 53
type userAuthBannerMsg (line 180) | type userAuthBannerMsg struct
constant msgUserAuthInfoRequest (line 187) | msgUserAuthInfoRequest = 60
constant msgUserAuthInfoResponse (line 188) | msgUserAuthInfoResponse = 61
type userAuthInfoRequestMsg (line 190) | type userAuthInfoRequestMsg struct
constant msgChannelOpen (line 199) | msgChannelOpen = 90
type channelOpenMsg (line 201) | type channelOpenMsg struct
constant msgChannelExtendedData (line 209) | msgChannelExtendedData = 95
constant msgChannelData (line 210) | msgChannelData = 94
type channelDataMsg (line 213) | type channelDataMsg struct
constant msgChannelOpenConfirm (line 220) | msgChannelOpenConfirm = 91
type channelOpenConfirmMsg (line 222) | type channelOpenConfirmMsg struct
constant msgChannelOpenFailure (line 231) | msgChannelOpenFailure = 92
type channelOpenFailureMsg (line 233) | type channelOpenFailureMsg struct
constant msgChannelRequest (line 240) | msgChannelRequest = 98
type channelRequestMsg (line 242) | type channelRequestMsg struct
constant msgChannelSuccess (line 250) | msgChannelSuccess = 99
type channelRequestSuccessMsg (line 252) | type channelRequestSuccessMsg struct
constant msgChannelFailure (line 257) | msgChannelFailure = 100
type channelRequestFailureMsg (line 259) | type channelRequestFailureMsg struct
constant msgChannelClose (line 264) | msgChannelClose = 97
type channelCloseMsg (line 266) | type channelCloseMsg struct
constant msgChannelEOF (line 271) | msgChannelEOF = 96
type channelEOFMsg (line 273) | type channelEOFMsg struct
constant msgGlobalRequest (line 278) | msgGlobalRequest = 80
type globalRequestMsg (line 280) | type globalRequestMsg struct
constant msgRequestSuccess (line 287) | msgRequestSuccess = 81
type globalRequestSuccessMsg (line 289) | type globalRequestSuccessMsg struct
constant msgRequestFailure (line 294) | msgRequestFailure = 82
type globalRequestFailureMsg (line 296) | type globalRequestFailureMsg struct
constant msgChannelWindowAdjust (line 301) | msgChannelWindowAdjust = 93
type windowAdjustMsg (line 303) | type windowAdjustMsg struct
constant msgUserAuthPubKeyOk (line 309) | msgUserAuthPubKeyOk = 60
type userAuthPubKeyOkMsg (line 311) | type userAuthPubKeyOkMsg struct
constant msgUserAuthGSSAPIResponse (line 317) | msgUserAuthGSSAPIResponse = 60
type userAuthGSSAPIResponse (line 319) | type userAuthGSSAPIResponse struct
constant msgUserAuthGSSAPIToken (line 323) | msgUserAuthGSSAPIToken = 61
type userAuthGSSAPIToken (line 325) | type userAuthGSSAPIToken struct
constant msgUserAuthGSSAPIMIC (line 329) | msgUserAuthGSSAPIMIC = 66
type userAuthGSSAPIMIC (line 331) | type userAuthGSSAPIMIC struct
constant msgUserAuthGSSAPIErrTok (line 336) | msgUserAuthGSSAPIErrTok = 64
type userAuthGSSAPIErrTok (line 338) | type userAuthGSSAPIErrTok struct
constant msgUserAuthGSSAPIError (line 343) | msgUserAuthGSSAPIError = 65
type userAuthGSSAPIError (line 345) | type userAuthGSSAPIError struct
constant msgPing (line 353) | msgPing = 192
type pingMsg (line 355) | type pingMsg struct
constant msgPong (line 360) | msgPong = 193
type pongMsg (line 362) | type pongMsg struct
function typeTags (line 368) | func typeTags(structType reflect.Type) (tags []byte) {
function fieldError (line 381) | func fieldError(t reflect.Type, field int, problem string) error {
function Unmarshal (line 396) | func Unmarshal(data []byte, out any) error {
function Marshal (line 519) | func Marshal(msg any) []byte {
function marshalStruct (line 524) | func marshalStruct(out []byte, msg any) []byte {
function parseString (line 607) | func parseString(in []byte) (out, rest []byte, ok bool) {
function parseNameList (line 627) | func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
function parseInt (line 644) | func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
function parseUint32 (line 668) | func parseUint32(in []byte) (uint32, []byte, bool) {
function parseUint64 (line 675) | func parseUint64(in []byte) (uint64, []byte, bool) {
function intLength (line 682) | func intLength(n *big.Int) int {
function marshalUint32 (line 707) | func marshalUint32(to []byte, n uint32) []byte {
function marshalUint64 (line 712) | func marshalUint64(to []byte, n uint64) []byte {
function marshalInt (line 717) | func marshalInt(to []byte, n *big.Int) []byte {
function writeInt (line 764) | func writeInt(w io.Writer, n *big.Int) {
function writeString (line 771) | func writeString(w io.Writer, s []byte) {
function stringLength (line 781) | func stringLength(n int) int {
function marshalString (line 785) | func marshalString(to []byte, s []byte) []byte {
function decode (line 798) | func decode(packet []byte) (any, error) {
FILE: gossh/crypto/ssh/mux.go
constant debugMux (line 18) | debugMux = false
type chanList (line 21) | type chanList struct
method add (line 36) | func (c *chanList) add(ch *channel) uint32 {
method getChan (line 50) | func (c *chanList) getChan(id uint32) *channel {
method remove (line 61) | func (c *chanList) remove(id uint32) {
method dropAll (line 71) | func (c *chanList) dropAll() []*channel {
type mux (line 88) | type mux struct
method Wait (line 106) | func (m *mux) Wait() error {
method sendMessage (line 132) | func (m *mux) sendMessage(msg any) error {
method SendRequest (line 140) | func (m *mux) SendRequest(name string, wantReply bool, payload []byte)...
method ackRequest (line 174) | func (m *mux) ackRequest(ok bool, data []byte) error {
method Close (line 181) | func (m *mux) Close() error {
method loop (line 187) | func (m *mux) loop() {
method onePacket (line 214) | func (m *mux) onePacket() error {
method handleGlobalPacket (line 255) | func (m *mux) handleGlobalPacket(packet []byte) error {
method handleChannelOpen (line 279) | func (m *mux) handleChannelOpen(packet []byte) error {
method OpenChannel (line 303) | func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-c...
method openChannel (line 312) | func (m *mux) openChannel(chanType string, extra []byte) (*channel, er...
method handleUnknownChannelPacket (line 338) | func (m *mux) handleUnknownChannelPacket(id uint32, packet []byte) err...
function newMux (line 116) | func newMux(p packetConn) *mux {
FILE: gossh/crypto/ssh/server.go
type Permissions (line 21) | type Permissions struct
type GSSAPIWithMICConfig (line 48) | type GSSAPIWithMICConfig struct
type ServerConfig (line 63) | type ServerConfig struct
method AddHostKey (line 140) | func (s *ServerConfig) AddHostKey(key Signer) {
type cachedPubKey (line 153) | type cachedPubKey struct
constant maxCachedPubKeys (line 160) | maxCachedPubKeys = 16
type pubKeyCache (line 166) | type pubKeyCache struct
method get (line 171) | func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKe...
method add (line 181) | func (c *pubKeyCache) add(candidate cachedPubKey) {
type ServerConn (line 189) | type ServerConn struct
function NewServerConn (line 205) | func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-cha...
function signAndMarshal (line 243) | func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo...
method serverHandshake (line 253) | func (s *connection) serverHandshake(config *ServerConfig) (*Permissions...
function checkSourceAddress (line 312) | func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
function gssExchangeToken (line 342) | func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, token []byte, s...
function isAlgoCompatible (line 395) | func isAlgoCompatible(algo, sigFormat string) bool {
type ServerAuthError (line 415) | type ServerAuthError struct
method Error (line 421) | func (l ServerAuthError) Error() string {
method serverAuthenticate (line 436) | func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissi...
type sshClientKeyboardInteractive (line 750) | type sshClientKeyboardInteractive struct
method Challenge (line 754) | func (c *sshClientKeyboardInteractive) Challenge(name, instruction str...
FILE: gossh/crypto/ssh/session.go
type Signal (line 19) | type Signal
constant SIGABRT (line 23) | SIGABRT Signal = "ABRT"
constant SIGALRM (line 24) | SIGALRM Signal = "ALRM"
constant SIGFPE (line 25) | SIGFPE Signal = "FPE"
constant SIGHUP (line 26) | SIGHUP Signal = "HUP"
constant SIGILL (line 27) | SIGILL Signal = "ILL"
constant SIGINT (line 28) | SIGINT Signal = "INT"
constant SIGKILL (line 29) | SIGKILL Signal = "KILL"
constant SIGPIPE (line 30) | SIGPIPE Signal = "PIPE"
constant SIGQUIT (line 31) | SIGQUIT Signal = "QUIT"
constant SIGSEGV (line 32) | SIGSEGV Signal = "SEGV"
constant SIGTERM (line 33) | SIGTERM Signal = "TERM"
constant SIGUSR1 (line 34) | SIGUSR1 Signal = "USR1"
constant SIGUSR2 (line 35) | SIGUSR2 Signal = "USR2"
type TerminalModes (line 52) | type TerminalModes
constant tty_OP_END (line 56) | tty_OP_END = 0
constant VINTR (line 57) | VINTR = 1
constant VQUIT (line 58) | VQUIT = 2
constant VERASE (line 59) | VERASE = 3
constant VKILL (line 60) | VKILL = 4
constant VEOF (line 61) | VEOF = 5
constant VEOL (line 62) | VEOL = 6
constant VEOL2 (line 63) | VEOL2 = 7
constant VSTART (line 64) | VSTART = 8
constant VSTOP (line 65) | VSTOP = 9
constant VSUSP (line 66) | VSUSP = 10
constant VDSUSP (line 67) | VDSUSP = 11
constant VREPRINT (line 68) | VREPRINT = 12
constant VWERASE (line 69) | VWERASE = 13
constant VLNEXT (line 70) | VLNEXT = 14
constant VFLUSH (line 71) | VFLUSH = 15
constant VSWTCH (line 72) | VSWTCH = 16
constant VSTATUS (line 73) | VSTATUS = 17
constant VDISCARD (line 74) | VDISCARD = 18
constant IGNPAR (line 75) | IGNPAR = 30
constant PARMRK (line 76) | PARMRK = 31
constant INPCK (line 77) | INPCK = 32
constant ISTRIP (line 78) | ISTRIP = 33
constant INLCR (line 79) | INLCR = 34
constant IGNCR (line 80) | IGNCR = 35
constant ICRNL (line 81) | ICRNL = 36
constant IUCLC (line 82) | IUCLC = 37
constant IXON (line 83) | IXON = 38
constant IXANY (line 84) | IXANY = 39
constant IXOFF (line 85) | IXOFF = 40
constant IMAXBEL (line 86) | IMAXBEL = 41
constant IUTF8 (line 87) | IUTF8 = 42
constant ISIG (line 88) | ISIG = 50
constant ICANON (line 89) | ICANON = 51
constant XCASE (line 90) | XCASE = 52
constant ECHO (line 91) | ECHO = 53
constant ECHOE (line 92) | ECHOE = 54
constant ECHOK (line 93) | ECHOK = 55
constant ECHONL (line 94) | ECHONL = 56
constant NOFLSH (line 95) | NOFLSH = 57
constant TOSTOP (line 96) | TOSTOP = 58
constant IEXTEN (line 97) | IEXTEN = 59
constant ECHOCTL (line 98) | ECHOCTL = 60
constant ECHOKE (line 99) | ECHOKE = 61
constant PENDIN (line 100) | PENDIN = 62
constant OPOST (line 101) | OPOST = 70
constant OLCUC (line 102) | OLCUC = 71
constant ONLCR (line 103) | ONLCR = 72
constant OCRNL (line 104) | OCRNL = 73
constant ONOCR (line 105) | ONOCR = 74
constant ONLRET (line 106) | ONLRET = 75
constant CS7 (line 107) | CS7 = 90
constant CS8 (line 108) | CS8 = 91
constant PARENB (line 109) | PARENB = 92
constant PARODD (line 110) | PARODD = 93
constant TTY_OP_ISPEED (line 111) | TTY_OP_ISPEED = 128
constant TTY_OP_OSPEED (line 112) | TTY_OP_OSPEED = 129
type Session (line 116) | type Session struct
method SendRequest (line 151) | func (s *Session) SendRequest(name string, wantReply bool, payload []b...
method Close (line 155) | func (s *Session) Close() error {
method Setenv (line 167) | func (s *Session) Setenv(name, value string) error {
method RequestPty (line 190) | func (s *Session) RequestPty(term string, h, w int, termmodes Terminal...
method RequestSubsystem (line 223) | func (s *Session) RequestSubsystem(subsystem string) error {
method WindowChange (line 243) | func (s *Session) WindowChange(h, w int) error {
method Signal (line 261) | func (s *Session) Signal(sig Signal) error {
method Start (line 278) | func (s *Session) Start(cmd string) error {
method Run (line 309) | func (s *Session) Run(cmd string) error {
method Output (line 318) | func (s *Session) Output(cmd string) ([]byte, error) {
method CombinedOutput (line 341) | func (s *Session) CombinedOutput(cmd string) ([]byte, error) {
method Shell (line 357) | func (s *Session) Shell() error {
method start (line 372) | func (s *Session) start() error {
method Wait (line 399) | func (s *Session) Wait() error {
method wait (line 420) | func (s *Session) wait(reqs <-chan *Request) error {
method stdin (line 479) | func (s *Session) stdin() {
method stdout (line 503) | func (s *Session) stdout() {
method stderr (line 516) | func (s *Session) stderr() {
method StdinPipe (line 541) | func (s *Session) StdinPipe() (io.WriteCloser, error) {
method StdoutPipe (line 558) | func (s *Session) StdoutPipe() (io.Reader, error) {
method StderrPipe (line 575) | func (s *Session) StderrPipe() (io.Reader, error) {
type setenvRequest (line 160) | type setenvRequest struct
type ptyRequestMsg (line 180) | type ptyRequestMsg struct
type subsystemRequestMsg (line 217) | type subsystemRequestMsg struct
type ptyWindowChangeMsg (line 235) | type ptyWindowChangeMsg struct
type signalMsg (line 255) | type signalMsg struct
type execMsg (line 271) | type execMsg struct
type singleWriter (line 328) | type singleWriter struct
method Write (line 333) | func (w *singleWriter) Write(p []byte) (int, error) {
type ExitMissingError (line 473) | type ExitMissingError struct
method Error (line 475) | func (e *ExitMissingError) Error() string {
type sessionStdin (line 530) | type sessionStdin struct
method Close (line 535) | func (s *sessionStdin) Close() error {
function newSession (line 587) | func newSession(ch Channel, reqs <-chan *Request) (*Session, error) {
type ExitError (line 600) | type ExitError struct
method Error (line 604) | func (e *ExitError) Error() string {
type Waitmsg (line 610) | type Waitmsg struct
method ExitStatus (line 618) | func (w Waitmsg) ExitStatus() int {
method Signal (line 624) | func (w Waitmsg) Signal() string {
method Msg (line 629) | func (w Waitmsg) Msg() string {
method Lang (line 634) | func (w Waitmsg) Lang() string {
method String (line 638) | func (w Waitmsg) String() string {
FILE: gossh/crypto/ssh/ssh_gss.go
function init (line 14) | func init() {
type GSSAPIClient (line 19) | type GSSAPIClient interface
type GSSAPIServer (line 58) | type GSSAPIServer interface
type userAuthRequestGSSAPI (line 99) | type userAuthRequestGSSAPI struct
function parseGSSAPIPayload (line 104) | func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) {
function buildMIC (line 131) | func buildMIC(sessionID string, username string, service string, authMet...
FILE: gossh/crypto/ssh/streamlocal.go
type streamLocalChannelOpenDirectMsg (line 14) | type streamLocalChannelOpenDirectMsg struct
type forwardedStreamLocalPayload (line 22) | type forwardedStreamLocalPayload struct
type streamLocalChannelForwardMsg (line 29) | type streamLocalChannelForwardMsg struct
method ListenUnix (line 34) | func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
method dialStreamLocal (line 52) | func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
type unixListener (line 64) | type unixListener struct
method Accept (line 72) | func (l *unixListener) Accept() (net.Conn, error) {
method Close (line 97) | func (l *unixListener) Close() error {
method Addr (line 111) | func (l *unixListener) Addr() net.Addr {
FILE: gossh/crypto/ssh/tcpip.go
method Listen (line 25) | func (c *Client) Listen(n, addr string) (net.Listener, error) {
constant openSSHPrefix (line 47) | openSSHPrefix = "OpenSSH_"
function isBrokenOpenSSHVersion (line 54) | func isBrokenOpenSSHVersion(versionStr string) bool {
method autoPortListenWorkaround (line 72) | func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Liste...
type channelForwardMsg (line 89) | type channelForwardMsg struct
method handleForwards (line 97) | func (c *Client) handleForwards() {
method ListenTCP (line 105) | func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
type forwardList (line 144) | type forwardList struct
method add (line 164) | func (l *forwardList) add(addr net.Addr) chan forward {
method handleChannels (line 195) | func (l *forwardList) handleChannels(in <-chan NewChannel) {
method remove (line 255) | func (l *forwardList) remove(addr net.Addr) {
method closeAll (line 268) | func (l *forwardList) closeAll() {
method forward (line 277) | func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bo...
type forwardEntry (line 151) | type forwardEntry struct
type forward (line 159) | type forward struct
type forwardedTCPPayload (line 176) | type forwardedTCPPayload struct
function parseTCPAddr (line 184) | func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
type tcpListener (line 289) | type tcpListener struct
method Accept (line 297) | func (l *tcpListener) Accept() (net.Conn, error) {
method Close (line 316) | func (l *tcpListener) Close() error {
method Addr (line 332) | func (l *tcpListener) Addr() net.Addr {
method DialContext (line 343) | func (c *Client) DialContext(ctx context.Context, n, addr string) (net.C...
method Dial (line 372) | func (c *Client) Dial(n, addr string) (net.Conn, error) {
method DialTCP (line 424) | func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn,...
type channelOpenDirectMsg (line 443) | type channelOpenDirectMsg struct
method dial (line 450) | func (c *Client) dial(laddr string, lport int, raddr string, rport int) ...
type tcpChan (line 465) | type tcpChan struct
type chanConn (line 471) | type chanConn struct
method LocalAddr (line 477) | func (t *chanConn) LocalAddr() net.Addr {
method RemoteAddr (line 482) | func (t *chanConn) RemoteAddr() net.Addr {
method SetDeadline (line 488) | func (t *chanConn) SetDeadline(deadline time.Time) error {
method SetReadDeadline (line 499) | func (t *chanConn) SetReadDeadline(deadline time.Time) error {
method SetWriteDeadline (line 507) | func (t *chanConn) SetWriteDeadline(deadline time.Time) error {
FILE: gossh/crypto/ssh/terminal/terminal.go
function NewTerminal (line 29) | func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
function IsTerminal (line 43) | func IsTerminal(fd int) bool {
function ReadPassword (line 50) | func ReadPassword(fd int) ([]byte, error) {
function MakeRaw (line 57) | func MakeRaw(fd int) (*State, error) {
function Restore (line 63) | func Restore(fd int, oldState *State) error {
function GetState (line 69) | func GetState(fd int) (*State, error) {
function GetSize (line 74) | func GetSize(fd int) (width, height int, err error) {
FILE: gossh/crypto/ssh/transport.go
constant debugTransport (line 17) | debugTransport = false
constant gcm128CipherID (line 20) | gcm128CipherID = "aes128-gcm@openssh.com"
constant gcm256CipherID (line 21) | gcm256CipherID = "aes256-gcm@openssh.com"
constant aes128cbcID (line 22) | aes128cbcID = "aes128-cbc"
constant tripledescbcID (line 23) | tripledescbcID = "3des-cbc"
type packetConn (line 28) | type packetConn interface
type transport (line 43) | type transport struct
method setStrictMode (line 80) | func (t *transport) setStrictMode() error {
method setInitialKEXDone (line 88) | func (t *transport) setInitialKEXDone() {
method prepareKeyChange (line 95) | func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexR...
method printPacket (line 111) | func (t *transport) printPacket(p []byte, write bool) {
method readPacket (line 128) | func (t *transport) readPacket() (p []byte, err error) {
method writePacket (line 188) | func (t *transport) writePacket(packet []byte) error {
type packetCipher (line 59) | type packetCipher interface
type connectionState (line 73) | type connectionState struct
method readPacket (line 146) | func (s *connectionState) readPacket(r *bufio.Reader, strictMode bool)...
method writePacket (line 195) | func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader,...
function newTransport (line 220) | func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool)...
type direction (line 248) | type direction struct
function newPacketCipher (line 262) | func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResu...
function generateKeyMaterial (line 283) | func generateKeyMaterial(out, tag []byte, r *kexResult) {
constant packageVersion (line 308) | packageVersion = "SSH-2.0-Go"
function exchangeVersions (line 313) | func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte...
constant maxVersionStringBytes (line 335) | maxVersionStringBytes = 255
function readVersion (line 338) | func readVersion(r io.Reader) ([]byte, error) {
FILE: gossh/gin/auth.go
constant AuthUserKey (line 17) | AuthUserKey = "user"
constant AuthProxyUserKey (line 20) | AuthProxyUserKey = "proxy_user"
type Accounts (line 23) | type Accounts
type authPair (line 25) | type authPair struct
type authPairs (line 30) | type authPairs
method searchCredential (line 32) | func (a authPairs) searchCredential(authValue string) (string, bool) {
function BasicAuthForRealm (line 48) | func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc {
function BasicAuth (line 72) | func BasicAuth(accounts Accounts) HandlerFunc {
function processAccounts (line 76) | func processAccounts(accounts Accounts) authPairs {
function authorizationHeader (line 91) | func authorizationHeader(user, password string) string {
function BasicAuthForProxy (line 98) | func BasicAuthForProxy(accounts Accounts, realm string) HandlerFunc {
FILE: gossh/gin/binding/binding.go
constant MIMEJSON (line 11) | MIMEJSON = "application/json"
constant MIMEHTML (line 12) | MIMEHTML = "text/html"
constant MIMEXML (line 13) | MIMEXML = "application/xml"
constant MIMEXML2 (line 14) | MIMEXML2 = "text/xml"
constant MIMEPlain (line 15) | MIMEPlain = "text/plain"
constant MIMEPOSTForm (line 16) | MIMEPOSTForm = "application/x-www-form-urlencoded"
constant MIMEMultipartPOSTForm (line 17) | MIMEMultipartPOSTForm = "multipart/form-data"
type Binding (line 23) | type Binding interface
type BindingBody (line 30) | type BindingBody interface
type BindingUri (line 37) | type BindingUri interface
type StructValidator (line 46) | type StructValidator interface
function Default (line 80) | func Default(method, contentType string) Binding {
function validate (line 97) | func validate(obj any) error {
FILE: gossh/gin/binding/default_validator.go
type defaultValidator (line 16) | type defaultValidator struct
method ValidateStruct (line 49) | func (v *defaultValidator) ValidateStruct(obj any) error {
method validateStruct (line 81) | func (v *defaultValidator) validateStruct(obj any) error {
method Engine (line 90) | func (v *defaultValidator) Engine() any {
method lazyinit (line 95) | func (v *defaultValidator) lazyinit() {
type SliceValidationError (line 21) | type SliceValidationError
method Error (line 24) | func (err SliceValidationError) Error() string {
FILE: gossh/gin/binding/form.go
constant defaultMemory (line 12) | defaultMemory = 32 << 20
type formBinding (line 14) | type formBinding struct
method Name (line 18) | func (formBinding) Name() string {
method Bind (line 22) | func (formBinding) Bind(req *http.Request, obj any) error {
type formPostBinding (line 15) | type formPostBinding struct
method Name (line 35) | func (formPostBinding) Name() string {
method Bind (line 39) | func (formPostBinding) Bind(req *http.Request, obj any) error {
type formMultipartBinding (line 16) | type formMultipartBinding struct
method Name (line 49) | func (formMultipartBinding) Name() string {
method Bind (line 53) | func (formMultipartBinding) Bind(req *http.Request, obj any) error {
FILE: gossh/gin/binding/form_mapping.go
function mapURI (line 30) | func mapURI(ptr any, m map[string][]string) error {
function mapForm (line 34) | func mapForm(ptr any, form map[string][]string) error {
function MapFormWithTag (line 38) | func MapFormWithTag(ptr any, form map[string][]string, tag string) error {
function mapFormByTag (line 44) | func mapFormByTag(ptr any, form map[string][]string, tag string) error {
type setter (line 64) | type setter interface
type formSource (line 68) | type formSource
method TrySet (line 73) | func (form formSource) TrySet(value reflect.Value, field reflect.Struc...
function mappingByPtr (line 77) | func mappingByPtr(ptr any, setter setter, tag string) error {
function mapping (line 82) | func mapping(value reflect.Value, field reflect.StructField, setter sett...
type setOptions (line 136) | type setOptions struct
function tryToSetValue (line 141) | func tryToSetValue(value reflect.Value, field reflect.StructField, sette...
function setByForm (line 168) | func setByForm(value reflect.Value, field reflect.StructField, form map[...
function setWithProperType (line 201) | func setWithProperType(val string, value reflect.Value, field reflect.St...
function setIntField (line 256) | func setIntField(val string, bitSize int, field reflect.Value) error {
function setUintField (line 267) | func setUintField(val string, bitSize int, field reflect.Value) error {
function setBoolField (line 278) | func setBoolField(val string, field reflect.Value) error {
function setFloatField (line 289) | func setFloatField(val string, bitSize int, field reflect.Value) error {
function setTimeField (line 300) | func setTimeField(val string, structField reflect.StructField, value ref...
function setArray (line 350) | func setArray(vals []string, value reflect.Value, field reflect.StructFi...
function setSlice (line 360) | func setSlice(vals []string, value reflect.Value, field reflect.StructFi...
function setTimeDuration (line 370) | func setTimeDuration(val string, value reflect.Value) error {
function head (line 379) | func head(str, sep string) (head string, tail string) {
function setFormMap (line 387) | func setFormMap(ptr any, form map[string][]string) error {
FILE: gossh/gin/binding/header.go
type headerBinding (line 13) | type headerBinding struct
method Name (line 15) | func (headerBinding) Name() string {
method Bind (line 19) | func (headerBinding) Bind(req *http.Request, obj any) error {
function mapHeader (line 28) | func mapHeader(ptr any, h map[string][]string) error {
type headerSource (line 32) | type headerSource
method TrySet (line 36) | func (hs headerSource) TrySet(value reflect.Value, field reflect.Struc...
FILE: gossh/gin/binding/json.go
type jsonBinding (line 27) | type jsonBinding struct
method Name (line 29) | func (jsonBinding) Name() string {
method Bind (line 33) | func (jsonBinding) Bind(req *http.Request, obj any) error {
method BindBody (line 40) | func (jsonBinding) BindBody(body []byte, obj any) error {
function decodeJSON (line 44) | func decodeJSON(r io.Reader, obj any) error {
FILE: gossh/gin/binding/multipart_form_mapping.go
type multipartRequest (line 14) | type multipartRequest
method TrySet (line 27) | func (r *multipartRequest) TrySet(value reflect.Value, field reflect.S...
function setByMultipartFormFile (line 35) | func setByMultipartFormFile(value reflect.Value, field reflect.StructFie...
function setArrayOfMultipartFormFiles (line 63) | func setArrayOfMultipartFormFiles(value reflect.Value, field reflect.Str...
FILE: gossh/gin/binding/query.go
type queryBinding (line 9) | type queryBinding struct
method Name (line 11) | func (queryBinding) Name() string {
method Bind (line 15) | func (queryBinding) Bind(req *http.Request, obj any) error {
FILE: gossh/gin/binding/uri.go
type uriBinding (line 7) | type uriBinding struct
method Name (line 9) | func (uriBinding) Name() string {
method BindUri (line 13) | func (uriBinding) BindUri(m map[string][]string, obj any) error {
FILE: gossh/gin/binding/xml.go
type xmlBinding (line 14) | type xmlBinding struct
method Name (line 16) | func (xmlBinding) Name() string {
method Bind (line 20) | func (xmlBinding) Bind(req *http.Request, obj any) error {
method BindBody (line 24) | func (xmlBinding) BindBody(body []byte, obj any) error {
function decodeXML (line 27) | func decodeXML(r io.Reader, obj any) error {
FILE: gossh/gin/context.go
constant MIMEJSON (line 28) | MIMEJSON = binding.MIMEJSON
constant MIMEHTML (line 29) | MIMEHTML = binding.MIMEHTML
constant MIMEXML (line 30) | MIMEXML = binding.MIMEXML
constant MIMEPlain (line 31) | MIMEPlain = binding.MIMEPlain
constant MIMEPOSTForm (line 32) | MIMEPOSTForm = binding.MIMEPOSTForm
constant MIMEMultipartPOSTForm (line 33) | MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
constant BodyBytesKey (line 37) | BodyBytesKey = "_gin-gonic/gin/bodybyteskey"
constant ContextKey (line 40) | ContextKey = "_gin-gonic/gin/contextkey"
type ContextKeyType (line 42) | type ContextKeyType
constant ContextRequestKey (line 44) | ContextRequestKey ContextKeyType = 0
constant abortIndex (line 47) | abortIndex int8 = math.MaxInt8 >> 1
type Context (line 51) | type Context struct
method reset (line 93) | func (c *Context) reset() {
method Copy (line 112) | func (c *Context) Copy() *Context {
method HandlerName (line 142) | func (c *Context) HandlerName() string {
method HandlerNames (line 148) | func (c *Context) HandlerNames() []string {
method Handler (line 157) | func (c *Context) Handler() HandlerFunc {
method FullPath (line 167) | func (c *Context) FullPath() string {
method Next (line 178) | func (c *Context) Next() {
method IsAborted (line 187) | func (c *Context) IsAborted() bool {
method Abort (line 195) | func (c *Context) Abort() {
method AbortWithStatus (line 201) | func (c *Context) AbortWithStatus(code int) {
method AbortWithStatusJSON (line 210) | func (c *Context) AbortWithStatusJSON(code int, jsonObj any) {
method AbortWithError (line 218) | func (c *Context) AbortWithError(code int, err error) *Error {
method Error (line 232) | func (c *Context) Error(err error) *Error {
method Set (line 256) | func (c *Context) Set(key string, value any) {
method Get (line 268) | func (c *Context) Get(key string) (value any, exists bool) {
method MustGet (line 276) | func (c *Context) MustGet(key string) any {
method GetString (line 284) | func (c *Context) GetString(key string) (s string) {
method GetBool (line 292) | func (c *Context) GetBool(key string) (b bool) {
method GetInt (line 300) | func (c *Context) GetInt(key string) (i int) {
method GetInt64 (line 308) | func (c *Context) GetInt64(key string) (i64 int64) {
method GetUint (line 316) | func (c *Context) GetUint(key string) (ui uint) {
method GetUint64 (line 324) | func (c *Context) GetUint64(key string) (ui64 uint64) {
method GetFloat64 (line 332) | func (c *Context) GetFloat64(key string) (f64 float64) {
method GetTime (line 340) | func (c *Context) GetTime(key string) (t time.Time) {
method GetDuration (line 348) | func (c *Context) GetDuration(key string) (d time.Duration) {
method GetStringSlice (line 356) | func (c *Context) GetStringSlice(key string) (ss []string) {
method GetStringMap (line 364) | func (c *Context) GetStringMap(key string) (sm map[string]any) {
method GetStringMapString (line 372) | func (c *Context) GetStringMapString(key string) (sms map[string]strin...
method GetStringMapStringSlice (line 380) | func (c *Context) GetStringMapStringSlice(key string) (smss map[string...
method Param (line 400) | func (c *Context) Param(key string) string {
method AddParam (line 409) | func (c *Context) AddParam(key, value string) {
method Query (line 422) | func (c *Context) Query(key string) (value string) {
method DefaultQuery (line 435) | func (c *Context) DefaultQuery(key, defaultValue string) string {
method GetQuery (line 451) | func (c *Context) GetQuery(key string) (string, bool) {
method QueryArray (line 460) | func (c *Context) QueryArray(key string) (values []string) {
method initQueryCache (line 465) | func (c *Context) initQueryCache() {
method GetQueryArray (line 477) | func (c *Context) GetQueryArray(key string) (values []string, ok bool) {
method QueryMap (line 484) | func (c *Context) QueryMap(key string) (dicts map[string]string) {
method GetQueryMap (line 491) | func (c *Context) GetQueryMap(key string) (map[string]string, bool) {
method PostForm (line 498) | func (c *Context) PostForm(key string) (value string) {
method DefaultPostForm (line 506) | func (c *Context) DefaultPostForm(key, defaultValue string) string {
method GetPostForm (line 521) | func (c *Context) GetPostForm(key string) (string, bool) {
method PostFormArray (line 530) | func (c *Context) PostFormArray(key string) (values []string) {
method initFormCache (line 535) | func (c *Context) initFormCache() {
method GetPostFormArray (line 550) | func (c *Context) GetPostFormArray(key string) (values []string, ok bo...
method PostFormMap (line 557) | func (c *Context) PostFormMap(key string) (dicts map[string]string) {
method GetPostFormMap (line 564) | func (c *Context) GetPostFormMap(key string) (map[string]string, bool) {
method get (line 570) | func (c *Context) get(m map[string][]string, key string) (map[string]s...
method FormFile (line 585) | func (c *Context) FormFile(name string) (*multipart.FileHeader, error) {
method MultipartForm (line 600) | func (c *Context) MultipartForm() (*multipart.Form, error) {
method SaveUploadedFile (line 606) | func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst str...
method Bind (line 636) | func (c *Context) Bind(obj any) error {
method BindJSON (line 642) | func (c *Context) BindJSON(obj any) error {
method BindXML (line 647) | func (c *Context) BindXML(obj any) error {
method BindQuery (line 652) | func (c *Context) BindQuery(obj any) error {
method BindHeader (line 657) | func (c *Context) BindHeader(obj any) error {
method BindUri (line 663) | func (c *Context) BindUri(obj any) error {
method MustBindWith (line 674) | func (c *Context) MustBindWith(obj any, b binding.Binding) error {
method ShouldBind (line 691) | func (c *Context) ShouldBind(obj any) error {
method ShouldBindJSON (line 697) | func (c *Context) ShouldBindJSON(obj any) error {
method ShouldBindXML (line 702) | func (c *Context) ShouldBindXML(obj any) error {
method ShouldBindQuery (line 707) | func (c *Context) ShouldBindQuery(obj any) error {
method ShouldBindHeader (line 712) | func (c *Context) ShouldBindHeader(obj any) error {
method ShouldBindUri (line 717) | func (c *Context) ShouldBindUri(obj any) error {
method ShouldBindWith (line 727) | func (c *Context) ShouldBindWith(obj any, b binding.Binding) error {
method ShouldBindBodyWith (line 736) | func (c *Context) ShouldBindBodyWith(obj any, bb binding.BindingBody) ...
method ShouldBindBodyWithJSON (line 754) | func (c *Context) ShouldBindBodyWithJSON(obj any) error {
method ShouldBindBodyWithXML (line 759) | func (c *Context) ShouldBindBodyWithXML(obj any) error {
method ClientIP (line 768) | func (c *Context) ClientIP() string {
method RemoteIP (line 798) | func (c *Context) RemoteIP() string {
method ContentType (line 807) | func (c *Context) ContentType() string {
method IsWebsocket (line 813) | func (c *Context) IsWebsocket() bool {
method requestHeader (line 821) | func (c *Context) requestHeader(key string) string {
method Status (line 843) | func (c *Context) Status(code int) {
method Header (line 850) | func (c *Context) Header(key, value string) {
method GetHeader (line 859) | func (c *Context) GetHeader(key string) string {
method GetRawData (line 864) | func (c *Context) GetRawData() ([]byte, error) {
method SetSameSite (line 872) | func (c *Context) SetSameSite(samesite http.SameSite) {
method SetCookie (line 879) | func (c *Context) SetCookie(name, value string, maxAge int, path, doma...
method Cookie (line 899) | func (c *Context) Cookie(name string) (string, error) {
method Render (line 909) | func (c *Context) Render(code int, r render.Render) {
method HTML (line 928) | func (c *Context) HTML(code int, name string, obj any) {
method IndentedJSON (line 937) | func (c *Context) IndentedJSON(code int, obj any) {
method SecureJSON (line 944) | func (c *Context) SecureJSON(code int, obj any) {
method JSONP (line 951) | func (c *Context) JSONP(code int, obj any) {
method JSON (line 962) | func (c *Context) JSON(code int, obj any) {
method AsciiJSON (line 968) | func (c *Context) AsciiJSON(code int, obj any) {
method PureJSON (line 974) | func (c *Context) PureJSON(code int, obj any) {
method XML (line 980) | func (c *Context) XML(code int, obj any) {
method String (line 985) | func (c *Context) String(code int, format string, values ...any) {
method Redirect (line 990) | func (c *Context) Redirect(code int, location string) {
method Data (line 999) | func (c *Context) Data(code int, contentType string, data []byte) {
method DataFromReader (line 1007) | func (c *Context) DataFromReader(code int, contentLength int64, conten...
method File (line 1017) | func (c *Context) File(filepath string) {
method FileFromFS (line 1022) | func (c *Context) FileFromFS(filepath string, fs http.FileSystem) {
method FileAttachment (line 1040) | func (c *Context) FileAttachment(filepath, filename string) {
method SSEvent (line 1050) | func (c *Context) SSEvent(name string, message any) {
method Stream (line 1059) | func (c *Context) Stream(step func(w io.Writer) bool) bool {
method Negotiate (line 1092) | func (c *Context) Negotiate(code int, config Negotiate) {
method NegotiateFormat (line 1112) | func (c *Context) NegotiateFormat(offered ...string) string {
method SetAccepted (line 1143) | func (c *Context) SetAccepted(formats ...string) {
method hasRequestContext (line 1152) | func (c *Context) hasRequestContext() bool {
method Deadline (line 1159) | func (c *Context) Deadline() (deadline time.Time, ok bool) {
method Done (line 1167) | func (c *Context) Done() <-chan struct{} {
method Err (line 1175) | func (c *Context) Err() error {
method Value (line 1185) | func (c *Context) Value(key any) any {
function bodyAllowedForStatus (line 830) | func bodyAllowedForStatus(status int) bool {
function escapeQuotes (line 1034) | func escapeQuotes(s string) string {
type Negotiate (line 1082) | type Negotiate struct
FILE: gossh/gin/debug.go
constant ginSupportMinGoVer (line 15) | ginSupportMinGoVer = 18
function IsDebugging (line 19) | func IsDebugging() bool {
function debugPrintRoute (line 29) | func debugPrintRoute(httpMethod, absolutePath string, handlers HandlersC...
function debugPrintLoadTemplate (line 41) | func debugPrintLoadTemplate(tmpl *template.Template) {
function debugPrint (line 53) | func debugPrint(format string, values ...any) {
function getMinVer (line 69) | func getMinVer(v string) (uint64, error) {
function debugPrintWARNINGDefault (line 78) | func debugPrintWARNINGDefault() {
function debugPrintWARNINGNew (line 89) | func debugPrintWARNINGNew() {
function debugPrintWARNINGSetHTMLTemplate (line 97) | func debugPrintWARNINGSetHTMLTemplate() {
function debugPrintError (line 107) | func debugPrintError(err error) {
FILE: gossh/gin/errors.go
type ErrorType (line 16) | type ErrorType
constant ErrorTypeBind (line 20) | ErrorTypeBind ErrorType = 1 << 63
constant ErrorTypeRender (line 22) | ErrorTypeRender ErrorType = 1 << 62
constant ErrorTypePrivate (line 24) | ErrorTypePrivate ErrorType = 1 << 0
constant ErrorTypePublic (line 26) | ErrorTypePublic ErrorType = 1 << 1
constant ErrorTypeAny (line 28) | ErrorTypeAny ErrorType = 1<<64 - 1
constant ErrorTypeNu (line 30) | ErrorTypeNu = 2
type Error (line 34) | type Error struct
method SetType (line 45) | func (msg *Error) SetType(flags ErrorType) *Error {
method SetMeta (line 51) | func (msg *Error) SetMeta(data any) *Error {
method JSON (line 57) | func (msg *Error) JSON() any {
method MarshalJSON (line 79) | func (msg *Error) MarshalJSON() ([]byte, error) {
method Error (line 84) | func (msg Error) Error() string {
method IsType (line 89) | func (msg *Error) IsType(flags ErrorType) bool {
method Unwrap (line 94) | func (msg *Error) Unwrap() error {
type errorMsgs (line 40) | type errorMsgs
method ByType (line 100) | func (a errorMsgs) ByType(typ ErrorType) errorMsgs {
method Last (line 118) | func (a errorMsgs) Last() *Error {
method Errors (line 132) | func (a errorMsgs) Errors() []string {
method JSON (line 143) | func (a errorMsgs) JSON() any {
method MarshalJSON (line 159) | func (a errorMsgs) MarshalJSON() ([]byte, error) {
method String (line 163) | func (a errorMsgs) String() string {
FILE: gossh/gin/fs.go
type onlyFilesFS (line 12) | type onlyFilesFS struct
method Open (line 33) | func (fs onlyFilesFS) Open(name string) (http.File, error) {
type neuteredReaddirFile (line 16) | type neuteredReaddirFile struct
method Readdir (line 42) | func (f neuteredReaddirFile) Readdir(_ int) ([]os.FileInfo, error) {
function Dir (line 24) | func Dir(root string, listDirectory bool) http.FileSystem {
FILE: gossh/gin/gin.go
constant defaultMultipartMemory (line 22) | defaultMultipartMemory = 32 << 20
type HandlerFunc (line 46) | type HandlerFunc
type OptionFunc (line 49) | type OptionFunc
type HandlersChain (line 52) | type HandlersChain
method Last (line 55) | func (c HandlersChain) Last() HandlerFunc {
type RouteInfo (line 63) | type RouteInfo struct
type RoutesInfo (line 71) | type RoutesInfo
type Engine (line 75) | type Engine struct
method Handler (line 205) | func (engine *Engine) Handler() http.Handler {
method allocateContext (line 209) | func (engine *Engine) allocateContext(maxParams uint16) *Context {
method Delims (line 216) | func (engine *Engine) Delims(left, right string) *Engine {
method SecureJsonPrefix (line 222) | func (engine *Engine) SecureJsonPrefix(prefix string) *Engine {
method LoadHTMLGlob (line 229) | func (engine *Engine) LoadHTMLGlob(pattern string) {
method LoadHTMLFiles (line 245) | func (engine *Engine) LoadHTMLFiles(files ...string) {
method SetHTMLTemplate (line 256) | func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
method SetFuncMap (line 265) | func (engine *Engine) SetFuncMap(funcMap template.FuncMap) {
method NoRoute (line 270) | func (engine *Engine) NoRoute(handlers ...HandlerFunc) {
method NoMethod (line 276) | func (engine *Engine) NoMethod(handlers ...HandlerFunc) {
method Use (line 284) | func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
method With (line 292) | func (engine *Engine) With(opts ...OptionFunc) *Engine {
method rebuild404Handlers (line 300) | func (engine *Engine) rebuild404Handlers() {
method rebuild405Handlers (line 304) | func (engine *Engine) rebuild405Handlers() {
method addRoute (line 308) | func (engine *Engine) addRoute(method, path string, handlers HandlersC...
method Routes (line 334) | func (engine *Engine) Routes() (routes RoutesInfo) {
method Run (line 361) | func (engine *Engine) Run(addr ...string) (err error) {
method prepareTrustedCIDRs (line 375) | func (engine *Engine) prepareTrustedCIDRs() ([]*net.IPNet, error) {
method SetTrustedProxies (line 412) | func (engine *Engine) SetTrustedProxies(trustedProxies []string) error {
method isUnsafeTrustedProxies (line 418) | func (engine *Engine) isUnsafeTrustedProxies() bool {
method parseTrustedProxies (line 423) | func (engine *Engine) parseTrustedProxies() error {
method isTrustedProxy (line 430) | func (engine *Engine) isTrustedProxy(ip net.IP) bool {
method validateHeader (line 443) | func (engine *Engine) validateHeader(header string) (clientIP string, ...
method RunTLS (line 481) | func (engine *Engine) RunTLS(addr, certFile, keyFile string) (err erro...
method RunUnix (line 497) | func (engine *Engine) RunUnix(file string) (err error) {
method RunFd (line 520) | func (engine *Engine) RunFd(fd int) (err error) {
method RunListener (line 541) | func (engine *Engine) RunListener(listener net.Listener) (err error) {
method ServeHTTP (line 555) | func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Reque...
method HandleContext (line 569) | func (engine *Engine) HandleContext(c *Context) {
method handleHTTPRequest (line 577) | func (engine *Engine) handleHTTPRequest(c *Context) {
function New (line 165) | func New(opts ...OptionFunc) *Engine {
function Default (line 198) | func Default(opts ...OptionFunc) *Engine {
function iterate (line 341) | func iterate(path, method string, routes RoutesInfo, root *node) RoutesI...
function parseIP (line 466) | func parseIP(ip string) net.IP {
function serveError (line 647) | func serveError(c *Context, code int, defaultMessage []byte) {
function redirectTrailingSlash (line 664) | func redirectTrailingSlash(c *Context) {
function redirectFixedPath (line 680) | func redirectFixedPath(c *Context, root *node, trailingSlash bool) bool {
function redirectRequest (line 692) | func redirectRequest(c *Context) {
FILE: gossh/gin/ginS/gins.go
function engine (line 18) | func engine() *gin.Engine {
function LoadHTMLGlob (line 26) | func LoadHTMLGlob(pattern string) {
function LoadHTMLFiles (line 31) | func LoadHTMLFiles(files ...string) {
function SetHTMLTemplate (line 36) | func SetHTMLTemplate(templ *template.Template) {
function NoRoute (line 41) | func NoRoute(handlers ...gin.HandlerFunc) {
function NoMethod (line 46) | func NoMethod(handlers ...gin.HandlerFunc) {
function Group (line 52) | func Group(relativePath string, handlers ...gin.HandlerFunc) *gin.Router...
function Handle (line 57) | func Handle(httpMethod, relativePath string, handlers ...gin.HandlerFunc...
function POST (line 62) | func POST(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
function GET (line 67) | func GET(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
function DELETE (line 72) | func DELETE(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
function PATCH (line 77) | func PATCH(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
function PUT (line 82) | func PUT(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
function OPTIONS (line 87) | func OPTIONS(relativePath string, handlers ...gin.HandlerFunc) gin.IRout...
function HEAD (line 92) | func HEAD(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
function Any (line 97) | func Any(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
function StaticFile (line 102) | func StaticFile(relativePath, filepath string) gin.IRoutes {
function Static (line 113) | func Static(relativePath, root string) gin.IRoutes {
function StaticFS (line 118) | func StaticFS(relativePath string, fs http.FileSystem) gin.IRoutes {
function Use (line 125) | func Use(middlewares ...gin.HandlerFunc) gin.IRoutes {
function Routes (line 130) | func Routes() gin.RoutesInfo {
function Run (line 137) | func Run(addr ...string) (err error) {
function RunTLS (line 144) | func RunTLS(addr, certFile, keyFile string) (err error) {
function RunUnix (line 151) | func RunUnix(file string) (err error) {
function RunFd (line 158) | func RunFd(fd int) (err error) {
FILE: gossh/gin/internal/bytesconv/bytesconv.go
function StringToBytes (line 13) | func StringToBytes(s string) []byte {
function BytesToString (line 19) | func BytesToString(b []byte) string {
FILE: gossh/gin/jwt/claims.go
type Claims (line 9) | type Claims interface
FILE: gossh/gin/jwt/cmd/jwt/main.go
function main (line 38) | func main() {
function start (line 62) | func start() error {
function loadData (line 77) | func loadData(p string) ([]byte, error) {
function printJSON (line 100) | func printJSON(j any) error {
function verifyToken (line 119) | func verifyToken() error {
function signToken (line 174) | func signToken() error {
function showToken (line 263) | func showToken() error {
function isEs (line 295) | func isEs() bool {
function isRs (line 299) | func isRs() bool {
function isEd (line 303) | func isEd() bool {
function isNone (line 307) | func isNone() bool {
function algHelp (line 311) | func algHelp() string {
type ArgList (line 330) | type ArgList
method String (line 332) | func (l ArgList) String() string {
method Set (line 337) | func (l ArgList) Set(arg string) error {
FILE: gossh/gin/jwt/ecdsa.go
type SigningMethodECDSA (line 18) | type SigningMethodECDSA struct
method Alg (line 52) | func (m *SigningMethodECDSA) Alg() string {
method Verify (line 58) | func (m *SigningMethodECDSA) Verify(signingString string, sig []byte, ...
method Sign (line 92) | func (m *SigningMethodECDSA) Sign(signingString string, key any) ([]by...
function init (line 32) | func init() {
FILE: gossh/gin/jwt/ecdsa_utils.go
function ParseECPrivateKeyFromPEM (line 16) | func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) {
function ParseECPublicKeyFromPEM (line 43) | func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) {
FILE: gossh/gin/jwt/ed25519.go
type SigningMethodEd25519 (line 16) | type SigningMethodEd25519 struct
method Alg (line 30) | func (m *SigningMethodEd25519) Alg() string {
method Verify (line 36) | func (m *SigningMethodEd25519) Verify(signingString string, sig []byte...
method Sign (line 58) | func (m *SigningMethodEd25519) Sign(signingString string, key any) ([]...
function init (line 23) | func init() {
FILE: gossh/gin/jwt/ed25519_utils.go
function ParseEdPrivateKeyFromPEM (line 17) | func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) {
function ParseEdPublicKeyFromPEM (line 42) | func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) {
FILE: gossh/gin/jwt/errors.go
type joinedError (line 30) | type joinedError struct
method Error (line 34) | func (je joinedError) Error() string {
function joinErrors (line 45) | func joinErrors(errs ...error) error {
FILE: gossh/gin/jwt/errors_go1_20.go
method Unwrap (line 12) | func (je joinedError) Unwrap() []error {
function newError (line 29) | func newError(message string, err error, more ...error) error {
FILE: gossh/gin/jwt/errors_go_other.go
method Is (line 13) | func (je joinedError) Is(err error) bool {
type wrappedErrors (line 28) | type wrappedErrors struct
method Error (line 34) | func (we wrappedErrors) Error() string {
function newError (line 52) | func newError(message string, err error, more ...error) error {
FILE: gossh/gin/jwt/hmac.go
type SigningMethodHMAC (line 11) | type SigningMethodHMAC struct
method Alg (line 44) | func (m *SigningMethodHMAC) Alg() string {
method Verify (line 58) | func (m *SigningMethodHMAC) Verify(signingString string, sig []byte, k...
method Sign (line 91) | func (m *SigningMethodHMAC) Sign(signingString string, key any) ([]byt...
function init (line 24) | func init() {
FILE: gossh/gin/jwt/map_claims.go
type MapClaims (line 10) | type MapClaims
method GetExpirationTime (line 13) | func (m MapClaims) GetExpirationTime() (*NumericDate, error) {
method GetNotBefore (line 18) | func (m MapClaims) GetNotBefore() (*NumericDate, error) {
method GetIssuedAt (line 23) | func (m MapClaims) GetIssuedAt() (*NumericDate, error) {
method GetAudience (line 28) | func (m MapClaims) GetAudience() (ClaimStrings, error) {
method GetIssuer (line 33) | func (m MapClaims) GetIssuer() (string, error) {
method GetSubject (line 38) | func (m MapClaims) GetSubject() (string, error) {
method parseNumericDate (line 45) | func (m MapClaims) parseNumericDate(key string) (*NumericDate, error) {
method parseClaimsString (line 69) | func (m MapClaims) parseClaimsString(key string) (ClaimStrings, error) {
method parseString (line 92) | func (m MapClaims) parseString(key string) (string, error) {
FILE: gossh/gin/jwt/none.go
constant UnsafeAllowNoneSignatureType (line 7) | UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing met...
type signingMethodNone (line 11) | type signingMethodNone struct
method Alg (line 23) | func (m *signingMethodNone) Alg() string {
method Verify (line 28) | func (m *signingMethodNone) Verify(signingString string, sig []byte, k...
method Sign (line 44) | func (m *signingMethodNone) Sign(signingString string, key any) ([]byt...
type unsafeNoneMagicConstant (line 12) | type unsafeNoneMagicConstant
function init (line 14) | func init() {
FILE: gossh/gin/jwt/parser.go
type Parser (line 11) | type Parser struct
method Parse (line 44) | func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, e...
method ParseWithClaims (line 55) | func (p *Parser) ParseWithClaims(tokenString string, claims Claims, ke...
method ParseUnverified (line 138) | func (p *Parser) ParseUnverified(tokenString string, claims Claims) (t...
method DecodeSegment (line 202) | func (p *Parser) DecodeSegment(seg string) ([]byte, error) {
function NewParser (line 29) | func NewParser(options ...ParserOption) *Parser {
function Parse (line 225) | func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption)...
function ParseWithClaims (line 236) | func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc,...
FILE: gossh/gin/jwt/parser_option.go
type ParserOption (line 9) | type ParserOption
function WithValidMethods (line 15) | func WithValidMethods(methods []string) ParserOption {
function WithJSONNumber (line 23) | func WithJSONNumber() ParserOption {
function WithoutClaimsValidation (line 31) | func WithoutClaimsValidation() ParserOption {
function WithLeeway (line 38) | func WithLeeway(leeway time.Duration) ParserOption {
function WithTimeFunc (line 47) | func WithTimeFunc(f func() time.Time) ParserOption {
function WithIssuedAt (line 55) | func WithIssuedAt() ParserOption {
function WithExpirationRequired (line 63) | func WithExpirationRequired() ParserOption {
function WithAudience (line 77) | func WithAudience(aud string) ParserOption {
function WithIssuer (line 91) | func WithIssuer(iss string) ParserOption {
function WithSubject (line 105) | func WithSubject(sub string) ParserOption {
function WithPaddingAllowed (line 115) | func WithPaddingAllowed() ParserOption {
function WithStrictDecoding (line 124) | func WithStrictDecoding() ParserOption {
FILE: gossh/gin/jwt/registered_claims.go
type RegisteredClaims (line 12) | type RegisteredClaims struct
method GetExpirationTime (line 36) | func (c RegisteredClaims) GetExpirationTime() (*NumericDate, error) {
method GetNotBefore (line 41) | func (c RegisteredClaims) GetNotBefore() (*NumericDate, error) {
method GetIssuedAt (line 46) | func (c RegisteredClaims) GetIssuedAt() (*NumericDate, error) {
method GetAudience (line 51) | func (c RegisteredClaims) GetAudience() (ClaimStrings, error) {
method GetIssuer (line 56) | func (c RegisteredClaims) GetIssuer() (string, error) {
method GetSubject (line 61) | func (c RegisteredClaims) GetSubject() (string, error) {
FILE: gossh/gin/jwt/request/extractor.go
type Extractor (line 17) | type Extractor interface
type HeaderExtractor (line 23) | type HeaderExtractor
method ExtractToken (line 25) | func (e HeaderExtractor) ExtractToken(req *http.Request) (string, erro...
type ArgumentExtractor (line 38) | type ArgumentExtractor
method ExtractToken (line 40) | func (e ArgumentExtractor) ExtractToken(req *http.Request) (string, er...
type MultiExtractor (line 55) | type MultiExtractor
method ExtractToken (line 57) | func (e MultiExtractor) ExtractToken(req *http.Request) (string, error) {
type PostExtractionFilter (line 71) | type PostExtractionFilter struct
method ExtractToken (line 76) | func (e *PostExtractionFilter) ExtractToken(req *http.Request) (string...
type BearerExtractor (line 87) | type BearerExtractor struct
method ExtractToken (line 89) | func (e BearerExtractor) ExtractToken(req *http.Request) (string, erro...
FILE: gossh/gin/jwt/request/oauth2.go
function stripBearerPrefixFromTokenString (line 8) | func stripBearerPrefixFromTokenString(tok string) (string, error) {
FILE: gossh/gin/jwt/request/request.go
function ParseFromRequest (line 15) | func ParseFromRequest(req *http.Request, extractor Extractor, keyFunc jw...
function ParseFromRequestWithClaims (line 45) | func ParseFromRequestWithClaims(req *http.Request, extractor Extractor, ...
type fromRequestParser (line 49) | type fromRequestParser struct
type ParseFromRequestOption (line 56) | type ParseFromRequestOption
function WithClaims (line 59) | func WithClaims(claims jwt.Claims) ParseFromRequestOption {
function WithParser (line 66) | func WithParser(parser *jwt.Parser) ParseFromRequestOption {
FILE: gossh/gin/jwt/rsa.go
type SigningMethodRSA (line 11) | type SigningMethodRSA struct
method Alg (line 43) | func (m *SigningMethodRSA) Alg() string {
method Verify (line 49) | func (m *SigningMethodRSA) Verify(signingString string, sig []byte, ke...
method Sign (line 70) | func (m *SigningMethodRSA) Sign(signingString string, key any) ([]byte...
function init (line 23) | func init() {
FILE: gossh/gin/jwt/rsa_pss.go
type SigningMethodRSAPSS (line 10) | type SigningMethodRSAPSS struct
method Verify (line 82) | func (m *SigningMethodRSAPSS) Verify(signingString string, sig []byte,...
method Sign (line 108) | func (m *SigningMethodRSAPSS) Sign(signingString string, key any) ([]b...
function init (line 27) | func init() {
FILE: gossh/gin/jwt/rsa_utils.go
function ParseRSAPrivateKeyFromPEM (line 17) | func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) {
function ParseRSAPrivateKeyFromPEMWithPassword (line 47) | func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) ...
function ParseRSAPublicKeyFromPEM (line 79) | func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) {
FILE: gossh/gin/jwt/signing_method.go
type SigningMethod (line 14) | type SigningMethod interface
function RegisterSigningMethod (line 22) | func RegisterSigningMethod(alg string, f func() SigningMethod) {
function GetSigningMethod (line 30) | func GetSigningMethod(alg string) (method SigningMethod) {
function GetAlgorithms (line 41) | func GetAlgorithms() (algs []string) {
FILE: gossh/gin/jwt/token.go
type Keyfunc (line 16) | type Keyfunc
type VerificationKey (line 19) | type VerificationKey interface
type VerificationKeySet (line 24) | type VerificationKeySet struct
type Token (line 30) | type Token struct
method SignedString (line 63) | func (t *Token) SignedString(key any) (string, error) {
method SigningString (line 80) | func (t *Token) SigningString() (string, error) {
method EncodeSegment (line 98) | func (*Token) EncodeSegment(seg []byte) string {
function New (line 41) | func New(method SigningMethod, opts ...TokenOption) *Token {
function NewWithClaims (line 47) | func NewWithClaims(method SigningMethod, claims Claims, opts ...TokenOpt...
FILE: gossh/gin/jwt/token_option.go
type TokenOption (line 5) | type TokenOption
FILE: gossh/gin/jwt/types.go
type NumericDate (line 32) | type NumericDate struct
method MarshalJSON (line 51) | func (date NumericDate) MarshalJSON() (b []byte, err error) {
method UnmarshalJSON (line 80) | func (date *NumericDate) UnmarshalJSON(b []byte) (err error) {
function NewNumericDate (line 38) | func NewNumericDate(t time.Time) *NumericDate {
function newNumericDateFromSeconds (line 44) | func newNumericDateFromSeconds(f float64) *NumericDate {
type ClaimStrings (line 103) | type ClaimStrings
method UnmarshalJSON (line 105) | func (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) {
method MarshalJSON (line 138) | func (s ClaimStrings) MarshalJSON() (b []byte, err error) {
FILE: gossh/gin/jwt/validator.go
type ClaimsValidator (line 26) | type ClaimsValidator interface
type Validator (line 36) | type Validator struct
method Validate (line 88) | func (v *Validator) Validate(claims Claims) error {
method verifyExpiresAt (line 167) | func (v *Validator) verifyExpiresAt(claims Claims, cmp time.Time, requ...
method verifyIssuedAt (line 188) | func (v *Validator) verifyIssuedAt(claims Claims, cmp time.Time, requi...
method verifyNotBefore (line 209) | func (v *Validator) verifyNotBefore(claims Claims, cmp time.Time, requ...
method verifyAudience (line 229) | func (v *Validator) verifyAudience(claims Claims, cmp string, required...
method verifyIssuer (line 265) | func (v *Validator) verifyIssuer(claims Claims, cmp string, required b...
method verifySubject (line 285) | func (v *Validator) verifySubject(claims Claims, cmp string, required ...
function NewValidator (line 77) | func NewValidator(opts ...ParserOption) *Validator {
function errorIfFalse (line 300) | func errorIfFalse(value bool, err error) error {
function errorIfRequired (line 310) | func errorIfRequired(required bool, claim string) error {
FILE: gossh/gin/logger.go
type consoleColorModeValue (line 15) | type consoleColorModeValue
constant autoColor (line 18) | autoColor consoleColorModeValue = iota
constant disableColor (line 19) | disableColor
constant forceColor (line 20) | forceColor
constant green (line 24) | green = "\033[97;42m"
constant white (line 25) | white = "\033[90;47m"
constant yellow (line 26) | yellow = "\033[90;43m"
constant red (line 27) | red = "\033[97;41m"
constant blue (line 28) | blue = "\033[97;44m"
constant magenta (line 29) | magenta = "\033[97;45m"
constant cyan (line 30) | cyan = "\033[97;46m"
constant reset (line 31) | reset = "\033[0m"
type LoggerConfig (line 37) | type LoggerConfig struct
type Skipper (line 55) | type Skipper
type LogFormatter (line 58) | type LogFormatter
type LogFormatterParams (line 61) | type LogFormatterParams struct
method StatusCodeColor (line 87) | func (p *LogFormatterParams) StatusCodeColor() string {
method MethodColor (line 105) | func (p *LogFormatterParams) MethodColor() string {
method ResetColor (line 129) | func (p *LogFormatterParams) ResetColor() string {
method IsOutputColor (line 134) | func (p *LogFormatterParams) IsOutputColor() bool {
function DisableConsoleColor (line 162) | func DisableConsoleColor() {
function ForceConsoleColor (line 167) | func ForceConsoleColor() {
function ErrorLogger (line 172) | func ErrorLogger() HandlerFunc {
function ErrorLoggerT (line 177) | func ErrorLoggerT(typ ErrorType) HandlerFunc {
function Logger (line 189) | func Logger() HandlerFunc {
function LoggerWithFormatter (line 194) | func LoggerWithFormatter(f LogFormatter) HandlerFunc {
function LoggerWithWriter (line 202) | func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc {
function LoggerWithConfig (line 210) | func LoggerWithConfig(conf LoggerConfig) HandlerFunc {
FILE: gossh/gin/mode.go
constant EnvGinMode (line 16) | EnvGinMode = "GIN_MODE"
constant DebugMode (line 20) | DebugMode = "debug"
constant ReleaseMode (line 22) | ReleaseMode = "release"
constant TestMode (line 24) | TestMode = "test"
constant debugCode (line 28) | debugCode = iota
constant releaseCode (line 29) | releaseCode
constant testCode (line 30) | testCode
function init (line 51) | func init() {
function SetMode (line 57) | func SetMode(value string) {
function DisableBindValidation (line 81) | func DisableBindValidation() {
function EnableJsonDecoderUseNumber (line 87) | func EnableJsonDecoderUseNumber() {
function EnableJsonDecoderDisallowUnknownFields (line 93) | func EnableJsonDecoderDisallowUnknownFields() {
function Mode (line 98) | func Mode() string {
FILE: gossh/gin/path.go
function cleanPath (line 21) | func cleanPath(p string) string {
function bufApp (line 127) | func bufApp(buf *[]byte, s string, w int, c byte) {
FILE: gossh/gin/recovery.go
type RecoveryFunc (line 30) | type RecoveryFunc
function Recovery (line 33) | func Recovery() HandlerFunc {
function CustomRecovery (line 38) | func CustomRecovery(handle RecoveryFunc) HandlerFunc {
function RecoveryWithWriter (line 43) | func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) Handler...
function CustomRecoveryWithWriter (line 51) | func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) Handle...
function defaultHandleRecovery (line 106) | func defaultHandleRecovery(c *Context, _ any) {
function stack (line 111) | func stack(skip int) []byte {
function source (line 138) | func source(lines [][]byte, n int) []byte {
function function (line 147) | func function(pc uintptr) []byte {
function timeFormat (line 172) | func timeFormat(t time.Time) string {
FILE: gossh/gin/render/data.go
type Data (line 10) | type Data struct
method Render (line 16) | func (r Data) Render(w http.ResponseWriter) (err error) {
method WriteContentType (line 23) | func (r Data) WriteContentType(w http.ResponseWriter) {
FILE: gossh/gin/render/html.go
type Delims (line 13) | type Delims struct
type HTMLRender (line 21) | type HTMLRender interface
type HTMLProduction (line 27) | type HTMLProduction struct
method Instance (line 50) | func (r HTMLProduction) Instance(name string, data any) Render {
type HTMLDebug (line 33) | type HTMLDebug struct
method Instance (line 59) | func (r HTMLDebug) Instance(name string, data any) Render {
method loadTemplate (line 66) | func (r HTMLDebug) loadTemplate() *template.Template {
type HTML (line 41) | type HTML struct
method Render (line 80) | func (r HTML) Render(w http.ResponseWriter) error {
method WriteContentType (line 90) | func (r HTML) WriteContentType(w http.ResponseWriter) {
FILE: gossh/gin/render/json.go
type JSON (line 18) | type JSON struct
method Render (line 56) | func (r JSON) Render(w http.ResponseWriter) error {
method WriteContentType (line 61) | func (r JSON) WriteContentType(w http.ResponseWriter) {
type IndentedJSON (line 23) | type IndentedJSON struct
method Render (line 77) | func (r IndentedJSON) Render(w http.ResponseWriter) error {
method WriteContentType (line 88) | func (r IndentedJSON) WriteContentType(w http.ResponseWriter) {
type SecureJSON (line 28) | type SecureJSON struct
method Render (line 93) | func (r SecureJSON) Render(w http.ResponseWriter) error {
method WriteContentType (line 111) | func (r SecureJSON) WriteContentType(w http.ResponseWriter) {
type JsonpJSON (line 34) | type JsonpJSON struct
method Render (line 116) | func (r JsonpJSON) Render(w http.ResponseWriter) (err error) {
method WriteContentType (line 149) | func (r JsonpJSON) WriteContentType(w http.ResponseWriter) {
type AsciiJSON (line 40) | type AsciiJSON struct
method Render (line 154) | func (r AsciiJSON) Render(w http.ResponseWriter) (err error) {
method WriteContentType (line 175) | func (r AsciiJSON) WriteContentType(w http.ResponseWriter) {
type PureJSON (line 45) | type PureJSON struct
method Render (line 180) | func (r PureJSON) Render(w http.ResponseWriter) error {
method WriteContentType (line 188) | func (r PureJSON) WriteContentType(w http.ResponseWriter) {
function WriteJSON (line 66) | func WriteJSON(w http.ResponseWriter, obj any) error {
FILE: gossh/gin/render/reader.go
type Reader (line 14) | type Reader struct
method Render (line 22) | func (r Reader) Render(w http.ResponseWriter) (err error) {
method WriteContentType (line 36) | func (r Reader) WriteContentType(w http.ResponseWriter) {
method writeHeaders (line 41) | func (r Reader) writeHeaders(w http.ResponseWriter, headers map[string...
FILE: gossh/gin/render/redirect.go
type Redirect (line 13) | type Redirect struct
method Render (line 20) | func (r Redirect) Render(w http.ResponseWriter) error {
method WriteContentType (line 29) | func (r Redirect) WriteContentType(http.ResponseWriter) {}
FILE: gossh/gin/render/render.go
type Render (line 10) | type Render interface
function writeContentType (line 33) | func writeContentType(w http.ResponseWriter, value []string) {
FILE: gossh/gin/render/text.go
type String (line 15) | type String struct
method Render (line 23) | func (r String) Render(w http.ResponseWriter) error {
method WriteContentType (line 28) | func (r String) WriteContentType(w http.ResponseWriter) {
function WriteString (line 33) | func WriteString(w http.ResponseWriter, format string, data []any) (err ...
FILE: gossh/gin/render/xml.go
type XML (line 13) | type XML struct
method Render (line 20) | func (r XML) Render(w http.ResponseWriter) error {
method WriteContentType (line 26) | func (r XML) WriteContentType(w http.ResponseWriter) {
FILE: gossh/gin/response_writer.go
constant noWritten (line 15) | noWritten = -1
constant defaultStatus (line 16) | defaultStatus = http.StatusOK
type ResponseWriter (line 20) | type ResponseWriter interface
type responseWriter (line 46) | type responseWriter struct
method Unwrap (line 54) | func (w *responseWriter) Unwrap() http.ResponseWriter {
method reset (line 58) | func (w *responseWriter) reset(writer http.ResponseWriter) {
method WriteHeader (line 64) | func (w *responseWriter) WriteHeader(code int) {
method WriteHeaderNow (line 74) | func (w *responseWriter) WriteHeaderNow() {
method Write (line 81) | func (w *responseWriter) Write(data []byte) (n int, err error) {
method WriteString (line 88) | func (w *responseWriter) WriteString(s string) (n int, err error) {
method Status (line 95) | func (w *responseWriter) Status() int {
method Size (line 99) | func (w *responseWriter) Size() int {
method Written (line 103) | func (w *responseWriter) Written() bool {
method Hijack (line 108) | func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
method CloseNotify (line 116) | func (w *responseWriter) CloseNotify() <-chan bool {
method Flush (line 121) | func (w *responseWriter) Flush() {
method Pusher (line 126) | func (w *responseWriter) Pusher() (pusher http.Pusher) {
FILE: gossh/gin/routergroup.go
type IRouter (line 27) | type IRouter interface
type IRoutes (line 33) | type IRoutes interface
type RouterGroup (line 55) | type RouterGroup struct
method Use (line 65) | func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
method Group (line 72) | func (group *RouterGroup) Group(relativePath string, handlers ...Handl...
method BasePath (line 82) | func (group *RouterGroup) BasePath() string {
method handle (line 86) | func (group *RouterGroup) handle(httpMethod, relativePath string, hand...
method Handle (line 103) | func (group *RouterGroup) Handle(httpMethod, relativePath string, hand...
method POST (line 111) | func (group *RouterGroup) POST(relativePath string, handlers ...Handle...
method GET (line 116) | func (group *RouterGroup) GET(relativePath string, handlers ...Handler...
method DELETE (line 121) | func (group *RouterGroup) DELETE(relativePath string, handlers ...Hand...
method PATCH (line 126) | func (group *RouterGroup) PATCH(relativePath string, handlers ...Handl...
method PUT (line 131) | func (group *RouterGroup) PUT(relativePath string, handlers ...Handler...
method OPTIONS (line 136) | func (group *RouterGroup) OPTIONS(relativePath string, handlers ...Han...
method HEAD (line 141) | func (group *RouterGroup) HEAD(relativePath string, handlers ...Handle...
method Any (line 147) | func (group *RouterGroup) Any(relativePath string, handlers ...Handler...
method Match (line 156) | func (group *RouterGroup) Match(methods []string, relativePath string,...
method StaticFile (line 166) | func (group *RouterGroup) StaticFile(relativePath, filepath string) IR...
method StaticFileFS (line 175) | func (group *RouterGroup) StaticFileFS(relativePath, filepath string, ...
method staticFileHandler (line 181) | func (group *RouterGroup) staticFileHandler(relativePath string, handl...
method Static (line 197) | func (group *RouterGroup) Static(relativePath, root string) IRoutes {
method StaticFS (line 203) | func (group *RouterGroup) StaticFS(relativePath string, fs http.FileSy...
method createStaticHandler (line 216) | func (group *RouterGroup) createStaticHandler(relativePath string, fs ...
method combineHandlers (line 241) | func (group *RouterGroup) combineHandlers(handlers HandlersChain) Hand...
method calculateAbsolutePath (line 250) | func (group *RouterGroup) calculateAbsolutePath(relativePath string) s...
method returnObj (line 254) | func (group *RouterGroup) returnObj() IRoutes {
FILE: gossh/gin/sessions/context/context.go
function Set (line 16) | func Set(r *http.Request, key, val any) {
function Get (line 27) | func Get(r *http.Request, key any) any {
function GetOk (line 39) | func GetOk(r *http.Request, key any) (any, bool) {
function GetAll (line 51) | func GetAll(r *http.Request) map[any]any {
function GetAllOk (line 67) | func GetAllOk(r *http.Request) (map[any]any, bool) {
function Delete (line 79) | func Delete(r *http.Request, key any) {
function Clear (line 91) | func Clear(r *http.Request) {
function clear (line 98) | func clear(r *http.Request) {
function Purge (line 112) | func Purge(maxAge int) int {
function ClearHandler (line 134) | func ClearHandler(h http.Handler) http.Handler {
FILE: gossh/gin/sessions/cookie/cookie.go
type Store (line 8) | type Store interface
function NewStore (line 21) | func NewStore(keyPairs ...[]byte) Store {
type store (line 25) | type store struct
method Options (line 29) | func (c *store) Options(options sessions.Options) {
FILE: gossh/gin/sessions/memstore/cache.go
type cache (line 7) | type cache struct
method value (line 18) | func (c *cache) value(name string) (valueType, bool) {
method setValue (line 26) | func (c *cache) setValue(name string, value valueType) {
method delete (line 33) | func (c *cache) delete(name string) {
function newCache (line 12) | func newCache() *cache {
FILE: gossh/gin/sessions/memstore/memstore.go
type MemStore (line 19) | type MemStore struct
method Get (line 62) | func (m *MemStore) Get(r *http.Request, name string) (*sessions.Sessio...
method New (line 71) | func (m *MemStore) New(r *http.Request, name string) (*sessions.Sessio...
method Save (line 104) | func (m *MemStore) Save(r *http.Request, w http.ResponseWriter, s *ses...
method MaxAge (line 130) | func (m *MemStore) MaxAge(age int) {
method copy (line 141) | func (m *MemStore) copy(v valueType) valueType {
type valueType (line 25) | type valueType
function NewMemStore (line 42) | func NewMemStore(keyPairs ...[]byte) *MemStore {
FILE: gossh/gin/sessions/memstore/store.go
type Store (line 7) | type Store interface
function NewStore (line 20) | func NewStore(keyPairs ...[]byte) Store {
type store (line 24) | type store struct
method Options (line 28) | func (c *store) Options(options sessions.Options) {
FILE: gossh/gin/sessions/securecookie/securecookie.go
type Error (line 27) | type Error interface
type errorType (line 58) | type errorType
constant usageError (line 61) | usageError = errorType(1 << iota)
constant decodeError (line 62) | decodeError
constant internalError (line 63) | internalError
type cookieError (line 66) | type cookieError struct
method IsUsage (line 72) | func (e cookieError) IsUsage() bool { return (e.typ & usageError) !...
method IsDecode (line 73) | func (e cookieError) IsDecode() bool { return (e.typ & decodeError) ...
method IsInternal (line 74) | func (e cookieError) IsInternal() bool { return (e.typ & internalError...
method Cause (line 76) | func (e cookieError) Cause() error { return e.cause }
method Error (line 78) | func (e cookieError) Error() string {
type Codec (line 116) | type Codec interface
function New (line 135) | func New(hashKey, blockKey []byte) *SecureCookie {
type SecureCookie (line 155) | type SecureCookie struct
method MaxLength (line 194) | func (s *SecureCookie) MaxLength(value int) *SecureCookie {
method MaxAge (line 202) | func (s *SecureCookie) MaxAge(value int) *SecureCookie {
method MinAge (line 210) | func (s *SecureCookie) MinAge(value int) *SecureCookie {
method HashFunc (line 218) | func (s *SecureCookie) HashFunc(f func() hash.Hash) *SecureCookie {
method BlockFunc (line 226) | func (s *SecureCookie) BlockFunc(f func([]byte) (cipher.Block, error))...
method SetSerializer (line 241) | func (s *SecureCookie) SetSerializer(sz Serializer) *SecureCookie {
method Encode (line 259) | func (s *SecureCookie) Encode(name string, value any) (string, error) {
method Decode (line 303) | func (s *SecureCookie) Decode(name, value string, dst any) error {
method timestamp (line 364) | func (s *SecureCookie) timestamp() int64 {
type Serializer (line 172) | type Serializer interface
type GobEncoder (line 179) | type GobEncoder struct
method Serialize (line 430) | func (e GobEncoder) Serialize(src any) ([]byte, error) {
method Deserialize (line 440) | func (e GobEncoder) Deserialize(src []byte, dst any) error {
type JSONEncoder (line 184) | type JSONEncoder struct
method Serialize (line 449) | func (e JSONEncoder) Serialize(src any) ([]byte, error) {
method Deserialize (line 459) | func (e JSONEncoder) Deserialize(src []byte, dst any) error {
type NopEncoder (line 189) | type NopEncoder struct
method Serialize (line 468) | func (e NopEncoder) Serialize(src any) ([]byte, error) {
method Deserialize (line 477) | func (e NopEncoder) Deserialize(src []byte, dst any) error {
function createMac (line 374) | func createMac(h hash.Hash, value []byte) []byte {
function verifyMac (line 380) | func verifyMac(h hash.Hash, value []byte, mac []byte) error {
function encrypt (line 396) | func encrypt(block cipher.Block, value []byte) ([]byte, error) {
function decrypt (line 412) | func decrypt(block cipher.Block, value []byte) ([]byte, error) {
function encode (line 488) | func encode(value []byte) []byte {
function decode (line 495) | func decode(value []byte) ([]byte, error) {
function GenerateRandomKey (line 515) | func GenerateRandomKey(length int) []byte {
function CodecsFromPairs (line 547) | func CodecsFromPairs(keyPairs ...[]byte) []Codec {
function EncodeMulti (line 565) | func EncodeMulti(name string, value any, codecs ...Codec) (string, error) {
function DecodeMulti (line 587) | func DecodeMulti(name string, value string, dst any, codecs ...Codec) er...
type MultiError (line 604) | type MultiError
method IsUsage (line 606) | func (m MultiError) IsUsage() bool { return m.any(func(e Error) boo...
method IsDecode (line 607) | func (m MultiError) IsDecode() bool { return m.any(func(e Error) boo...
method IsInternal (line 608) | func (m MultiError) IsInternal() bool { return m.any(func(e Error) boo...
method Cause (line 618) | func (m MultiError) Cause() error { return nil }
method Error (line 620) | func (m MultiError) Error() string {
method any (line 642) | func (m MultiError) any(pred func(Error) bool) bool {
FILE: gossh/gin/sessions/session_options_go1.10.go
type Options (line 12) | type Options struct
method ToGorillaOptions (line 23) | func (options Options) ToGorillaOptions() *gsessions.Options {
FILE: gossh/gin/sessions/session_options_go1.11.go
type Options (line 14) | type Options struct
method ToGorillaOptions (line 29) | func (options Options) ToGorillaOptions() *gsessions.Options {
FILE: gossh/gin/sessions/sessions.go
constant DefaultKey (line 13) | DefaultKey = "gin-sessions"
constant errorFormat (line 14) | errorFormat = "[sessions] ERROR! %s\n"
type Store (line 17) | type Store interface
type Session (line 24) | type Session interface
function Sessions (line 49) | func Sessions(name string, store Store) gin.HandlerFunc {
function SessionsMany (line 58) | func SessionsMany(names []string, store Store) gin.HandlerFunc {
type session (line 70) | type session struct
method ID (line 79) | func (s *session) ID() string {
method Get (line 83) | func (s *session) Get(key any) any {
method Set (line 87) | func (s *session) Set(key any, val any) {
method Delete (line 92) | func (s *session) Delete(key any) {
method Clear (line 97) | func (s *session) Clear() {
method AddFlash (line 103) | func (s *session) AddFlash(value any, vars ...string) {
method Flashes (line 108) | func (s *session) Flashes(vars ...string) []any {
method Options (line 113) | func (s *session) Options(options Options) {
method Save (line 118) | func (s *session) Save() error {
method Session (line 129) | func (s *session) Session() *sessions.Session {
method Written (line 140) | func (s *session) Written() bool {
function Default (line 145) | func Default(c *gin.Context) Session {
function DefaultMany (line 150) | func DefaultMany(c *gin.Context, name string) Session {
FILE: gossh/gin/sessions/sessions/cookie.go
function newCookieFromOptions (line 9) | func newCookieFromOptions(name, value string, options *Options) *http.Co...
FILE: gossh/gin/sessions/sessions/cookie_go111.go
function newCookieFromOptions (line 9) | func newCookieFromOptions(name, value string, options *Options) *http.Co...
FILE: gossh/gin/sessions/sessions/lex.go
function isToken (line 88) | func isToken(r rune) bool {
function isNotToken (line 93) | func isNotToken(r rune) bool {
function isCookieNameValid (line 97) | func isCookieNameValid(raw string) bool {
FILE: gossh/gin/sessions/sessions/options.go
type Options (line 9) | type Options struct
FILE: gossh/gin/sessions/sessions/options_go111.go
type Options (line 11) | type Options struct
FILE: gossh/gin/sessions/sessions/sessions.go
constant flashesKey (line 16) | flashesKey = "_flash"
function NewSession (line 21) | func NewSession(store Store, name string) *Session {
type Session (line 31) | type Session struct
method Flashes (line 47) | func (s *Session) Flashes(vars ...string) []any {
method AddFlash (line 65) | func (s *Session) AddFlash(value any, vars ...string) {
method Save (line 80) | func (s *Session) Save(r *http.Request, w http.ResponseWriter) error {
method Name (line 85) | func (s *Session) Name() string {
method Store (line 90) | func (s *Session) Store() Store {
type sessionInfo (line 97) | type sessionInfo struct
type contextKey (line 103) | type contextKey
constant registryKey (line 106) | registryKey contextKey = 0
function GetRegistry (line 109) | func GetRegistry(r *http.Request) *Registry {
type Registry (line 124) | type Registry struct
method Get (line 132) | func (s *Registry) Get(store Store, name string) (session *Session, er...
method Save (line 148) | func (s *Registry) Save(w http.ResponseWriter) error {
function init (line 168) | func init() {
function Save (line 173) | func Save(r *http.Request, w http.ResponseWriter) error {
function NewCookie (line 180) | func NewCookie(name, value string, options *Options) *http.Cookie {
type MultiError (line 197) | type MultiError
method Error (line 199) | func (m MultiError) Error() string {
FILE: gossh/gin/sessions/sessions/store.go
type Store (line 20) | type Store interface
function NewCookieStore (line 48) | func NewCookieStore(keyPairs ...[]byte) *CookieStore {
type CookieStore (line 62) | type CookieStore struct
method Get (line 74) | func (s *CookieStore) Get(r *http.Request, name string) (*Session, err...
method New (line 83) | func (s *CookieStore) New(r *http.Request, name string) (*Session, err...
method Save (line 100) | func (s *CookieStore) Save(r *http.Request, w http.ResponseWriter,
method MaxAge (line 114) | func (s *CookieStore) MaxAge(age int) {
function NewFilesystemStore (line 135) | func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore {
type FilesystemStore (line 157) | type FilesystemStore struct
method MaxLength (line 166) | func (s *FilesystemStore) MaxLength(l int) {
method Get (line 177) | func (s *FilesystemStore) Get(r *http.Request, name string) (*Session,...
method New (line 184) | func (s *FilesystemStore) New(r *http.Request, name string) (*Session,...
method Save (line 210) | func (s *FilesystemStore) Save(r *http.Request, w http.ResponseWriter,
method MaxAge (line 242) | func (s *FilesystemStore) MaxAge(age int) {
method save (line 254) | func (s *FilesystemStore) save(session *Session) error {
method load (line 267) | func (s *FilesystemStore) load(session *Session) error {
method erase (line 283) | func (s *FilesystemStore) erase(session *Session) error {
FILE: gossh/gin/sse/sse-decoder.go
type decoder (line 12) | type decoder struct
method dispatchEvent (line 21) | func (d *decoder) dispatchEvent(event Event, data string) {
method decode (line 38) | func (d *decoder) decode(r io.Reader) ([]Event, error) {
function Decode (line 16) | func Decode(r io.Reader) ([]Event, error) {
FILE: gossh/gin/sse/sse-encoder.go
constant ContentType (line 21) | ContentType = "text/event-stream"
type Event (line 34) | type Event struct
method Render (line 89) | func (r Event) Render(w http.ResponseWriter) error {
method WriteContentType (line 94) | func (r Event) WriteContentType(w http.ResponseWriter) {
function Encode (line 41) | func Encode(writer io.Writer, event Event) error {
function writeId (line 49) | func writeId(w stringWriter, id string) {
function writeEvent (line 57) | func writeEvent(w stringWriter, event string) {
function writeRetry (line 65) | func writeRetry(w stringWriter, retry uint) {
function writeData (line 73) | func writeData(w stringWriter, data any) error {
function kindOfData (line 103) | func kindOfData(data any) reflect.Kind {
FILE: gossh/gin/sse/writer.go
type stringWriter (line 5) | type stringWriter interface
type stringWrapper (line 10) | type stringWrapper struct
method WriteString (line 14) | func (w stringWrapper) WriteString(str string) (int, error) {
function checkWriter (line 18) | func checkWriter(writer io.Writer) stringWriter {
FILE: gossh/gin/tree.go
type Param (line 24) | type Param struct
type Params (line 32) | type Params
method Get (line 36) | func (ps Params) Get(name string) (string, bool) {
method ByName (line 47) | func (ps Params) ByName(name string) (va string) {
type methodTree (line 52) | type methodTree struct
type methodTrees (line 57) | type methodTrees
method get (line 59) | func (trees methodTrees) get(method string) *node {
function min (line 68) | func min(a, b int) int {
function longestCommonPrefix (line 75) | func longestCommonPrefix(a, b string) int {
function countParams (line 94) | func countParams(path string) uint16 {
function countSections (line 102) | func countSections(path string) uint16 {
type nodeType (line 107) | type nodeType
constant static (line 110) | static nodeType = iota
constant root (line 111) | root
constant param (line 112) | param
constant catchAll (line 113) | catchAll
type node (line 116) | type node struct
method addChild (line 85) | func (n *node) addChild(child *node) {
method incrementChildPrio (line 128) | func (n *node) incrementChildPrio(pos int) int {
method addRoute (line 152) | func (n *node) addRoute(path string, handlers HandlersChain) {
method insertChild (line 293) | func (n *node) insertChild(path string, fullPath string, handlers Hand...
method getValue (line 423) | func (n *node) getValue(path string, params *Params, skippedNodes *[]s...
method findCaseInsensitivePath (line 676) | func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash b...
method findCaseInsensitivePathRec (line 713) | func (n *node) findCaseInsensitivePathRec(path string, ciPath []byte, ...
function findWildcard (line 270) | func findWildcard(path string) (wildcard string, i int, valid bool) {
type nodeValue (line 405) | type nodeValue struct
type skippedNode (line 412) | type skippedNode struct
function shiftNRuneBytes (line 697) | func shiftNRuneBytes(rb [4]byte, n int) [4]byte {
FILE: gossh/gin/utils.go
constant BindKey (line 19) | BindKey = "_gin-gonic/gin/bindkey"
function Bind (line 22) | func Bind(val any) HandlerFunc {
function WrapF (line 40) | func WrapF(f http.HandlerFunc) HandlerFunc {
function WrapH (line 47) | func WrapH(h http.Handler) HandlerFunc {
type H (line 54) | type H
method MarshalXML (line 57) | func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
function assert1 (line 78) | func assert1(guard bool, text string) {
function filterFlags (line 84) | func filterFlags(content string) string {
function chooseData (line 93) | func chooseData(custom, wildcard any) any {
function parseAccept (line 103) | func parseAccept(acceptHeader string) []string {
function lastChar (line 117) | func lastChar(str string) uint8 {
function nameOfFunction (line 124) | func nameOfFunction(f any) string {
function joinPaths (line 128) | func joinPaths(absolutePath, relativePath string) string {
function resolveAddress (line 140) | func resolveAddress(addr []string) string {
function isASCII (line 157) | func isASCII(s string) bool {
FILE: gossh/gin/validator/baked_in.go
type Func (line 24) | type Func
type FuncCtx (line 28) | type FuncCtx
function wrapFunc (line 31) | func wrapFunc(fn Func) FuncCtx {
function parseOneOfParam2 (line 233) | func parseOneOfParam2(s string) []string {
function isURLEncoded (line 249) | func isURLEncoded(fl FieldLevel) bool {
function isHTMLEncoded (line 253) | func isHTMLEncoded(fl FieldLevel) bool {
function isHTML (line 257) | func isHTML(fl FieldLevel) bool {
function isOneOf (line 261) | func isOneOf(fl FieldLevel) bool {
function isUnique (line 286) | func isUnique(fl FieldLevel) bool {
function isMAC (line 359) | func isMAC(fl FieldLevel) bool {
function isCIDRv4 (line 366) | func isCIDRv4(fl FieldLevel) bool {
function isCIDRv6 (line 373) | func isCIDRv6(fl FieldLevel) bool {
function isCIDR (line 380) | func isCIDR(fl FieldLevel) bool {
function isIPv4 (line 387) | func isIPv4(fl FieldLevel) bool {
function isIPv6 (line 394) | func isIPv6(fl FieldLevel) bool {
function isIP (line 401) | func isIP(fl FieldLevel) bool {
function isSSN (line 408) | func isSSN(fl FieldLevel) bool {
function isLongitude (line 419) | func isLongitude(fl FieldLevel) bool {
function isLatitude (line 442) | func isLatitude(fl FieldLevel) bool {
function isDataURI (line 465) | func isDataURI(fl FieldLevel) bool {
function hasMultiByteCharacter (line 480) | func hasMultiByteCharacter(fl FieldLevel) bool {
function isPrintableASCII (line 491) | func isPrintableASCII(fl FieldLevel) bool {
function isASCII (line 496) | func isASCII(fl FieldLevel) bool {
function isUUID5 (line 501) | func isUUID5(fl FieldLevel) bool {
function isUUID4 (line 506) | func isUUID4(fl FieldLevel) bool {
function isUUID3 (line 511) | func isUUID3(fl FieldLevel) bool {
function isUUID (line 516) | func isUUID(fl FieldLevel) bool {
function isUUID5RFC4122 (line 521) | func isUUID5RFC4122(fl FieldLevel) bool {
function isUUID4RFC4122 (line 526) | func isUUID4RFC4122(fl FieldLevel) bool {
function isUUID3RFC4122 (line 531) | func isUUID3RFC4122(fl FieldLevel) bool {
function isUUIDRFC4122 (line 536) | func isUUIDRFC4122(fl FieldLevel) bool {
function isULID (line 541) | func isULID(fl FieldLevel) bool {
function isMD4 (line 546) | func isMD4(fl FieldLevel) bool {
function isMD5 (line 551) | func isMD5(fl FieldLevel) bool {
function isSHA256 (line 556) | func isSHA256(fl FieldLevel) bool {
function isSHA384 (line 561) | func isSHA384(fl FieldLevel) bool {
function isSHA512 (line 566) | func isSHA512(fl FieldLevel) bool {
function isRIPEMD128 (line 571) | func isRIPEMD128(fl FieldLevel) bool {
function isRIPEMD160 (line 576) | func isRIPEMD160(fl FieldLevel) bool {
function isTIGER128 (line 581) | func isTIGER128(fl FieldLevel) bool {
function isTIGER160 (line 586) | func isTIGER160(fl FieldLevel) bool {
function isTIGER192 (line 591) | func isTIGER192(fl FieldLevel) bool {
function isISBN (line 596) | func isISBN(fl FieldLevel) bool {
function isISBN13 (line 601) | func isISBN13(fl FieldLevel) bool {
function isISBN10 (line 621) | func isISBN10(fl FieldLevel) bool {
function isISSN (line 645) | func isISSN(fl FieldLevel) bool {
function isEthereumAddress (line 671) | func isEthereumAddress(fl FieldLevel) bool {
function isBitcoinAddress (line 678) | func isBitcoinAddress(fl FieldLevel) bool {
function isBitcoinBech32Address (line 715) | func isBitcoinBech32Address(fl FieldLevel) bool {
function excludesRune (line 795) | func excludesRune(fl FieldLevel) bool {
function excludesAll (line 800) | func excludesAll(fl FieldLevel) bool {
function excludes (line 805) | func excludes(fl FieldLevel) bool {
function containsRune (line 810) | func containsRune(fl FieldLevel) bool {
function containsAny (line 817) | func containsAny(fl FieldLevel) bool {
function contains (line 822) | func contains(fl FieldLevel) bool {
function startsWith (line 827) | func startsWith(fl FieldLevel) bool {
function endsWith (line 832) | func endsWith(fl FieldLevel) bool {
function startsNotWith (line 837) | func startsNotWith(fl FieldLevel) bool {
function endsNotWith (line 842) | func endsNotWith(fl FieldLevel) bool {
function fieldContains (line 847) | func fieldContains(fl FieldLevel) bool {
function fieldExcludes (line 860) | func fieldExcludes(fl FieldLevel) bool {
function isNeField (line 872) | func isNeField(fl FieldLevel) bool {
function isNe (line 922) | func isNe(fl FieldLevel) bool {
function isNeIgnoreCase (line 928) | func isNeIgnoreCase(fl FieldLevel) bool {
function isLteCrossStructField (line 933) | func isLteCrossStructField(fl FieldLevel) bool {
function isLtCrossStructField (line 980) | func isLtCrossStructField(fl FieldLevel) bool {
function isGteCrossStructField (line 1026) | func isGteCrossStructField(fl FieldLevel) bool {
function isGtCrossStructField (line 1072) | func isGtCrossStructField(fl FieldLevel) bool {
function isNeCrossStructField (line 1118) | func isNeCrossStructField(fl FieldLevel) bool {
function isEqCrossStructField (line 1167) | func isEqCrossStructField(fl FieldLevel) bool {
function isEqField (line 1216) | func isEqField(fl FieldLevel) bool {
function isEq (line 1265) | func isEq(fl FieldLevel) bool {
function isEqIgnoreCase (line 1311) | func isEqIgnoreCase(fl FieldLevel) bool {
function isPostcodeByIso3166Alpha2 (line 1326) | func isPostcodeByIso3166Alpha2(fl FieldLevel) bool {
function isPostcodeByIso3166Alpha2Field (line 1340) | func isPostcodeByIso3166Alpha2Field(fl FieldLevel) bool {
function isBase64 (line 1366) | func isBase64(fl FieldLevel) bool {
function isBase64URL (line 1371) | func isBase64URL(fl FieldLevel) bool {
function isBase64RawURL (line 1376) | func isBase64RawURL(fl FieldLevel) bool {
function isURI (line 1381) | func isURI(fl FieldLevel) bool {
function isFileURL (line 1408) | func isFileURL(path string) bool {
function isURL (line 1417) | func isURL(fl FieldLevel) bool {
function isHttpURL (line 1449) | func isHttpURL(fl FieldLevel) bool {
function isFile (line 1472) | func isFile(fl FieldLevel) bool {
function isFilePath (line 1489) | func isFilePath(fl FieldLevel) bool {
function isE164 (line 1544) | func isE164(fl FieldLevel) bool {
function isEmail (line 1549) | func isEmail(fl FieldLevel) bool {
function isHSLA (line 1554) | func isHSLA(fl FieldLevel) bool {
function isHSL (line 1559) | func isHSL(fl FieldLevel) bool {
function isRGBA (line 1564) | func isRGBA(fl FieldLevel) bool {
function isRGB (line 1569) | func isRGB(fl FieldLevel) bool {
function isHEXColor (line 1574) | func isHEXColor(fl FieldLevel) bool {
function isHexadecimal (line 1579) | func isHexadecimal(fl FieldLevel) bool {
function isNumber (line 1584) | func isNumber(fl FieldLevel) bool {
function isNumeric (line 1594) | func isNumeric(fl FieldLevel) bool {
function isAlphanum (line 1604) | func isAlphanum(fl FieldLevel) bool {
function isAlpha (line 1609) | func isAlpha(fl FieldLevel) bool {
function isAlphanumUnicode (line 1614) | func isAlphanumUnicode(fl FieldLevel) bool {
function isAlphaUnicode (line 1619) | func isAlphaUnicode(fl FieldLevel) bool {
function isBoolean (line 1624) | func isBoolean(fl FieldLevel) bool {
function isDefault (line 1635) | func isDefault(fl FieldLevel) bool {
function hasValue (line 1640) | func hasValue(fl FieldLevel) bool {
function requireCheckFieldKind (line 1654) | func requireCheckFieldKind(fl FieldLevel, param string, defaultNotFoundV...
function requireCheckFieldValue (line 1678) | func requireCheckFieldValue(
function requiredIf (line 1713) | func requiredIf(fl FieldLevel) bool {
function excludedIf (line 1728) | func excludedIf(fl FieldLevel) bool {
function requiredUnless (line 1744) | func requiredUnless(fl FieldLevel) bool {
function skipUnless (line 1760) | func skipUnless(fl FieldLevel) bool {
function excludedUnless (line 1775) | func excludedUnless(fl FieldLevel) bool {
function excludedWith (line 1790) | func excludedWith(fl FieldLevel) bool {
function requiredWith (line 1802) | func requiredWith(fl FieldLevel) bool {
function excludedWithAll (line 1814) | func excludedWithAll(fl FieldLevel) bool {
function requiredWithAll (line 1826) | func requiredWithAll(fl FieldLevel) bool {
function excludedWithout (line 1838) | func excludedWithout(fl FieldLevel) bool {
function requiredWithout (line 1847) | func requiredWithout(fl FieldLevel) bool {
function excludedWithoutAll (line 1856) | func excludedWithoutAll(fl FieldLevel) bool {
function requiredWithoutAll (line 1868) | func requiredWithoutAll(fl FieldLevel) bool {
function isGteField (line 1879) | func isGteField(fl FieldLevel) bool {
function isGtField (line 1925) | func isGtField(fl FieldLevel) bool {
function isGte (line 1971) | func isGte(fl FieldLevel) bool {
function isGt (line 2022) | func isGt(fl FieldLevel) bool {
function hasLengthOf (line 2070) | func hasLengthOf(fl FieldLevel) bool {
function hasMinOf (line 2111) | func hasMinOf(fl FieldLevel) bool {
function isLteField (line 2116) | func isLteField(fl FieldLevel) bool {
function isLtField (line 2162) | func isLtField(fl FieldLevel) bool {
function isLte (line 2208) | func isLte(fl FieldLevel) bool {
function isLt (line 2259) | func isLt(fl FieldLevel) bool {
function hasMaxOf (line 2307) | func hasMaxOf(fl FieldLevel) bool {
function isTCP4AddrResolvable (line 2312) | func isTCP4AddrResolvable(fl FieldLevel) bool {
function isTCP6AddrResolvable (line 2322) | func isTCP6AddrResolvable(fl FieldLevel) bool {
function isTCPAddrResolvable (line 2333) | func isTCPAddrResolvable(fl FieldLevel) bool {
function isUDP4AddrResolvable (line 2344) | func isUDP4AddrResolvable(fl FieldLevel) bool {
function isUDP6AddrResolvable (line 2355) | func isUDP6AddrResolvable(fl FieldLevel) bool {
function isUDPAddrResolvable (line 2366) | func isUDPAddrResolvable(fl FieldLevel) bool {
function isIP4AddrResolvable (line 2377) | func isIP4AddrResolvable(fl FieldLevel) bool {
function isIP6AddrResolvable (line 2388) | func isIP6AddrResolvable(fl FieldLevel) bool {
function isIPAddrResolvable (line 2399) | func isIPAddrResolvable(fl FieldLevel) bool {
function isUnixAddrResolvable (line 2410) | func isUnixAddrResolvable(fl FieldLevel) bool {
function isIP4Addr (line 2416) | func isIP4Addr(fl FieldLevel) bool {
function isIP6Addr (line 2428) | func isIP6Addr(fl FieldLevel) bool {
function isHostnameRFC952 (line 2442) | func isHostnameRFC952(fl FieldLevel) bool {
function isHostnameRFC1123 (line 2446) | func isHostnameRFC1123(fl FieldLevel) bool {
function isFQDN (line 2450) | func isFQDN(fl FieldLevel) bool {
function isDir (line 2461) | func isDir(fl FieldLevel) bool {
function isDirPath (line 2477) | func isDirPath(fl FieldLevel) bool {
function isJSON (line 2535) | func isJSON(fl FieldLevel) bool {
function isJWT (line 2555) | func isJWT(fl FieldLevel) bool {
function isHostnamePort (line 2560) | func isHostnamePort(fl FieldLevel) bool {
function isLowercase (line 2581) | func isLowercase(fl FieldLevel) bool {
function isUppercase (line 2595) | func isUppercase(fl FieldLevel) bool {
function isDatetime (line 2609) | func isDatetime(fl FieldLevel) bool {
function isTimeZone (line 2623) | func isTimeZone(fl FieldLevel) bool {
function isIso3166Alpha2 (line 2645) | func isIso3166Alpha2(fl FieldLevel) bool {
function isIso3166Alpha3 (line 2651) | func isIso3166Alpha3(fl FieldLevel) bool {
function isIso3166AlphaNumeric (line 2657) | func isIso3166AlphaNumeric(fl FieldLevel) bool {
function isIso31662 (line 2679) | func isIso31662(fl FieldLevel) bool {
function isIso4217 (line 2685) | func isIso4217(fl FieldLevel) bool {
function isIso4217Numeric (line 2691) | func isIso4217Numeric(fl FieldLevel) bool {
function isIsoBicFormat (line 2707) | func isIsoBicFormat(fl FieldLevel) bool {
function isSemverFormat (line 2714) | func isSemverFormat(fl FieldLevel) bool {
function isCveFormat (line 2721) | func isCveFormat(fl FieldLevel) bool {
function isDnsRFC1035LabelFormat (line 2730) | func isDnsRFC1035LabelFormat(fl FieldLevel) bool {
function digitsHaveLuhnChecksum (line 2736) | func digitsHaveLuhnChecksum(digits []string) bool {
function isMongoDB (line 2759) | func isMongoDB(fl FieldLevel) bool {
function isSpiceDB (line 2765) | func isSpiceDB(fl FieldLevel) bool {
function isCreditCard (line 2782) | func isCreditCard(fl FieldLevel) bool {
function hasLuhnChecksum (line 2803) | func hasLuhnChecksum(fl FieldLevel) bool {
function isCron (line 2825) | func isCron(fl FieldLevel) bool {
FILE: gossh/gin/validator/cache.go
type tagType (line 11) | type tagType
constant typeDefault (line 14) | typeDefault tagType = iota
constant typeOmitEmpty (line 15) | typeOmitEmpty
constant typeIsDefault (line 16) | typeIsDefault
constant typeNoStructLevel (line 17) | typeNoStructLevel
constant typeStructOnly (line 18) | typeStructOnly
constant typeDive (line 19) | typeDive
constant typeOr (line 20) | typeOr
constant typeKeys (line 21) | typeKeys
constant typeEndKeys (line 22) | typeEndKeys
constant typeOmitNil (line 23) | typeOmitNil
constant invalidValidation (line 27) | invalidValidation = "Invalid validation tag on field '%s'"
constant undefinedValidation (line 28) | undefinedValidation = "Undefined validation function '%s' on field '%s'"
constant keysTagNotDefined (line 29) | keysTagNotDefined = "'" + endKeysTag + "' tag encountered without a co...
type structCache (line 32) | type structCache struct
method Get (line 37) | func (sc *structCache) Get(key reflect.Type) (c *cStruct, found bool) {
method Set (line 42) | func (sc *structCache) Set(key reflect.Type, value *cStruct) {
type tagCache (line 52) | type tagCache struct
method Get (line 57) | func (tc *tagCache) Get(key string) (c *cTag, found bool) {
method Set (line 62) | func (tc *tagCache) Set(key string, value *cTag) {
type cStruct (line 72) | type cStruct struct
type cField (line 78) | type cField struct
type cTag (line 86) | type cTag struct
method extractStructCache (line 102) | func (v *Validate) extractStructCache(current reflect.Value, sName strin...
method parseFieldTagsRecursive (line 175) | func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string,...
method fetchCacheTag (line 316) | func (v *Validate) fetchCacheTag(tag string) *cTag {
FILE: gossh/gin/validator/errors.go
constant fieldErrMsg (line 12) | fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '...
type ValidationErrorsTranslations (line 16) | type ValidationErrorsTranslations
type InvalidValidationError (line 20) | type InvalidValidationError struct
method Error (line 25) | func (e *InvalidValidationError) Error() string {
type ValidationErrors (line 36) | type ValidationErrors
method Error (line 42) | func (ve ValidationErrors) Error() string {
type FieldError (line 56) | type FieldError interface
type fieldError (line 143) | type fieldError struct
method Translate (line 157) | func (fe *fieldError) Translate() string {
method Tag (line 162) | func (fe *fieldError) Tag() string {
method ActualTag (line 168) | func (fe *fieldError) ActualTag() string {
method Namespace (line 174) | func (fe *fieldError) Namespace() string {
method StructNamespace (line 180) | func (fe *fieldError) StructNamespace() string {
method Field (line 186) | func (fe *fieldError) Field() string {
method StructField (line 202) | func (fe *fieldError) StructField() string {
method Value (line 209) | func (fe *fieldError) Value() any {
method Param (line 215) | func (fe *fieldError) Param() string {
method Kind (line 220) | func (fe *fieldError) Kind() reflect.Kind {
method Type (line 225) | func (fe *fieldError) Type() reflect.Type {
method Error (line 230) | func (fe *fieldError) Error() string {
FILE: gossh/gin/validator/field_level.go
type FieldLevel (line 7) | type FieldLevel interface
method Field (line 69) | func (v *validate) Field() reflect.Value {
method FieldName (line 75) | func (v *validate) FieldName() string {
method GetTag (line 80) | func (v *validate) GetTag() string {
method StructFieldName (line 85) | func (v *validate) StructFieldName() string {
method Param (line 90) | func (v *validate) Param() string {
method GetStructFieldOK (line 97) | func (v *validate) GetStructFieldOK() (reflect.Value, reflect.Kind, bool) {
method GetStructFieldOKAdvanced (line 106) | func (v *validate) GetStructFieldOKAdvanced(val reflect.Value, namespace...
method GetStructFieldOK2 (line 112) | func (v *validate) GetStructFieldOK2() (reflect.Value, reflect.Kind, boo...
method GetStructFieldOKAdvanced2 (line 118) | func (v *validate) GetStructFieldOKAdvanced2(val reflect.Value, namespac...
FILE: gossh/gin/validator/options.go
type Option (line 4) | type Option
function WithRequiredStructEnabled (line 12) | func WithRequiredStructEnabled() Option {
FILE: gossh/gin/validator/postcode_regexes.go
function init (line 169) | func init() {
FILE: gossh/gin/validator/regexes.go
constant alphaRegexString (line 6) | alphaRegexString = "^[a-zA-Z]+$"
constant alphaNumericRegexString (line 7) | alphaNumericRegexString = "^[a-zA-Z0-9]+$"
constant alphaUnicodeRegexString (line 8) | alphaUnicodeRegexString = "^[\\p{L}]+$"
constant alphaUnicodeNumericRegexString (line 9) | alphaUnicodeNumericRegexString = "^[\\p{L}\\p{N}]+$"
constant numericRegexString (line 10) | numericRegexString = "^[-+]?[0-9]+(?:\\.[0-9]+)?$"
constant numberRegexString (line 11) | numberRegexString = "^[0-9]+$"
constant hexadecimalRegexString (line 12) | hexadecimalRegexString = "^(0[xX])?[0-9a-fA-F]+$"
constant hexColorRegexString (line 13) | hexColorRegexString = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[...
constant rgbRegexString (line 14) | rgbRegexString = "^rgb\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d...
constant rgbaRegexString (line 15) | rgbaRegexString = "^rgba\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\...
constant hslRegexString (line 16) | hslRegexString = "^hsl\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d...
constant hslaRegexString (line 17) | hslaRegexString = "^hsla\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\...
constant emailRegexString (line 18) | emailRegexString = "^(?:(?:(?:(?:[a-zA-Z]|\\d|[!#\\$%&'\...
constant e164RegexString (line 19) | e164RegexString = "^\\+[1-9]?[0-9]{7,14}$"
constant base64RegexString (line 20) | base64RegexString = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-...
constant base64URLRegexString (line 21) | base64URLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-...
constant base64RawURLRegexString (line 22) | base64RawURLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-...
constant iSBN10RegexString (line 23) | iSBN10RegexString = "^(?:[0-9]{9}X|[0-9]{10})$"
constant iSBN13RegexString (line 24) | iSBN13RegexString = "^(?:(?:97(?:8|9))[0-9]{10})$"
constant iSSNRegexString (line 25) | iSSNRegexString = "^(?:[0-9]{4}-[0-9]{3}[0-9X])$"
constant uUID3RegexString (line 26) | uUID3RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3...
constant uUID4RegexString (line 27) | uUID4RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3...
constant uUID5RegexString (line 28) | uUID5RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3...
constant uUIDRegexString (line 29) | uUIDRegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}...
constant uUID3RFC4122RegexString (line 30) | uUID3RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-3[0-9...
constant uUID4RFC4122RegexString (line 31) | uUID4RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9...
constant uUID5RFC4122RegexString (line 32) | uUID5RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-5[0-9...
constant uUIDRFC4122RegexString (line 33) | uUIDRFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a...
constant uLIDRegexString (line 34) | uLIDRegexString = "^[A-HJKMNP-TV-Z0-9]{26}$"
constant md4RegexString (line 35) | md4RegexString = "^[0-9a-f]{32}$"
constant md5RegexString (line 36) | md5RegexString = "^[0-9a-f]{32}$"
constant sha256RegexString (line 37) | sha256RegexString = "^[0-9a-f]{64}$"
constant sha384RegexString (line 38) | sha384RegexString = "^[0-9a-f]{96}$"
constant sha512RegexString (line 39) | sha512RegexString = "^[0-9a-f]{128}$"
constant ripemd128RegexString (line 40) | ripemd128RegexString = "^[0-9a-f]{32}$"
constant ripemd160RegexString (line 41) | ripemd160RegexString = "^[0-9a-f]{40}$"
constant tiger128RegexString (line 42) | tiger128RegexString = "^[0-9a-f]{32}$"
constant tiger160RegexString (line 43) | tiger160RegexString = "^[0-9a-f]{40}$"
constant tiger192RegexString (line 44) | tiger192RegexString = "^[0-9a-f]{48}$"
constant aSCIIRegexString (line 45) | aSCIIRegexString = "^[\x00-\x7F]*$"
constant printableASCIIRegexString (line 46) | printableASCIIRegexString = "^[\x20-\x7E]*$"
constant multibyteRegexString (line 47) | multibyteRegexString = "[^\x00-\x7F]"
constant dataURIRegexString (line 48) | dataURIRegexString = `^data:((?:\w+\/(?:([^;]|;[^;]).)+)?)`
constant latitudeRegexString (line 49) | latitudeRegexString = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)...
constant longitudeRegexString (line 50) | longitudeRegexString = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-...
constant sSNRegexString (line 51) | sSNRegexString = `^[0-9]{3}[ -]?(0[1-9]|[1-9][0-9])[ -...
constant hostnameRegexStringRFC952 (line 52) | hostnameRegexStringRFC952 = `^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA...
constant hostnameRegexStringRFC1123 (line 53) | hostnameRegexStringRFC1123 = `^([a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62}){...
constant fqdnRegexStringRFC1123 (line 54) | fqdnRegexStringRFC1123 = `^([a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})(...
constant btcAddressRegexString (line 55) | btcAddressRegexString = `^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$`
constant btcAddressUpperRegexStringBech32 (line 56) | btcAddressUpperRegexStringBech32 = `^BC1[02-9AC-HJ-NP-Z]{7,76}$`
constant btcAddressLowerRegexStringBech32 (line 57) | btcAddressLowerRegexStringBech32 = `^bc1[02-9ac-hj-np-z]{7,76}$`
constant ethAddressRegexString (line 58) | ethAddressRegexString = `^0x[0-9a-fA-F]{40}$`
constant ethAddressUpperRegexString (line 59) | ethAddressUpperRegexString = `^0x[0-9A-F]{40}$`
constant ethAddressLowerRegexString (line 60) | et
Copy disabled (too large)
Download .json
Condensed preview — 997 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (14,250K chars).
[
{
"path": ".github/workflows/build-and-release.yml",
"chars": 2572,
"preview": "name: Build & Release\n\non:\n push:\n tags:\n - 'v*'\n\njobs:\n build-release:\n runs-on: ubuntu-latest\n name: B"
},
{
"path": ".gitignore",
"chars": 1866,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# Diagnostic reports (https://nodejs."
},
{
"path": "Dockerfile",
"chars": 313,
"preview": "# 第一阶段:构建\nFROM golang:1.23.4 AS builder\nWORKDIR /mnt\nCOPY gossh ./gossh\nRUN cd /mnt/gossh && CGO_ENABLED=0 go build -o /"
},
{
"path": "LICENSE",
"chars": 1063,
"preview": "MIT License\n\nCopyright (c) 2021 o8oo8o\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
},
{
"path": "README.md",
"chars": 3126,
"preview": "## GoWebSSH\n<br/>\n\n### 项目介绍:\n* **Web版ssh客户端 + (sshd,sftp)服务端实现**\n<br/>\n\n### 概要:\n* Golang 1.23 + (Vue3.5 + Vite6) 实现一个We"
},
{
"path": "gossh/Makefile",
"chars": 664,
"preview": "\n.PHONY: clean all\n\nall: linux-amd64 linux-arm64 macos-amd64 macos-arm64 windows-amd64\n\nlinux-amd64:\n\tCGO_ENABLED=0 GOOS"
},
{
"path": "gossh/app/config/config.go",
"chars": 4279,
"preview": "package config\n\nimport (\n\t\"flag\"\n\t\"gossh/app/utils\"\n\t\"gossh/toml\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path\"\n\t\"time\"\n)\n\ntype AppConfig st"
},
{
"path": "gossh/app/middleware/db_check.go",
"chars": 551,
"preview": "package middleware\n\nimport (\n\t\"gossh/app/config\"\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n)\n\nfunc DbCheck() gin.HandlerFunc {\n\tre"
},
{
"path": "gossh/app/middleware/jwt_auth.go",
"chars": 2262,
"preview": "package middleware\n\nimport (\n\t\"errors\"\n\t\"gossh/app/config\"\n\t\"gossh/gin\"\n\t\"gossh/gin/jwt\"\n\t\"strings\"\n\t\"time\"\n)\n\n// JwtSec"
},
{
"path": "gossh/app/middleware/net_filter.go",
"chars": 1639,
"preview": "package middleware\n\nimport (\n\t\"fmt\"\n\t\"gossh/app/config\"\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"log/slog\"\n\t\"net\"\n)\n\nfunc check"
},
{
"path": "gossh/app/middleware/perm_check.go",
"chars": 2676,
"preview": "package middleware\n\nimport (\n\t\"fmt\"\n\t\"gossh/app/config\"\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"slices\"\n\t\"strings\"\n)\n\nvar chec"
},
{
"path": "gossh/app/middleware/sys_init.go",
"chars": 279,
"preview": "package middleware\n\nimport (\n\t\"gossh/app/config\"\n\t\"gossh/gin\"\n)\n\nfunc SysInit() gin.HandlerFunc {\n\treturn func(c *gin.Co"
},
{
"path": "gossh/app/model/cmd_note.go",
"chars": 1369,
"preview": "package model\n\ntype CmdNote struct {\n\tID uint `gorm:\"column:id;primaryKey,autoIncrement\" form:\"id\" json:\"id\"`\n\tUi"
},
{
"path": "gossh/app/model/datetime.go",
"chars": 1376,
"preview": "package model\n\nimport (\n\t\"database/sql/driver\"\n\t\"fmt\"\n\t\"time\"\n)\n\nconst (\n\tTimeFormat = \"2006-01-02 15:04:05\"\n)\n\ntype Dat"
},
{
"path": "gossh/app/model/db_init.go",
"chars": 2301,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"gossh/app/config\"\n\t\"gossh/gorm\"\n\t\"gossh/gorm/driver/mysql\"\n\t\"gossh/gorm/drive"
},
{
"path": "gossh/app/model/login_audit.go",
"chars": 2215,
"preview": "package model\n\ntype LoginAudit struct {\n\tID uint `gorm:\"column:id;primaryKey,autoIncrement\" form:\"id\" json:\"i"
},
{
"path": "gossh/app/model/net_filter.go",
"chars": 1941,
"preview": "package model\n\nimport \"time\"\n\ntype NetFilter struct {\n\tID uint `gorm:\"column:id;primaryKey,autoIncrement\" for"
},
{
"path": "gossh/app/model/policy_conf.go",
"chars": 1053,
"preview": "package model\n\ntype PolicyConf struct {\n\tID uint `gorm:\"column:id;primaryKey,autoIncrement\" form:\"id\" json:\"id\""
},
{
"path": "gossh/app/model/ssh_conf.go",
"chars": 4881,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"gossh/app/config\"\n\t\"gossh/app/utils\"\n\t\"gossh/gorm\"\n)\n\ntype SshConf struct {\n\tID "
},
{
"path": "gossh/app/model/sshd_cert.go",
"chars": 2009,
"preview": "package model\n\nimport \"time\"\n\ntype SshdCert struct {\n\tID uint `gorm:\"column:id;primaryKey,autoIncrement\" form:"
},
{
"path": "gossh/app/model/sshd_conf.go",
"chars": 2858,
"preview": "package model\n\nimport (\n\t\"gossh/app/config\"\n\t\"gossh/app/utils\"\n\t\"gossh/gorm\"\n)\n\ntype SshdConf struct {\n\tID ui"
},
{
"path": "gossh/app/model/sshd_user.go",
"chars": 2798,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"gossh/app/config\"\n\t\"gossh/app/utils\"\n\t\"gossh/gorm\"\n\t\"time\"\n)\n\ntype SshdUser s"
},
{
"path": "gossh/app/model/web_user.go",
"chars": 2971,
"preview": "package model\n\nimport (\n\t\"errors\"\n\t\"gossh/app/config\"\n\t\"gossh/app/utils\"\n\t\"gossh/gorm\"\n)\n\ntype WebUser struct {\n\tID "
},
{
"path": "gossh/app/service/cmd_note.go",
"chars": 1990,
"preview": "package service\n\nimport (\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"strconv\"\n)\n\nfunc CmdNoteCreate(c *gin.Context) {\n\tvar cmd mo"
},
{
"path": "gossh/app/service/db_conn.go",
"chars": 1573,
"preview": "package service\n\nimport (\n\t\"gossh/app/config\"\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"gossh/gorm\"\n\t\"gossh/gorm/driver/mysql\"\n\t"
},
{
"path": "gossh/app/service/login_audit.go",
"chars": 1786,
"preview": "package service\n\nimport (\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"strconv\"\n)\n\nfunc AuditFindByID(c *gin.Context) {\n\tid, err :="
},
{
"path": "gossh/app/service/net_filter.go",
"chars": 2008,
"preview": "package service\n\nimport (\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"strconv\"\n)\n\nfunc NetFilterCreate(c *gin.Context) {\n\tvar netF"
},
{
"path": "gossh/app/service/policy_conf.go",
"chars": 2101,
"preview": "package service\n\nimport (\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"strconv\"\n)\n\nfunc PolicyConfCreate(c *gin.Context) {\n\tvar con"
},
{
"path": "gossh/app/service/service_init.go",
"chars": 2309,
"preview": "package service\n\nimport (\n\t\"gossh/app/config\"\n\t\"io\"\n\t\"log/slog\"\n\t\"sync\"\n\t\"time\"\n)\n\n// OnlineClients 存储的客户端信息\nvar OnlineC"
},
{
"path": "gossh/app/service/ssh_conf.go",
"chars": 2108,
"preview": "package service\n\nimport (\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"strconv\"\n)\n\nfunc ConfCreate(c *gin.Context) {\n\tvar config mo"
},
{
"path": "gossh/app/service/ssh_conn.go",
"chars": 10483,
"preview": "package service\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"gossh/app/model\"\n\t\"gossh/app/utils\"\n\t\"gossh/crypto/ssh\"\n\t\"gossh/gin\""
},
{
"path": "gossh/app/service/ssh_sftp.go",
"chars": 6680,
"preview": "package service\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"gossh/gin\"\n\t\"io\"\n\t\"log/slog\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"strconv\"\n\t\"st"
},
{
"path": "gossh/app/service/ssh_status.go",
"chars": 1447,
"preview": "package service\n\nimport (\n\t\"gossh/app/config\"\n\t\"gossh/gin\"\n\t\"gossh/gin/sse\"\n\t\"net/http\"\n\t\"sort\"\n\t\"time\"\n)\n\ntype SshConnB"
},
{
"path": "gossh/app/service/sshd_cert.go",
"chars": 3578,
"preview": "package service\n\nimport (\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"log/slog\"\n\t\"strconv\"\n)\n\nfunc SshdCertCreate(c *gin.Context) "
},
{
"path": "gossh/app/service/sshd_server.go",
"chars": 14116,
"preview": "package service\n\nimport (\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/sha256\"\n\t\"crypto/sha512\"\n\t\"crypto/x509\"\n\t\"encod"
},
{
"path": "gossh/app/service/sshd_user.go",
"chars": 3193,
"preview": "package service\n\nimport (\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"log/slog\"\n\t\"strconv\"\n)\n\nfunc SshdUserCreate(c *gin.Context) "
},
{
"path": "gossh/app/service/sys_init.go",
"chars": 5189,
"preview": "package service\n\nimport (\n\t\"gossh/app/config\"\n\t\"gossh/app/model\"\n\t\"gossh/gin\"\n\t\"log/slog\"\n\t\"os/exec\"\n\t\"runtime\"\n)\n\nfunc "
},
{
"path": "gossh/app/service/web_user.go",
"chars": 6722,
"preview": "package service\n\nimport (\n\t\"gossh/app/config\"\n\t\"gossh/app/middleware\"\n\t\"gossh/app/model\"\n\t\"gossh/app/utils\"\n\t\"gossh/gin\""
},
{
"path": "gossh/app/utils/crypto.go",
"chars": 3760,
"preview": "package utils\n\nimport (\n\t\"bytes\"\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/rand\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\""
},
{
"path": "gossh/app/utils/utils.go",
"chars": 572,
"preview": "package utils\n\nimport (\n\t\"math/rand\"\n\t\"time\"\n\t\"unicode/utf8\"\n)\n\n// RandString 生成指定长度随机字符串\nfunc RandString(length int) st"
},
{
"path": "gossh/crypto/blowfish/block.go",
"chars": 6161,
"preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/blowfish/cipher.go",
"chars": 3536,
"preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/blowfish/const.go",
"chars": 13132,
"preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/chacha_arm64.go",
"chars": 441,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/chacha_arm64.s",
"chars": 8130,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/chacha_generic.go",
"chars": 14175,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/chacha_noasm.go",
"chars": 361,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/chacha_ppc64le.go",
"chars": 447,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/chacha_ppc64le.s",
"chars": 9315,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/chacha_s390x.go",
"chars": 736,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/chacha_s390x.s",
"chars": 5460,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20/xor.go",
"chars": 1274,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20poly1305/chacha20poly1305.go",
"chars": 2853,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20poly1305/chacha20poly1305_amd64.go",
"chars": 2434,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20poly1305/chacha20poly1305_amd64.s",
"chars": 107823,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20poly1305/chacha20poly1305_generic.go",
"chars": 2183,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20poly1305/chacha20poly1305_noasm.go",
"chars": 534,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/chacha20poly1305/xchacha20poly1305.go",
"chars": 2574,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/curve25519/curve25519.go",
"chars": 2156,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/curve25519/curve25519_compat.go",
"chars": 2314,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/curve25519/curve25519_go120.go",
"chars": 1113,
"preview": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/curve25519/internal/field/fe.go",
"chars": 11828,
"preview": "// Copyright (c) 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
},
{
"path": "gossh/crypto/curve25519/internal/field/fe_amd64.go",
"chars": 410,
"preview": "// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.\n\n"
},
{
"path": "gossh/crypto/curve25519/internal/field/fe_amd64.s",
"chars": 5738,
"preview": "// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.\n\n"
},
{
"path": "gossh/crypto/curve25519/internal/field/fe_amd64_noasm.go",
"chars": 326,
"preview": "// Copyright (c) 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
},
{
"path": "gossh/crypto/curve25519/internal/field/fe_arm64.go",
"chars": 338,
"preview": "// Copyright (c) 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
},
{
"path": "gossh/crypto/curve25519/internal/field/fe_arm64.s",
"chars": 1064,
"preview": "// Copyright (c) 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
},
{
"path": "gossh/crypto/curve25519/internal/field/fe_arm64_noasm.go",
"chars": 297,
"preview": "// Copyright (c) 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
},
{
"path": "gossh/crypto/curve25519/internal/field/fe_generic.go",
"chars": 8385,
"preview": "// Copyright (c) 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
},
{
"path": "gossh/crypto/curve25519/internal/field/sync.checkpoint",
"chars": 41,
"preview": "b0c49ae9f59d233526f8934262c5bbbe14d4358d\n"
},
{
"path": "gossh/crypto/curve25519/internal/field/sync.sh",
"chars": 611,
"preview": "#! /bin/bash\nset -euo pipefail\n\ncd \"$(git rev-parse --show-toplevel)\"\n\nSTD_PATH=src/crypto/ed25519/internal/edwards25519"
},
{
"path": "gossh/crypto/internal/alias/alias.go",
"chars": 1130,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/alias/alias_purego.go",
"chars": 1260,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/mac_noasm.go",
"chars": 268,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/poly1305.go",
"chars": 3386,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/sum_amd64.go",
"chars": 1119,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/sum_amd64.s",
"chars": 2545,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/sum_generic.go",
"chars": 9682,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/sum_ppc64le.go",
"chars": 1119,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/sum_ppc64le.s",
"chars": 3298,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/sum_s390x.go",
"chars": 2019,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/poly1305/sum_s390x.s",
"chars": 17106,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/testenv/exec.go",
"chars": 4629,
"preview": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/testenv/testenv_notunix.go",
"chars": 401,
"preview": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/internal/testenv/testenv_unix.go",
"chars": 348,
"preview": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/agent/client.go",
"chars": 23738,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/agent/forward.go",
"chars": 2207,
"preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/agent/keyring.go",
"chars": 5386,
"preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/agent/server.go",
"chars": 13617,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/buffer.go",
"chars": 2180,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/certs.go",
"chars": 17920,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/channel.go",
"chars": 16479,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/cipher.go",
"chars": 21743,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/client.go",
"chars": 8789,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/client_auth.go",
"chars": 23827,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/common.go",
"chars": 13513,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/connection.go",
"chars": 3413,
"preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/doc.go",
"chars": 1007,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/handshake.go",
"chars": 22251,
"preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go",
"chars": 2423,
"preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/kex.go",
"chars": 22709,
"preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/keys.go",
"chars": 45753,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/knownhosts/knownhosts.go",
"chars": 12565,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/mac.go",
"chars": 1576,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/messages.go",
"chars": 20723,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/mux.go",
"chars": 8048,
"preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/server.go",
"chars": 26553,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/session.go",
"chars": 15437,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/ssh_gss.go",
"chars": 5570,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/streamlocal.go",
"chars": 2939,
"preview": "package ssh\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"net\"\n)\n\n// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_"
},
{
"path": "gossh/crypto/ssh/tcpip.go",
"chars": 13152,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/terminal/terminal.go",
"chars": 2570,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/crypto/ssh/transport.go",
"chars": 9996,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "gossh/gin/auth.go",
"chars": 3823,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/binding/binding.go",
"chars": 3492,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/binding/default_validator.go",
"chars": 2366,
"preview": "// Copyright 2017 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/binding/form.go",
"chars": 1346,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/binding/form_mapping.go",
"chars": 9387,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/binding/header.go",
"chars": 869,
"preview": "// Copyright 2022 Gin Core Team. All rights reserved.\n// Use of this source code is governed by a MIT style\n// license t"
},
{
"path": "gossh/gin/binding/json.go",
"chars": 1527,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/binding/multipart_form_mapping.go",
"chars": 2244,
"preview": "// Copyright 2019 Gin Core Team. All rights reserved.\n// Use of this source code is governed by a MIT style\n// license t"
},
{
"path": "gossh/gin/binding/query.go",
"chars": 460,
"preview": "// Copyright 2017 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/binding/uri.go",
"chars": 399,
"preview": "// Copyright 2018 Gin Core Team. All rights reserved.\n// Use of this source code is governed by a MIT style\n// license t"
},
{
"path": "gossh/gin/binding/xml.go",
"chars": 676,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/context.go",
"chars": 36759,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/debug.go",
"chars": 2929,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/errors.go",
"chars": 3985,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/fs.go",
"chars": 1119,
"preview": "// Copyright 2017 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/gin.go",
"chars": 22766,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/ginS/README.md",
"chars": 220,
"preview": "# Gin Default Server\n\nThis is API experiment for Gin.\n\n```go\npackage main\n\nimport (\n\t\"gossh/gin\"\n\t\"gossh/gin/ginS\"\n)\n\nfu"
},
{
"path": "gossh/gin/ginS/gins.go",
"chars": 5575,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/internal/bytesconv/bytesconv.go",
"chars": 719,
"preview": "// Copyright 2023 Gin Core Team. All rights reserved.\n// Use of this source code is governed by a MIT style\n// license t"
},
{
"path": "gossh/gin/internal/json/json.go",
"chars": 587,
"preview": "// Copyright 2017 Bo-Yi Wu. All rights reserved.\n// Use of this source code is governed by a MIT style\n// license that c"
},
{
"path": "gossh/gin/jwt/README.md",
"chars": 7796,
"preview": "# jwt-go\n\n[](https://github.com/golang-"
},
{
"path": "gossh/gin/jwt/claims.go",
"chars": 638,
"preview": "package jwt\n\n// Claims represent any form of a JWT Claims Set according to\n// https://datatracker.ietf.org/doc/html/rfc7"
},
{
"path": "gossh/gin/jwt/cmd/jwt/README.md",
"chars": 624,
"preview": "`jwt` command-line tool\n=======================\n\nThis is a simple tool to sign, verify and show JSON Web Tokens from\nthe"
},
{
"path": "gossh/gin/jwt/cmd/jwt/main.go",
"chars": 8118,
"preview": "// A useful example app. You can use this to debug your tokens on the command line.\n// This is also a great place to lo"
},
{
"path": "gossh/gin/jwt/ecdsa.go",
"chars": 3463,
"preview": "package jwt\n\nimport (\n\t\"crypto\"\n\t\"crypto/ecdsa\"\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"math/big\"\n)\n\nvar (\n\t// Sadly this is missing "
},
{
"path": "gossh/gin/jwt/ecdsa_utils.go",
"chars": 1580,
"preview": "package jwt\n\nimport (\n\t\"crypto/ecdsa\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"errors\"\n)\n\nvar (\n\tErrNotECPublicKey = errors.New"
},
{
"path": "gossh/gin/jwt/ed25519.go",
"chars": 2074,
"preview": "package jwt\n\nimport (\n\t\"crypto\"\n\t\"crypto/ed25519\"\n\t\"crypto/rand\"\n\t\"errors\"\n)\n\nvar (\n\tErrEd25519Verification = errors.New"
},
{
"path": "gossh/gin/jwt/ed25519_utils.go",
"chars": 1398,
"preview": "package jwt\n\nimport (\n\t\"crypto\"\n\t\"crypto/ed25519\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"errors\"\n)\n\nvar (\n\tErrNotEdPrivateKey "
},
{
"path": "gossh/gin/jwt/errors.go",
"chars": 1836,
"preview": "package jwt\n\nimport (\n\t\"errors\"\n\t\"strings\"\n)\n\nvar (\n\tErrInvalidKey = errors.New(\"key is invalid\")\n\tErrInv"
},
{
"path": "gossh/gin/jwt/errors_go1_20.go",
"chars": 1120,
"preview": "//go:build go1.20\n// +build go1.20\n\npackage jwt\n\nimport (\n\t\"fmt\"\n)\n\n// Unwrap implements the multiple error unwrapping f"
},
{
"path": "gossh/gin/jwt/errors_go_other.go",
"chars": 2126,
"preview": "//go:build !go1.20\n// +build !go1.20\n\npackage jwt\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\n// Is implements checking for multiple e"
},
{
"path": "gossh/gin/jwt/hmac.go",
"chars": 3411,
"preview": "package jwt\n\nimport (\n\t\"crypto\"\n\t\"crypto/hmac\"\n\t\"errors\"\n)\n\n// SigningMethodHMAC implements the HMAC-SHA family of signi"
},
{
"path": "gossh/gin/jwt/map_claims.go",
"chars": 2691,
"preview": "package jwt\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// MapClaims is a claims type that uses the map[string]interface{} for "
},
{
"path": "gossh/gin/jwt/none.go",
"chars": 1615,
"preview": "package jwt\n\n// SigningMethodNone implements the none signing method. This is required by the spec\n// but you probably "
},
{
"path": "gossh/gin/jwt/parser.go",
"chars": 7975,
"preview": "package jwt\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype Parser struct {\n\t// If popu"
},
{
"path": "gossh/gin/jwt/parser_option.go",
"chars": 4565,
"preview": "package jwt\n\nimport \"time\"\n\n// ParserOption is used to implement functional-style options that modify the\n// behavior of"
},
{
"path": "gossh/gin/jwt/registered_claims.go",
"chars": 2321,
"preview": "package jwt\n\n// RegisteredClaims are a structured version of the JWT Claims Set,\n// restricted to Registered Claim Names"
},
{
"path": "gossh/gin/jwt/request/doc.go",
"chars": 247,
"preview": "// Utility package for extracting JWT tokens from\n// HTTP requests.\n//\n// The main function is ParseFromRequest and it's"
},
{
"path": "gossh/gin/jwt/request/extractor.go",
"chars": 3071,
"preview": "package request\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// Errors\nvar (\n\tErrNoTokenInRequest = errors.New(\"no toke"
},
{
"path": "gossh/gin/jwt/request/oauth2.go",
"chars": 821,
"preview": "package request\n\nimport (\n\t\"strings\"\n)\n\n// Strips 'Bearer ' prefix from bearer token string\nfunc stripBearerPrefixFromTo"
},
{
"path": "gossh/gin/jwt/request/request.go",
"chars": 1928,
"preview": "package request\n\nimport (\n\t\"net/http\"\n\n\t\"gossh/gin/jwt\"\n)\n\n// ParseFromRequest extracts and parses a JWT token from an H"
},
{
"path": "gossh/gin/jwt/rsa.go",
"chars": 2401,
"preview": "package jwt\n\nimport (\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n)\n\n// SigningMethodRSA implements the RSA family of signing"
},
{
"path": "gossh/gin/jwt/rsa_pss.go",
"chars": 3411,
"preview": "package jwt\n\nimport (\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n)\n\n// SigningMethodRSAPSS implements the RSAPSS family of s"
},
{
"path": "gossh/gin/jwt/rsa_utils.go",
"chars": 2916,
"preview": "package jwt\n\nimport (\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"errors\"\n)\n\nvar (\n\tErrKeyMustBePEMEncoded = errors.N"
},
{
"path": "gossh/gin/jwt/signing_method.go",
"chars": 1539,
"preview": "package jwt\n\nimport (\n\t\"sync\"\n)\n\nvar signingMethods = map[string]func() SigningMethod{}\nvar signingMethodLock = new(sync"
},
{
"path": "gossh/gin/jwt/token.go",
"chars": 3548,
"preview": "package jwt\n\nimport (\n\t\"crypto\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n)\n\n// Keyfunc will be used by the Parse methods as a"
},
{
"path": "gossh/gin/jwt/token_option.go",
"chars": 185,
"preview": "package jwt\n\n// TokenOption is a reserved type, which provides some forward compatibility,\n// if we ever want to introdu"
},
{
"path": "gossh/gin/jwt/types.go",
"chars": 4879,
"preview": "package jwt\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n\t\"strconv\"\n\t\"time\"\n)\n\n// TimePrecision sets the precision of times"
},
{
"path": "gossh/gin/jwt/validator.go",
"chars": 9751,
"preview": "package jwt\n\nimport (\n\t\"crypto/subtle\"\n\t\"fmt\"\n\t\"time\"\n)\n\n// ClaimsValidator is an interface that can be implemented by c"
},
{
"path": "gossh/gin/logger.go",
"chars": 6986,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/mode.go",
"chars": 2342,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/path.go",
"chars": 3691,
"preview": "// Copyright 2013 Julien Schmidt. All rights reserved.\n// Based on the path package, Copyright 2009 The Go Authors.\n// U"
},
{
"path": "gossh/gin/recovery.go",
"chars": 5205,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/render/data.go",
"chars": 639,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/render/html.go",
"chars": 2527,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/render/json.go",
"chars": 4804,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/render/reader.go",
"chars": 1208,
"preview": "// Copyright 2018 Gin Core Team. All rights reserved.\n// Use of this source code is governed by a MIT style\n// license t"
},
{
"path": "gossh/gin/render/redirect.go",
"chars": 904,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/render/render.go",
"chars": 1084,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/render/text.go",
"chars": 1076,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/render/xml.go",
"chars": 730,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/response_writer.go",
"chars": 2854,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/routergroup.go",
"chars": 9280,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/sessions/context/context.go",
"chars": 3258,
"preview": "package context\n\nimport (\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar (\n\tmutex sync.RWMutex\n\tdata = make(map[*http.Request]map[a"
},
{
"path": "gossh/gin/sessions/cookie/cookie.go",
"chars": 931,
"preview": "package cookie\n\nimport (\n\t\"gossh/gin/sessions\"\n\tgsessions \"gossh/gin/sessions/sessions\"\n)\n\ntype Store interface {\n\tsessi"
},
{
"path": "gossh/gin/sessions/memstore/cache.go",
"chars": 592,
"preview": "package memstore\n\nimport (\n\t\"sync\"\n)\n\ntype cache struct {\n\tdata map[string]valueType\n\tmutex sync.RWMutex\n}\n\nfunc newCac"
},
{
"path": "gossh/gin/sessions/memstore/memstore.go",
"chars": 4648,
"preview": "package memstore\n\nimport (\n\t\"bytes\"\n\t\"encoding/base32\"\n\t\"encoding/gob\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"gossh/gin/sessio"
},
{
"path": "gossh/gin/sessions/memstore/store.go",
"chars": 863,
"preview": "package memstore\n\nimport (\n\t\"gossh/gin/sessions\"\n)\n\ntype Store interface {\n\tsessions.Store\n}\n\n// Keys are defined in pai"
},
{
"path": "gossh/gin/sessions/securecookie/securecookie.go",
"chars": 20105,
"preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
},
{
"path": "gossh/gin/sessions/session_options_go1.10.go",
"chars": 739,
"preview": "//go:build !go1.11\n// +build !go1.11\n\npackage sessions\n\nimport (\n\tgsessions \"gossh/gin/sessions/sessions\"\n)\n\n// Options "
},
{
"path": "gossh/gin/sessions/session_options_go1.11.go",
"chars": 1044,
"preview": "//go:build go1.11\n// +build go1.11\n\npackage sessions\n\nimport (\n\t\"net/http\"\n\n\tgsessions \"gossh/gin/sessions/sessions\"\n)\n\n"
},
{
"path": "gossh/gin/sessions/sessions/cookie.go",
"chars": 428,
"preview": "//go:build !go1.11\n// +build !go1.11\n\npackage sessions\n\nimport \"net/http\"\n\n// newCookieFromOptions returns an http.Cooki"
},
{
"path": "gossh/gin/sessions/sessions/cookie_go111.go",
"chars": 456,
"preview": "//go:build go1.11\n// +build go1.11\n\npackage sessions\n\nimport \"net/http\"\n\n// newCookieFromOptions returns an http.Cookie "
},
{
"path": "gossh/gin/sessions/sessions/doc.go",
"chars": 7555,
"preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
},
{
"path": "gossh/gin/sessions/sessions/lex.go",
"chars": 1505,
"preview": "// This file contains code adapted from the Go standard library\n// https://github.com/golang/go/blob/39ad0fd0789872f9469"
},
{
"path": "gossh/gin/sessions/sessions/options.go",
"chars": 497,
"preview": "//go:build !go1.11\n// +build !go1.11\n\npackage sessions\n\n// Options stores configuration for a session or session store.\n"
},
{
"path": "gossh/gin/sessions/sessions/options_go111.go",
"chars": 579,
"preview": "//go:build go1.11\n// +build go1.11\n\npackage sessions\n\nimport \"net/http\"\n\n// Options stores configuration for a session o"
},
{
"path": "gossh/gin/sessions/sessions/sessions.go",
"chars": 5767,
"preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
},
{
"path": "gossh/gin/sessions/sessions/store.go",
"chars": 8626,
"preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
},
{
"path": "gossh/gin/sessions/sessions.go",
"chars": 3553,
"preview": "package sessions\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\n\t\"gossh/gin\"\n\t\"gossh/gin/sessions/context\"\n\t\"gossh/gin/sessions/sessions\""
},
{
"path": "gossh/gin/sse/sse-decoder.go",
"chars": 3721,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// "
},
{
"path": "gossh/gin/sse/sse-encoder.go",
"chars": 2232,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// "
},
{
"path": "gossh/gin/sse/writer.go",
"chars": 395,
"preview": "package sse\n\nimport \"io\"\n\ntype stringWriter interface {\n\tio.Writer\n\tWriteString(string) (int, error)\n}\n\ntype stringWrapp"
},
{
"path": "gossh/gin/tree.go",
"chars": 22897,
"preview": "// Copyright 2013 Julien Schmidt. All rights reserved.\n// Use of this source code is governed by a BSD-style license tha"
},
{
"path": "gossh/gin/utils.go",
"chars": 3595,
"preview": "// Copyright 2014 Manu Martinez-Almeida. All rights reserved.\n// Use of this source code is governed by a MIT style\n// l"
},
{
"path": "gossh/gin/validator/baked_in.go",
"chars": 83073,
"preview": "package validator\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"net\"\n\t\"net/url\"\n\t\"os"
},
{
"path": "gossh/gin/validator/cache.go",
"chars": 7766,
"preview": "package validator\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n)\n\ntype tagType uint8\n\nconst (\n\ttypeDefa"
}
]
// ... and 797 more files (download for full content)
About this extraction
This page contains the full source code of the o8oo8o/GoWebSSH GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 997 files (12.8 MB), approximately 3.4M tokens, and a symbol index with 107986 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.