Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(session): SHA1 has been deprecated #17

Merged
merged 6 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: CI
on:
push:
workflow_dispatch:
pull_request:
branches: [master]
schedule:
- cron: "0 6 * * 1"
jobs:
Expand All @@ -12,17 +13,15 @@ jobs:
os: [ubuntu-latest]
crystal:
- latest
- nightly
- 1.0.0
runs-on: ${{ matrix.os }}
container: crystallang/crystal:${{ matrix.crystal }}-alpine

services:
# Label used to access the service container
sshtest:
image: placeos/ssh-test:latest
image: testcontainers/sshd:1.2.0
env:
ROOT_PASS: somepassword
PASSWORD: somepassword

steps:
- uses: actions/checkout@v2
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ This library provides binding for libssh2 library.

# Requirements

- Crystal language version 0.7.0 and higher.
- libssh2 version 1.5.0 or higher

You can use `homebrew` to install the latest libssh2:
Expand Down Expand Up @@ -90,10 +89,11 @@ end
In order to run test suite you need to pull and run the following docker container:

```
$ docker pull tutum/ubuntu:trusty
$ docker run -d -p 2222:22 -e AUTHORIZED_KEYS="`cat ./spec/keys/id_rsa.pub`" tutum/ubuntu:trusty
docker compose up -d
```

Have a look at the docker-compose.yml file for configuration details

# License

MIT clause - see LICENSE for more details.
Expand Down
7 changes: 7 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
sshd:
image: testcontainers/sshd:1.2.0
environment:
PASSWORD: "somepassword"
ports:
- 10022:22
4 changes: 2 additions & 2 deletions examples/sftp.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ require "../src/ssh2"
SSH2::Session.open("localhost", 2222) do |session|
session.login_with_pubkey("root", "./spec/keys/id_rsa")
session.sftp_session do |sftp|
sftp.open_dir(".").ll do |fn|
puts fn
sftp.open_dir(".").ll do |file_name|
puts file_name
end
file = sftp.open(".bashrc")
puts file.read
Expand Down
16 changes: 8 additions & 8 deletions examples/shell.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@ require "../src/ssh2"

SSH2::Session.open("my_server") do |session|
session.login("username", "password")
session.open_session do |ch|
ch.request_pty("vt100")
ch.shell
session.open_session do |chan|
chan.request_pty("vt100")
chan.shell
session.blocking = false

buf_space = Bytes.new(1024)
buf = buf_space.to_slice
loop do
io = IO.select([STDIN, ch.socket]).first
io = IO.select([STDIN, chan.socket]).first
if io == STDIN
command = gets
if command
ch.write(command.to_slice)
chan.write(command.to_slice)
end
elsif io == ch.socket
len = ch.read(buf).to_i32
elsif io == chan.socket
len = chan.read(buf).to_i32
print! String.new buf[0, len]
break if ch.eof?
break if chan.eof?
end
end
end
Expand Down
3 changes: 1 addition & 2 deletions shard.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
name: ssh2
version: 1.6.1
crystal: ">= 0.36.1"
version: 1.7.0

libraries:
libssh2: ">= 1.11.0"
Expand Down
37 changes: 17 additions & 20 deletions spec/ssh2_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@ require "../src/ssh2"
require "spec"

SPEC_SSH_HOST = ENV["SPEC_SSH_HOST"]? || "localhost"
SPEC_SSH_PORT = ENV["CI"]? ? 22 : 2222
SPEC_SSH_PORT = ENV["CI"]? ? 22 : 10022

def connect_ssh
def connect_ssh(&)
SSH2::Session.open(SPEC_SSH_HOST, SPEC_SSH_PORT) do |session|
if ENV["CI"]?
session.login("root", "somepassword")
else
session.login_with_pubkey("root", "./spec/keys/id_rsa", "./spec/keys/id_rsa.pub")
end
session.login("root", "somepassword")
session.authenticated?.should be_true
yield session
end
Expand All @@ -30,6 +26,7 @@ describe SSH2 do

it "should be able to connect in interactive mode" do
SSH2::Session.open(SPEC_SSH_HOST, SPEC_SSH_PORT) do |session|
pending!("container doesn't support interactive login...")
session.interactive_login("root") { "somepassword" }

session.open_session do |channel|
Expand All @@ -51,16 +48,16 @@ describe SSH2 do
it "should be able to scp transfer file" do
fn = "#{Time.utc.to_unix}.txt"
connect_ssh do |session|
session.scp_send(fn, 0o0644, 12) do |ch|
ch.puts "hello world"
session.scp_send(fn, 0o0644, 12) do |chan|
chan.puts "hello world"
end
session.open_session do |ch|
ch.command("ls -l")
ch.gets_to_end.includes?(fn).should be_true
session.open_session do |chan|
chan.command("ls -l")
chan.gets_to_end.includes?(fn).should be_true
end
session.scp_recv(fn) do |ch, st|
buf = Slice(UInt8).new(st.st_size.to_i32)
ch.read(buf)
session.scp_recv(fn) do |chan, stat|
buf = Slice(UInt8).new(stat.st_size.to_i32)
chan.read(buf)
String.new(buf).should eq("hello world\n")
end
end
Expand Down Expand Up @@ -98,7 +95,7 @@ describe SSH2::KnownHosts do
known_hosts.size.should eq(2)
known_hosts.map(&.name).includes?(SPEC_SSH_HOST).should be_true
known_hosts.write_file("known_hosts")
known_hosts.delete_if { |h| h.name == SPEC_SSH_HOST }
known_hosts.delete_if { |host| host.name == SPEC_SSH_HOST }
known_hosts.size.should eq(1)
end

Expand All @@ -117,22 +114,22 @@ describe SSH2::SFTP do
it "should be able to list directory" do
connect_ssh do |ssh|
ssh.sftp_session do |sftp|
dir = sftp.open_dir(".")
dir = sftp.open_dir("/usr/bin/")
files = dir.ls
files.empty?.should be_false
files.includes?(".bashrc").should be_true
files.includes?("scp").should be_true
end
end
end

it "should be able to retrieve a file" do
connect_ssh do |ssh|
ssh.sftp_session do |sftp|
file = sftp.open(".bashrc")
file = sftp.open("/etc/resolv.conf")
attrs = file.fstat
attrs.atime.should be_a(Time)
attrs.permissions.to_s(8).should eq("100644")
file.gets_to_end.should match(/.bashrc/)
file.gets_to_end.should match(/nameserver/)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions src/agent.cr
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ class SSH2::Agent
raise SSH2Error.new "Failed to authenticate username #{username} with SSH agent"
end

def each
def each(&)
each_unsafe do |key|
yield PublicKey.new(
Slice.new(key.value.blob, key.value.blob_len),
String.new(key.value.comment))
end
end

private def each_unsafe
private def each_unsafe(&)
prev = Pointer(LibSSH2::AgentPublicKey).null
until LibSSH2.agent_get_identity(self, out store, prev) == 1
yield store
Expand Down
2 changes: 1 addition & 1 deletion src/channel.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class SSH2::Channel < IO
end

def socket
@session.socket.not_nil!
@session.socket.as(TCPSocket)
end

# Close an active data channel. In practice this means sending an
Expand Down
6 changes: 3 additions & 3 deletions src/known_hosts.cr
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class SSH2::KnownHosts
LibSSH2.knownhost_checkp(self, host, port, key, key.size.to_u64, typemask, out store)
end

def delete_if
def delete_if(&)
each_unsafe do |known_host|
if yield conv_to_host(known_host)
ret = LibSSH2.knownhost_del(self, known_host)
Expand All @@ -53,7 +53,7 @@ class SSH2::KnownHosts
check_error(ret)
end

def each
def each(&)
each_unsafe do |known_host|
yield conv_to_host(known_host)
end
Expand All @@ -65,7 +65,7 @@ class SSH2::KnownHosts
Host.new(name, key, known_host.value.typemask)
end

private def each_unsafe
private def each_unsafe(&)
prev = Pointer(LibSSH2::KnownHost).null
until LibSSH2.knownhost_get(self, out store, prev) == 1
yield store
Expand Down
7 changes: 5 additions & 2 deletions src/lib_ssh2.cr
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,11 @@ lib LibSSH2
fun session_supported_algs = libssh2_session_supported_algs(session : Session, type : MethodType, algs : UInt8***) : Int32

enum HashType
MD5 = 1
SHA1 = 2
MD5 = 1
SHA1 = 2
SHA256 = 3
# SHA384 = 4
# SHA512 = 5
end

fun hostkey_hash = libssh2_hostkey_hash(session : Session, type : HashType) : UInt8*
Expand Down
Loading
Loading