diff --git a/.github/workflows/e2e_pr.yaml b/.github/workflows/e2e_pr.yaml
new file mode 100644
index 0000000..d3f293f
--- /dev/null
+++ b/.github/workflows/e2e_pr.yaml
@@ -0,0 +1,57 @@
+name: CI for ssh-mapper
+on: [push, pull_request]
+
+jobs:
+ ssh-mapper-dropbear-server:
+ if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
+ runs-on: ubuntu-latest
+ # strategy:
+ # fail-fast: true
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Start learning DropbearSSH server
+ run: cd experiments/scripts/ && ./start_experiment.sh dropbear
+
+ - name: Verify Result
+ run: |
+ # wait for the learning to be over
+ while [ "$( docker container inspect -f '{{.State.Running}}' dropbear-learner )" = "true" ]; do date; echo "still learning"; sleep 5; done
+ experiments/scripts/diff_hyps.sh experiments/results/servers/dropbear experiments/orchestration/learner_output_dropbear 3
+
+ ssh-mapper-openssh7-server:
+ if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
+ runs-on: ubuntu-latest
+ # strategy:
+ # fail-fast: true
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Start learning OpenSSH7 server
+ run: cd experiments/scripts/ && ./start_experiment.sh openssh7
+
+ - name: Verify Result
+ run: |
+ # wait for the learning to be over
+ while [ "$( docker container inspect -f '{{.State.Running}}' openssh-learner7 )" = "true" ]; do date; echo "still learning"; sleep 5; done
+ experiments/scripts/diff_hyps.sh experiments/results/servers/openssh7 experiments/orchestration/learner_output_openssh7 3
+
+ ssh-mapper-openssh8-server:
+ if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
+ runs-on: ubuntu-latest
+ # strategy:
+ # fail-fast: true
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Start learning OpenSSH8 server
+ run: cd experiments/scripts/ && ./start_experiment.sh openssh8
+
+ - name: Verify Result
+ run: |
+ # wait for the learning to be over
+ while [ "$( docker container inspect -f '{{.State.Running}}' openssh-learner8 )" = "true" ]; do date; echo "still learning"; sleep 5; done
+ experiments/scripts/diff_hyps.sh experiments/results/servers/openssh8 experiments/orchestration/learner_output_openssh8 2
diff --git a/.gitignore b/.gitignore
index 8a982ce..48d1f6a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,4 +27,5 @@ ssh-mapper/paramiko.egg-info/**
ssh-mapper/build/**
ssh-mapper/dist/**
ssh-mapper/mapper/__pycache__/**
-ssh-learner/target/**
\ No newline at end of file
+ssh-learner/target/**
+__pycache__/
\ No newline at end of file
diff --git a/docker-compose.yaml b/docker-compose.yaml
deleted file mode 100644
index f30ea29..0000000
--- a/docker-compose.yaml
+++ /dev/null
@@ -1,51 +0,0 @@
-version: "3.8"
-
-services:
- # Dropbear service
- dropbear-ssh:
- build:
- context: .
- dockerfile: Dockerfile.dropbear
- container_name: dropbear-ssh
- ports:
- - "2222:22"
- networks:
- - fuzzer_network
- volumes:
- - ./ssh-keys:${HOME}/.ssh/:ro
-
- # SSH Mapper service
- ssh-mapper:
- build:
- context: ./ssh-mapper
- dockerfile: Dockerfile
- container_name: ssh-mapper
- ports:
- - "8080:8080"
- depends_on:
- - dropbear
- networks:
- - fuzzer_network
- volumes:
- - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro
- - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro
- command: -l 0.0.0.0:8080 -s dropbear-ssh:22 -f server
-
- # SSH Learner service
- ssh-learner:
- build:
- context: ./ssh-learner
- dockerfile: Dockerfile
- container_name: ssh-learner
- networks:
- - fuzzer_network
- depends_on:
- - dropbear
- - ssh-mapper
- volumes:
- - ./learner_output:/app/output_folder
- command: ["state-fuzzer-server", "-connect", "ssh-mapper:8080", "-alphabet", "/app/inputs/alphabets/servers/trans_auth.xml", "-ceReruns", "3", "-depth", "2", "-learningAlgorithm", "LSTAR", "-output", "/app/output_folder", "-ros", "-sshMapperAddress", "ssh-mapper:8080"]
-
-networks:
- fuzzer_network:
- driver: bridge
diff --git a/experiments/orchestration/docker-compose-dropbear.yaml b/experiments/orchestration/docker-compose-dropbear.yaml
new file mode 100644
index 0000000..ad9a510
--- /dev/null
+++ b/experiments/orchestration/docker-compose-dropbear.yaml
@@ -0,0 +1,52 @@
+version: "3.8"
+
+services:
+ dropbear-ssh:
+ build:
+ context: .
+ dockerfile: dockerfiles/Dockerfile.dropbear
+ container_name: dropbear-ssh
+ ports:
+ - "2222:22"
+ networks:
+ - dropbear_network
+ volumes:
+ - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro
+ - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro
+ entrypoint: ["sh", "-c", "cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && /usr/local/sbin/dropbear -F -E -j -k -s"]
+
+
+ dropbear-mapper:
+ build:
+ context: ../../ssh-mapper
+ dockerfile: Dockerfile
+ container_name: dropbear-mapper
+ # ports:
+ # - "8080:8080"
+ depends_on:
+ - dropbear-ssh
+ networks:
+ - dropbear_network
+ volumes:
+ - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro
+ - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro
+ command: -l 0.0.0.0:8080 -s dropbear-ssh:22 -f server
+
+ dropbear-learner:
+ build:
+ context: ../../ssh-learner
+ dockerfile: Dockerfile
+ container_name: dropbear-learner
+ networks:
+ - dropbear_network
+ depends_on:
+ - dropbear-ssh
+ - dropbear-mapper
+ volumes:
+ - ./learner_output_dropbear:/app/output_folder
+ - ../../ssh-learner/inputs/alphabets/servers/:/app/inputs/alphabets/servers/
+ command: ["state-fuzzer-server", "-connect", "dropbear-mapper:8080", "-alphabet", "/app/inputs/alphabets/servers/trans_auth.xml", "-output", "/app/output_folder", "-sshMapperAddress", "dropbear-mapper:8080", "-roundLimit", "3", "-debug"]
+
+networks:
+ dropbear_network:
+ driver: bridge
diff --git a/experiments/orchestration/docker-compose-openssh7.yaml b/experiments/orchestration/docker-compose-openssh7.yaml
new file mode 100644
index 0000000..5ea4ff6
--- /dev/null
+++ b/experiments/orchestration/docker-compose-openssh7.yaml
@@ -0,0 +1,52 @@
+version: "3.8"
+
+services:
+ openssh-server7:
+ build:
+ context: .
+ dockerfile: dockerfiles/Dockerfile.openssh7
+ container_name: openssh-server7
+ # ports:
+ # - "2222:22"
+ networks:
+ - openssh_network7
+ volumes:
+ - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro
+ - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro
+ entrypoint: ["sh", "-c", "cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && /usr/sbin/sshd -D -e"]
+
+
+ openssh-mapper7:
+ build:
+ context: ../../ssh-mapper
+ dockerfile: Dockerfile
+ container_name: openssh-mapper7
+ # ports:
+ # - "8080:8080"
+ depends_on:
+ - openssh-server7
+ networks:
+ - openssh_network7
+ volumes:
+ - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro
+ - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro
+ command: -l 0.0.0.0:8080 -s openssh-server7:22 -c OpenSSH -f server
+
+ openssh-learner7:
+ build:
+ context: ../../ssh-learner
+ dockerfile: Dockerfile
+ container_name: openssh-learner7
+ networks:
+ - openssh_network7
+ depends_on:
+ - openssh-server7
+ - openssh-mapper7
+ volumes:
+ - ./learner_output_openssh7:/app/output_folder
+ - ../../ssh-learner/inputs/alphabets/servers/:/app/inputs/alphabets/servers/
+ command: ["state-fuzzer-server", "-connect", "openssh-mapper7:8080", "-alphabet", "/app/inputs/alphabets/servers/trans_auth.xml", "-output", "/app/output_folder", "-sshMapperAddress", "openssh-mapper7:8080","-debug", "-roundLimit", "3"]
+
+networks:
+ openssh_network7:
+ driver: bridge
diff --git a/experiments/orchestration/docker-compose-openssh8.yaml b/experiments/orchestration/docker-compose-openssh8.yaml
new file mode 100644
index 0000000..598dcac
--- /dev/null
+++ b/experiments/orchestration/docker-compose-openssh8.yaml
@@ -0,0 +1,52 @@
+version: "3.8"
+
+services:
+ openssh-server8:
+ build:
+ context: .
+ dockerfile: dockerfiles/Dockerfile.openssh8
+ container_name: openssh-server8
+ # ports:
+ # - "2222:22"
+ networks:
+ - openssh_network8
+ volumes:
+ - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro
+ - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro
+ entrypoint: ["sh", "-c", "cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && /usr/sbin/sshd -D -e"]
+
+
+ openssh-mapper8:
+ build:
+ context: ../../ssh-mapper
+ dockerfile: Dockerfile
+ container_name: openssh-mapper8
+ # ports:
+ # - "8080:8080"
+ depends_on:
+ - openssh-server8
+ networks:
+ - openssh_network8
+ volumes:
+ - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro
+ - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro
+ command: -l 0.0.0.0:8080 -s openssh-server8:22 -c OpenSSH -f server
+
+ openssh-learner8:
+ build:
+ context: ../../ssh-learner
+ dockerfile: Dockerfile
+ container_name: openssh-learner8
+ networks:
+ - openssh_network8
+ depends_on:
+ - openssh-server8
+ - openssh-mapper8
+ volumes:
+ - ./learner_output_openssh8:/app/output_folder
+ - ../../ssh-learner/inputs/alphabets/servers/:/app/inputs/alphabets/servers/
+ command: ["state-fuzzer-server", "-connect", "openssh-mapper8:8080", "-alphabet", "/app/inputs/alphabets/servers/trans_auth.xml", "-output", "/app/output_folder", "-sshMapperAddress", "openssh-mapper8:8080","-debug", "-roundLimit", "3"]
+
+networks:
+ openssh_network8:
+ driver: bridge
diff --git a/Dockerfile.dropbear b/experiments/orchestration/dockerfiles/Dockerfile.dropbear
similarity index 93%
rename from Dockerfile.dropbear
rename to experiments/orchestration/dockerfiles/Dockerfile.dropbear
index 4b866a3..3d6422c 100644
--- a/Dockerfile.dropbear
+++ b/experiments/orchestration/dockerfiles/Dockerfile.dropbear
@@ -42,9 +42,7 @@ RUN dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key && \
# Set Dropbear server to run on port 22 (override in `docker run -p`)
EXPOSE 22
-COPY ssh-keys/learner-ssh.pub .
-
-RUN mkdir ~/.ssh; cat learner-ssh.pub >> ~/.ssh/authorized_keys
+RUN mkdir ~/.ssh; chmod 700 ~/.ssh
# Command to run Dropbear SSH server
CMD ["/usr/local/sbin/dropbear", "-F", "-E", "-j", "-k", "-s"]
diff --git a/experiments/orchestration/dockerfiles/Dockerfile.openssh7 b/experiments/orchestration/dockerfiles/Dockerfile.openssh7
new file mode 100644
index 0000000..97ee2b0
--- /dev/null
+++ b/experiments/orchestration/dockerfiles/Dockerfile.openssh7
@@ -0,0 +1,16 @@
+FROM ubuntu:bionic
+
+USER root
+
+RUN apt-get update && apt-get install -y systemd openssh-server sudo vim
+
+RUN mkdir /run/sshd
+
+RUN echo "LogLevel DEBUG3" >> /etc/ssh/sshd_config
+
+RUN echo "KexAlgorithms +curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" >> /etc/ssh/sshd_config && \
+ echo "PubkeyAcceptedKeyTypes=+ssh-rsa" >> /etc/ssh/sshd_config
+
+RUN systemctl enable ssh
+
+CMD ["/usr/sbin/sshd", "-D", "-e"]
diff --git a/experiments/orchestration/dockerfiles/Dockerfile.openssh8 b/experiments/orchestration/dockerfiles/Dockerfile.openssh8
new file mode 100644
index 0000000..f60427a
--- /dev/null
+++ b/experiments/orchestration/dockerfiles/Dockerfile.openssh8
@@ -0,0 +1,16 @@
+FROM ubuntu:focal
+
+USER root
+
+RUN apt-get update && apt-get install -y systemd openssh-server sudo vim
+
+RUN mkdir /run/sshd
+
+RUN echo "LogLevel DEBUG3" >> /etc/ssh/sshd_config
+
+RUN echo "KexAlgorithms +curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" >> /etc/ssh/sshd_config && \
+ echo "PubkeyAcceptedKeyTypes=+ssh-rsa" >> /etc/ssh/sshd_config
+
+RUN systemctl enable ssh
+
+CMD ["/usr/sbin/sshd", "-D", "-e"]
diff --git a/experiments/results/servers/dropbear/alphabet.xml b/experiments/results/servers/dropbear/alphabet.xml
new file mode 100644
index 0000000..92ea4e1
--- /dev/null
+++ b/experiments/results/servers/dropbear/alphabet.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experiments/results/servers/dropbear/command.args b/experiments/results/servers/dropbear/command.args
new file mode 100644
index 0000000..91964e8
--- /dev/null
+++ b/experiments/results/servers/dropbear/command.args
@@ -0,0 +1,11 @@
+state-fuzzer-server
+-connect
+ssh-mapper:8080
+-alphabet
+/app/inputs/alphabets/servers/trans_auth.xml
+-output
+/app/output_folder
+-sshMapperAddress
+ssh-mapper:8080
+-roundLimit
+3
diff --git a/experiments/results/servers/dropbear/hyp1.dot b/experiments/results/servers/dropbear/hyp1.dot
new file mode 100644
index 0000000..f56ec16
--- /dev/null
+++ b/experiments/results/servers/dropbear/hyp1.dot
@@ -0,0 +1,15 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s0 -> s0 [label="KEXINIT / KEXINIT"];
+ s0 -> s0 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="SR_AUTH / KEXINIT"];
+ s0 -> s0 [label="SR_CONN / KEXINIT"];
+ s0 -> s0 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s0 [label="UA_PK_NOK / KEXINIT"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/dropbear/hyp2.dot b/experiments/results/servers/dropbear/hyp2.dot
new file mode 100644
index 0000000..ca96235
--- /dev/null
+++ b/experiments/results/servers/dropbear/hyp2.dot
@@ -0,0 +1,39 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s2 [label="SR_AUTH / KEXINIT"];
+ s0 -> s2 [label="SR_CONN / KEXINIT"];
+ s0 -> s2 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s2 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s2 [label="KEXINIT / NO_CONN"];
+ s1 -> s3 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s2 [label="SR_AUTH / NO_CONN"];
+ s1 -> s2 [label="SR_CONN / NO_CONN"];
+ s1 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / NO_CONN"];
+ s2 -> s2 [label="KEX30 / NO_CONN"];
+ s2 -> s2 [label="NEWKEYS / NO_CONN"];
+ s2 -> s2 [label="SR_AUTH / NO_CONN"];
+ s2 -> s2 [label="SR_CONN / NO_CONN"];
+ s2 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s3 -> s2 [label="KEXINIT / NO_CONN"];
+ s3 -> s3 [label="KEX30 / UNIMPL"];
+ s3 -> s0 [label="NEWKEYS / NO_RESP"];
+ s3 -> s2 [label="SR_AUTH / NO_CONN"];
+ s3 -> s2 [label="SR_CONN / NO_CONN"];
+ s3 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s3 -> s2 [label="UA_PK_NOK / NO_CONN"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/dropbear/hyp3.dot b/experiments/results/servers/dropbear/hyp3.dot
new file mode 100644
index 0000000..87c75d9
--- /dev/null
+++ b/experiments/results/servers/dropbear/hyp3.dot
@@ -0,0 +1,55 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s4 [shape="circle" label="s4"];
+ s5 [shape="circle" label="s5"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s2 [label="SR_AUTH / KEXINIT"];
+ s0 -> s2 [label="SR_CONN / KEXINIT"];
+ s0 -> s2 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s2 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s2 [label="KEXINIT / NO_CONN"];
+ s1 -> s3 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s2 [label="SR_AUTH / NO_CONN"];
+ s1 -> s2 [label="SR_CONN / NO_CONN"];
+ s1 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / NO_CONN"];
+ s2 -> s2 [label="KEX30 / NO_CONN"];
+ s2 -> s2 [label="NEWKEYS / NO_CONN"];
+ s2 -> s2 [label="SR_AUTH / NO_CONN"];
+ s2 -> s2 [label="SR_CONN / NO_CONN"];
+ s2 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s3 -> s2 [label="KEXINIT / NO_CONN"];
+ s3 -> s3 [label="KEX30 / UNIMPL"];
+ s3 -> s4 [label="NEWKEYS / NO_RESP"];
+ s3 -> s2 [label="SR_AUTH / NO_CONN"];
+ s3 -> s2 [label="SR_CONN / NO_CONN"];
+ s3 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s3 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s4 -> s5 [label="KEXINIT / KEXINIT"];
+ s4 -> s2 [label="KEX30 / NO_CONN"];
+ s4 -> s2 [label="NEWKEYS / NO_CONN"];
+ s4 -> s4 [label="SR_AUTH / SR_ACCEPT"];
+ s4 -> s2 [label="SR_CONN / NO_CONN"];
+ s4 -> s4 [label="UA_PK_OK / UA_FAILURE"];
+ s4 -> s4 [label="UA_PK_NOK / UA_FAILURE"];
+ s5 -> s2 [label="KEXINIT / NO_CONN"];
+ s5 -> s3 [label="KEX30 / KEX31+NEWKEYS"];
+ s5 -> s2 [label="NEWKEYS / UNIMPL"];
+ s5 -> s2 [label="SR_AUTH / NO_CONN"];
+ s5 -> s2 [label="SR_CONN / NO_CONN"];
+ s5 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s5 -> s2 [label="UA_PK_NOK / NO_CONN"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/dropbear/learnedModel.dot b/experiments/results/servers/dropbear/learnedModel.dot
new file mode 100644
index 0000000..87c75d9
--- /dev/null
+++ b/experiments/results/servers/dropbear/learnedModel.dot
@@ -0,0 +1,55 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s4 [shape="circle" label="s4"];
+ s5 [shape="circle" label="s5"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s2 [label="SR_AUTH / KEXINIT"];
+ s0 -> s2 [label="SR_CONN / KEXINIT"];
+ s0 -> s2 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s2 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s2 [label="KEXINIT / NO_CONN"];
+ s1 -> s3 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s2 [label="SR_AUTH / NO_CONN"];
+ s1 -> s2 [label="SR_CONN / NO_CONN"];
+ s1 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / NO_CONN"];
+ s2 -> s2 [label="KEX30 / NO_CONN"];
+ s2 -> s2 [label="NEWKEYS / NO_CONN"];
+ s2 -> s2 [label="SR_AUTH / NO_CONN"];
+ s2 -> s2 [label="SR_CONN / NO_CONN"];
+ s2 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s3 -> s2 [label="KEXINIT / NO_CONN"];
+ s3 -> s3 [label="KEX30 / UNIMPL"];
+ s3 -> s4 [label="NEWKEYS / NO_RESP"];
+ s3 -> s2 [label="SR_AUTH / NO_CONN"];
+ s3 -> s2 [label="SR_CONN / NO_CONN"];
+ s3 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s3 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s4 -> s5 [label="KEXINIT / KEXINIT"];
+ s4 -> s2 [label="KEX30 / NO_CONN"];
+ s4 -> s2 [label="NEWKEYS / NO_CONN"];
+ s4 -> s4 [label="SR_AUTH / SR_ACCEPT"];
+ s4 -> s2 [label="SR_CONN / NO_CONN"];
+ s4 -> s4 [label="UA_PK_OK / UA_FAILURE"];
+ s4 -> s4 [label="UA_PK_NOK / UA_FAILURE"];
+ s5 -> s2 [label="KEXINIT / NO_CONN"];
+ s5 -> s3 [label="KEX30 / KEX31+NEWKEYS"];
+ s5 -> s2 [label="NEWKEYS / UNIMPL"];
+ s5 -> s2 [label="SR_AUTH / NO_CONN"];
+ s5 -> s2 [label="SR_CONN / NO_CONN"];
+ s5 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s5 -> s2 [label="UA_PK_NOK / NO_CONN"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/dropbear/statistics.txt b/experiments/results/servers/dropbear/statistics.txt
new file mode 100644
index 0000000..f866c84
--- /dev/null
+++ b/experiments/results/servers/dropbear/statistics.txt
@@ -0,0 +1,89 @@
+=== RUN DESCRIPTION ===
+Alphabet: [KEXINIT, KEX30, NEWKEYS, SR_AUTH, SR_CONN, UA_PK_OK, UA_PK_NOK]
+
+StateFuzzerConfig Parameters
+Help: false
+Debug: false
+Quiet: false
+Output Directory: /app/output_folder
+Fuzzing Client: false
+
+LearnerConfig Parameters
+Alphabet: /app/inputs/alphabets/servers/trans_auth.xml
+Learning Algorithm: TTT
+Equivalence Algorithms: [RANDOM_WP_METHOD]
+Max Depth: 1
+Min Length: 5
+Max Length: 15
+Max Equivalence Queries: 1000
+Runs Per Membership Query: 1
+Random Length: 5
+Membership Query Retries: 3
+Log Queries: false
+Prob Reset: 0.0
+Test File: null
+Seed: 0
+Cache Tests: false
+Ce Sanitization: true
+Skip Non Det Tests: false
+Ce Reruns: 3
+Probabilistic Sanitization: true
+Time Limit: null
+Test Limit: null
+Round Limit: 3
+IOMode: true
+Probability of Choosing a New DataValue: 0.1
+Max Runs: 1
+Max Depth for Register Automata: 1
+Reset Runs: true
+Seed transitions: true
+Draw symbols uniformly: true
+
+SulConfig Parameters
+Fuzzing Role: client
+Fuzzing Client: true
+Response Wait: 100
+Input Response Timeout: null
+Command: null
+Terminate Command: null
+Process Dir: null
+Redirect Output Streams: false
+Process Trigger: NEW_TEST
+Start Wait: 0
+
+SulServerConfigStandard Parameters
+Connect to: ssh-mapper:8080
+
+MapperConfig Parameters
+Mapper Connection Config: null
+Repeating Outputs: null
+Socket Closed as Timeout: false
+Disabled as Timeout: false
+Merge Repeating: true
+
+SulAdapterConfig Parameters
+Adapter Port: null
+Adapter Address: localhost
+
+=== STATISTICS ===
+Learning finished: false
+Reason: hypothesis construction round limit reached
+Size of the input alphabet: 7
+Number of states: 6
+Number of hypotheses: 3
+Number of inputs: 584
+Number of tests: 130
+Number of learning inputs: 428
+Number of learning tests: 116
+Number of inputs up to last hypothesis: 584
+Number of tests up to last hypothesis: 130
+Time (ms) to learn model: 833275
+Counterexamples:
+CE 1:Query[ε|NEWKEYS SR_CONN NEWKEYS SR_CONN KEXINIT UA_PK_NOK NEWKEYS SR_CONN KEXINIT KEX30 SR_CONN / KEXINIT+UNIMPL NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN]
+CE 2:Query[ε|KEXINIT KEX30 NEWKEYS KEX30 UA_PK_NOK SR_CONN SR_AUTH SR_AUTH KEX30 / KEXINIT KEX31+NEWKEYS+BUFFERED NO_RESP NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN]
+Number of inputs when hypothesis was generated: [7, 269, 584]
+Number of tests when hypothesis was generated: [7, 81, 130]
+Time (ms) when hypothesis was generated: [13198, 334418, 833271]
+Number of inputs when counterexample was found: [51, 381]
+Number of tests when counterexample was found: [11, 91]
+Time (ms) when counterexample was found: [33044, 414891]
diff --git a/experiments/results/servers/openssh7/alphabet.xml b/experiments/results/servers/openssh7/alphabet.xml
new file mode 100644
index 0000000..92ea4e1
--- /dev/null
+++ b/experiments/results/servers/openssh7/alphabet.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experiments/results/servers/openssh7/command.args b/experiments/results/servers/openssh7/command.args
new file mode 100644
index 0000000..f280f2f
--- /dev/null
+++ b/experiments/results/servers/openssh7/command.args
@@ -0,0 +1,12 @@
+state-fuzzer-server
+-connect
+openssh-mapper7:8080
+-alphabet
+/app/inputs/alphabets/servers/trans_auth.xml
+-output
+/app/output_folder
+-sshMapperAddress
+openssh-mapper7:8080
+-debug
+-roundLimit
+3
diff --git a/experiments/results/servers/openssh7/error.msg b/experiments/results/servers/openssh7/error.msg
new file mode 100644
index 0000000..042f5fe
--- /dev/null
+++ b/experiments/results/servers/openssh7/error.msg
@@ -0,0 +1,21 @@
+Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null
+java.lang.NullPointerException: Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null
+ at com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.hashCode(AbstractOutput.java:218)
+ at net.automatalib.word.Word.hashCode(Word.java:242)
+ at java.base/java.util.HashMap.hash(HashMap.java:338)
+ at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1191)
+ at de.learnlib.datastructure.discriminationtree.SplitData.getIncoming(SplitData.java:110)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.prepareSplit(AbstractTTTLearner.java:624)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.finalizeDiscriminator(AbstractTTTLearner.java:554)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.finalizeAny(AbstractTTTLearner.java:305)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.refineHypothesisSingle(AbstractTTTLearner.java:215)
+ at de.learnlib.algorithm.ttt.mealy.TTTLearnerMealy.refineHypothesisSingle(TTTLearnerMealy.java:67)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.refineHypothesis(AbstractTTTLearner.java:163)
+ at com.github.protocolfuzzing.protocolstatefuzzer.statefuzzer.core.StateFuzzerStandard.inferStateMachine(StateFuzzerStandard.java:164)
+ at com.github.protocolfuzzing.protocolstatefuzzer.statefuzzer.core.StateFuzzerStandard.startFuzzing(StateFuzzerStandard.java:84)
+ at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.executeCommand(CommandLineParser.java:355)
+ at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parseAndExecuteCommand(CommandLineParser.java:226)
+ at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parse(CommandLineParser.java:168)
+ at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parse(CommandLineParser.java:212)
+ at learner.Main.runMealyLearner(Main.java:32)
+ at learner.Main.main(Main.java:21)
diff --git a/experiments/results/servers/openssh7/hyp1.dot b/experiments/results/servers/openssh7/hyp1.dot
new file mode 100644
index 0000000..99bfa7f
--- /dev/null
+++ b/experiments/results/servers/openssh7/hyp1.dot
@@ -0,0 +1,15 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s0 -> s0 [label="KEXINIT / KEXINIT"];
+ s0 -> s0 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="SR_AUTH / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="SR_CONN / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s0 [label="UA_PK_NOK / KEXINIT"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/openssh7/hyp2.dot b/experiments/results/servers/openssh7/hyp2.dot
new file mode 100644
index 0000000..cfb4db3
--- /dev/null
+++ b/experiments/results/servers/openssh7/hyp2.dot
@@ -0,0 +1,39 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"];
+ s0 -> s3 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s3 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s3 [label="KEXINIT / NO_CONN"];
+ s1 -> s2 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s1 [label="SR_AUTH / UNIMPL"];
+ s1 -> s1 [label="SR_CONN / UNIMPL"];
+ s1 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s3 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / UNIMPL"];
+ s2 -> s2 [label="KEX30 / UNIMPL"];
+ s2 -> s2 [label="NEWKEYS / NO_RESP"];
+ s2 -> s2 [label="SR_AUTH / UNIMPL"];
+ s2 -> s2 [label="SR_CONN / UNIMPL"];
+ s2 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s3 [label="UA_PK_NOK / NO_CONN"];
+ s3 -> s3 [label="KEXINIT / NO_CONN"];
+ s3 -> s3 [label="KEX30 / NO_CONN"];
+ s3 -> s3 [label="NEWKEYS / NO_CONN"];
+ s3 -> s3 [label="SR_AUTH / NO_CONN"];
+ s3 -> s3 [label="SR_CONN / NO_CONN"];
+ s3 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s3 -> s3 [label="UA_PK_NOK / NO_CONN"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/openssh7/hyp3.dot b/experiments/results/servers/openssh7/hyp3.dot
new file mode 100644
index 0000000..942e677
--- /dev/null
+++ b/experiments/results/servers/openssh7/hyp3.dot
@@ -0,0 +1,47 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s4 [shape="circle" label="s4"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"];
+ s0 -> s3 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s3 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s3 [label="KEXINIT / NO_CONN"];
+ s1 -> s2 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s1 [label="SR_AUTH / UNIMPL"];
+ s1 -> s1 [label="SR_CONN / UNIMPL"];
+ s1 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s3 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / UNIMPL"];
+ s2 -> s2 [label="KEX30 / UNIMPL"];
+ s2 -> s4 [label="NEWKEYS / NO_RESP"];
+ s2 -> s2 [label="SR_AUTH / UNIMPL"];
+ s2 -> s2 [label="SR_CONN / UNIMPL"];
+ s2 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s3 [label="UA_PK_NOK / NO_CONN"];
+ s3 -> s3 [label="KEXINIT / NO_CONN"];
+ s3 -> s3 [label="KEX30 / NO_CONN"];
+ s3 -> s3 [label="NEWKEYS / NO_CONN"];
+ s3 -> s3 [label="SR_AUTH / NO_CONN"];
+ s3 -> s3 [label="SR_CONN / NO_CONN"];
+ s3 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s3 -> s3 [label="UA_PK_NOK / NO_CONN"];
+ s4 -> s4 [label="KEXINIT / UNIMPL"];
+ s4 -> s4 [label="KEX30 / UNIMPL"];
+ s4 -> s3 [label="NEWKEYS / UNIMPL"];
+ s4 -> s4 [label="SR_AUTH / SR_ACCEPT"];
+ s4 -> s3 [label="SR_CONN / DISCONNECT"];
+ s4 -> s4 [label="UA_PK_OK / UNIMPL"];
+ s4 -> s4 [label="UA_PK_NOK / UNIMPL"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/openssh7/learnedModel.dot b/experiments/results/servers/openssh7/learnedModel.dot
new file mode 100644
index 0000000..942e677
--- /dev/null
+++ b/experiments/results/servers/openssh7/learnedModel.dot
@@ -0,0 +1,47 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s4 [shape="circle" label="s4"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"];
+ s0 -> s3 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s3 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s3 [label="KEXINIT / NO_CONN"];
+ s1 -> s2 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s1 [label="SR_AUTH / UNIMPL"];
+ s1 -> s1 [label="SR_CONN / UNIMPL"];
+ s1 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s3 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / UNIMPL"];
+ s2 -> s2 [label="KEX30 / UNIMPL"];
+ s2 -> s4 [label="NEWKEYS / NO_RESP"];
+ s2 -> s2 [label="SR_AUTH / UNIMPL"];
+ s2 -> s2 [label="SR_CONN / UNIMPL"];
+ s2 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s3 [label="UA_PK_NOK / NO_CONN"];
+ s3 -> s3 [label="KEXINIT / NO_CONN"];
+ s3 -> s3 [label="KEX30 / NO_CONN"];
+ s3 -> s3 [label="NEWKEYS / NO_CONN"];
+ s3 -> s3 [label="SR_AUTH / NO_CONN"];
+ s3 -> s3 [label="SR_CONN / NO_CONN"];
+ s3 -> s3 [label="UA_PK_OK / NO_CONN"];
+ s3 -> s3 [label="UA_PK_NOK / NO_CONN"];
+ s4 -> s4 [label="KEXINIT / UNIMPL"];
+ s4 -> s4 [label="KEX30 / UNIMPL"];
+ s4 -> s3 [label="NEWKEYS / UNIMPL"];
+ s4 -> s4 [label="SR_AUTH / SR_ACCEPT"];
+ s4 -> s3 [label="SR_CONN / DISCONNECT"];
+ s4 -> s4 [label="UA_PK_OK / UNIMPL"];
+ s4 -> s4 [label="UA_PK_NOK / UNIMPL"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/openssh7/statistics.txt b/experiments/results/servers/openssh7/statistics.txt
new file mode 100644
index 0000000..a3c07be
--- /dev/null
+++ b/experiments/results/servers/openssh7/statistics.txt
@@ -0,0 +1,89 @@
+=== RUN DESCRIPTION ===
+Alphabet: [KEXINIT, KEX30, NEWKEYS, SR_AUTH, SR_CONN, UA_PK_OK, UA_PK_NOK]
+
+StateFuzzerConfig Parameters
+Help: false
+Debug: true
+Quiet: false
+Output Directory: /app/output_folder
+Fuzzing Client: false
+
+LearnerConfig Parameters
+Alphabet: /app/inputs/alphabets/servers/trans_auth.xml
+Learning Algorithm: TTT
+Equivalence Algorithms: [RANDOM_WP_METHOD]
+Max Depth: 1
+Min Length: 5
+Max Length: 15
+Max Equivalence Queries: 1000
+Runs Per Membership Query: 1
+Random Length: 5
+Membership Query Retries: 3
+Log Queries: false
+Prob Reset: 0.0
+Test File: null
+Seed: 0
+Cache Tests: false
+Ce Sanitization: true
+Skip Non Det Tests: false
+Ce Reruns: 3
+Probabilistic Sanitization: true
+Time Limit: null
+Test Limit: null
+Round Limit: 3
+IOMode: true
+Probability of Choosing a New DataValue: 0.1
+Max Runs: 1
+Max Depth for Register Automata: 1
+Reset Runs: true
+Seed transitions: true
+Draw symbols uniformly: true
+
+SulConfig Parameters
+Fuzzing Role: client
+Fuzzing Client: true
+Response Wait: 100
+Input Response Timeout: null
+Command: null
+Terminate Command: null
+Process Dir: null
+Redirect Output Streams: false
+Process Trigger: NEW_TEST
+Start Wait: 0
+
+SulServerConfigStandard Parameters
+Connect to: openssh-mapper7:8080
+
+MapperConfig Parameters
+Mapper Connection Config: null
+Repeating Outputs: null
+Socket Closed as Timeout: false
+Disabled as Timeout: false
+Merge Repeating: true
+
+SulAdapterConfig Parameters
+Adapter Port: null
+Adapter Address: localhost
+
+=== STATISTICS ===
+Learning finished: false
+Reason: hypothesis construction round limit reached
+Size of the input alphabet: 7
+Number of states: 5
+Number of hypotheses: 3
+Number of inputs: 412
+Number of tests: 107
+Number of learning inputs: 328
+Number of learning tests: 99
+Number of inputs up to last hypothesis: 412
+Number of tests up to last hypothesis: 107
+Time (ms) to learn model: 706559
+Counterexamples:
+CE 1:Query[ε|NEWKEYS SR_CONN NEWKEYS SR_CONN KEXINIT UA_PK_NOK NEWKEYS SR_CONN KEXINIT KEX30 SR_CONN / KEXINIT+UNIMPL UNIMPL UNIMPL UNIMPL NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN]
+CE 2:Query[ε|KEXINIT KEX30 NEWKEYS SR_CONN KEXINIT SR_AUTH KEXINIT KEX30 SR_CONN KEXINIT / KEXINIT KEX31+NEWKEYS+BUFFERED NO_RESP DISCONNECT NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN]
+Number of inputs when hypothesis was generated: [7, 262, 412]
+Number of tests when hypothesis was generated: [7, 79, 107]
+Time (ms) when hypothesis was generated: [15107, 392539, 706550]
+Number of inputs when counterexample was found: [51, 302]
+Number of tests when counterexample was found: [11, 83]
+Time (ms) when counterexample was found: [57282, 436913]
diff --git a/experiments/results/servers/openssh8/alphabet.xml b/experiments/results/servers/openssh8/alphabet.xml
new file mode 100644
index 0000000..92ea4e1
--- /dev/null
+++ b/experiments/results/servers/openssh8/alphabet.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experiments/results/servers/openssh8/command.args b/experiments/results/servers/openssh8/command.args
new file mode 100644
index 0000000..b176dfe
--- /dev/null
+++ b/experiments/results/servers/openssh8/command.args
@@ -0,0 +1,12 @@
+state-fuzzer-server
+-connect
+openssh-mapper8:8080
+-alphabet
+/app/inputs/alphabets/servers/trans_auth.xml
+-output
+/app/output_folder
+-sshMapperAddress
+openssh-mapper8:8080
+-debug
+-roundLimit
+3
diff --git a/experiments/results/servers/openssh8/error.msg b/experiments/results/servers/openssh8/error.msg
new file mode 100644
index 0000000..042f5fe
--- /dev/null
+++ b/experiments/results/servers/openssh8/error.msg
@@ -0,0 +1,21 @@
+Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null
+java.lang.NullPointerException: Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null
+ at com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.hashCode(AbstractOutput.java:218)
+ at net.automatalib.word.Word.hashCode(Word.java:242)
+ at java.base/java.util.HashMap.hash(HashMap.java:338)
+ at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1191)
+ at de.learnlib.datastructure.discriminationtree.SplitData.getIncoming(SplitData.java:110)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.prepareSplit(AbstractTTTLearner.java:624)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.finalizeDiscriminator(AbstractTTTLearner.java:554)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.finalizeAny(AbstractTTTLearner.java:305)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.refineHypothesisSingle(AbstractTTTLearner.java:215)
+ at de.learnlib.algorithm.ttt.mealy.TTTLearnerMealy.refineHypothesisSingle(TTTLearnerMealy.java:67)
+ at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.refineHypothesis(AbstractTTTLearner.java:163)
+ at com.github.protocolfuzzing.protocolstatefuzzer.statefuzzer.core.StateFuzzerStandard.inferStateMachine(StateFuzzerStandard.java:164)
+ at com.github.protocolfuzzing.protocolstatefuzzer.statefuzzer.core.StateFuzzerStandard.startFuzzing(StateFuzzerStandard.java:84)
+ at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.executeCommand(CommandLineParser.java:355)
+ at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parseAndExecuteCommand(CommandLineParser.java:226)
+ at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parse(CommandLineParser.java:168)
+ at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parse(CommandLineParser.java:212)
+ at learner.Main.runMealyLearner(Main.java:32)
+ at learner.Main.main(Main.java:21)
diff --git a/experiments/results/servers/openssh8/hyp1.dot b/experiments/results/servers/openssh8/hyp1.dot
new file mode 100644
index 0000000..99bfa7f
--- /dev/null
+++ b/experiments/results/servers/openssh8/hyp1.dot
@@ -0,0 +1,15 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s0 -> s0 [label="KEXINIT / KEXINIT"];
+ s0 -> s0 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="SR_AUTH / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="SR_CONN / KEXINIT+UNIMPL"];
+ s0 -> s0 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s0 [label="UA_PK_NOK / KEXINIT"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/openssh8/hyp2.dot b/experiments/results/servers/openssh8/hyp2.dot
new file mode 100644
index 0000000..4e505b7
--- /dev/null
+++ b/experiments/results/servers/openssh8/hyp2.dot
@@ -0,0 +1,31 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"];
+ s0 -> s2 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s2 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s1 [label="KEXINIT / UNIMPL"];
+ s1 -> s1 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s1 [label="SR_AUTH / UNIMPL"];
+ s1 -> s1 [label="SR_CONN / UNIMPL"];
+ s1 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / NO_CONN"];
+ s2 -> s2 [label="KEX30 / NO_CONN"];
+ s2 -> s2 [label="NEWKEYS / NO_CONN"];
+ s2 -> s2 [label="SR_AUTH / NO_CONN"];
+ s2 -> s2 [label="SR_CONN / NO_CONN"];
+ s2 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s2 [label="UA_PK_NOK / NO_CONN"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/openssh8/hyp3.dot b/experiments/results/servers/openssh8/hyp3.dot
new file mode 100644
index 0000000..732715e
--- /dev/null
+++ b/experiments/results/servers/openssh8/hyp3.dot
@@ -0,0 +1,79 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s4 [shape="circle" label="s4"];
+ s5 [shape="circle" label="s5"];
+ s6 [shape="circle" label="s6"];
+ s7 [shape="circle" label="s7"];
+ s8 [shape="circle" label="s8"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"];
+ s0 -> s2 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s2 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s4 [label="KEXINIT / UNIMPL"];
+ s1 -> s3 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s1 [label="SR_AUTH / UNIMPL"];
+ s1 -> s1 [label="SR_CONN / UNIMPL"];
+ s1 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / NO_CONN"];
+ s2 -> s2 [label="KEX30 / NO_CONN"];
+ s2 -> s2 [label="NEWKEYS / NO_CONN"];
+ s2 -> s2 [label="SR_AUTH / NO_CONN"];
+ s2 -> s2 [label="SR_CONN / NO_CONN"];
+ s2 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s3 -> s3 [label="KEXINIT / UNIMPL"];
+ s3 -> s3 [label="KEX30 / UNIMPL"];
+ s3 -> s6 [label="NEWKEYS / NO_RESP"];
+ s3 -> s3 [label="SR_AUTH / UNIMPL"];
+ s3 -> s3 [label="SR_CONN / UNIMPL"];
+ s3 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s3 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s4 -> s4 [label="KEXINIT / UNIMPL"];
+ s4 -> s5 [label="KEX30 / KEX31+NEWKEYS"];
+ s4 -> s4 [label="NEWKEYS / UNIMPL"];
+ s4 -> s4 [label="SR_AUTH / UNIMPL"];
+ s4 -> s4 [label="SR_CONN / UNIMPL"];
+ s4 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s4 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s5 -> s5 [label="KEXINIT / NO_RESP"];
+ s5 -> s5 [label="KEX30 / NO_RESP"];
+ s5 -> s2 [label="NEWKEYS / NO_RESP"];
+ s5 -> s5 [label="SR_AUTH / NO_RESP"];
+ s5 -> s5 [label="SR_CONN / NO_RESP"];
+ s5 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s5 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s6 -> s6 [label="KEXINIT / UNIMPL"];
+ s6 -> s6 [label="KEX30 / UNIMPL"];
+ s6 -> s2 [label="NEWKEYS / UNIMPL"];
+ s6 -> s7 [label="SR_AUTH / SR_ACCEPT"];
+ s6 -> s2 [label="SR_CONN / DISCONNECT"];
+ s6 -> s6 [label="UA_PK_OK / UNIMPL"];
+ s6 -> s6 [label="UA_PK_NOK / UNIMPL"];
+ s7 -> s7 [label="KEXINIT / UNIMPL"];
+ s7 -> s7 [label="KEX30 / UNIMPL"];
+ s7 -> s2 [label="NEWKEYS / UNIMPL"];
+ s7 -> s7 [label="SR_AUTH / SR_ACCEPT"];
+ s7 -> s2 [label="SR_CONN / DISCONNECT"];
+ s7 -> s7 [label="UA_PK_OK / UA_FAILURE"];
+ s7 -> s8 [label="UA_PK_NOK / UA_FAILURE"];
+ s8 -> s8 [label="KEXINIT / UNIMPL"];
+ s8 -> s8 [label="KEX30 / UNIMPL"];
+ s8 -> s2 [label="NEWKEYS / UNIMPL"];
+ s8 -> s8 [label="SR_AUTH / SR_ACCEPT"];
+ s8 -> s2 [label="SR_CONN / DISCONNECT"];
+ s8 -> s2 [label="UA_PK_OK / DISCONNECT"];
+ s8 -> s8 [label="UA_PK_NOK / UA_FAILURE"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/openssh8/learnedModel.dot b/experiments/results/servers/openssh8/learnedModel.dot
new file mode 100644
index 0000000..8c77c41
--- /dev/null
+++ b/experiments/results/servers/openssh8/learnedModel.dot
@@ -0,0 +1,31 @@
+digraph g {
+
+ s0 [shape="circle" label="0"];
+ s1 [shape="circle" label="1"];
+ s2 [shape="circle" label="2"];
+ s0 -> s1 [label="KEXINIT / KEXINIT"];
+ s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"];
+ s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"];
+ s0 -> s2 [label="UA_PK_OK / KEXINIT"];
+ s0 -> s2 [label="UA_PK_NOK / KEXINIT"];
+ s1 -> s1 [label="KEXINIT / UNIMPL"];
+ s1 -> s1 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"];
+ s1 -> s1 [label="NEWKEYS / UNIMPL"];
+ s1 -> s1 [label="SR_AUTH / UNIMPL"];
+ s1 -> s1 [label="SR_CONN / UNIMPL"];
+ s1 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s1 -> s2 [label="UA_PK_NOK / NO_CONN"];
+ s2 -> s2 [label="KEXINIT / NO_CONN"];
+ s2 -> s2 [label="KEX30 / NO_CONN"];
+ s2 -> s2 [label="NEWKEYS / NO_CONN"];
+ s2 -> s2 [label="SR_AUTH / NO_CONN"];
+ s2 -> s2 [label="SR_CONN / NO_CONN"];
+ s2 -> s2 [label="UA_PK_OK / NO_CONN"];
+ s2 -> s2 [label="UA_PK_NOK / NO_CONN"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/results/servers/openssh8/statistics.txt b/experiments/results/servers/openssh8/statistics.txt
new file mode 100644
index 0000000..7f32be3
--- /dev/null
+++ b/experiments/results/servers/openssh8/statistics.txt
@@ -0,0 +1,89 @@
+=== RUN DESCRIPTION ===
+Alphabet: [KEXINIT, KEX30, NEWKEYS, SR_AUTH, SR_CONN, UA_PK_OK, UA_PK_NOK]
+
+StateFuzzerConfig Parameters
+Help: false
+Debug: true
+Quiet: false
+Output Directory: /app/output_folder
+Fuzzing Client: false
+
+LearnerConfig Parameters
+Alphabet: /app/inputs/alphabets/servers/trans_auth.xml
+Learning Algorithm: TTT
+Equivalence Algorithms: [RANDOM_WP_METHOD]
+Max Depth: 1
+Min Length: 5
+Max Length: 15
+Max Equivalence Queries: 1000
+Runs Per Membership Query: 1
+Random Length: 5
+Membership Query Retries: 3
+Log Queries: false
+Prob Reset: 0.0
+Test File: null
+Seed: 0
+Cache Tests: false
+Ce Sanitization: true
+Skip Non Det Tests: false
+Ce Reruns: 3
+Probabilistic Sanitization: true
+Time Limit: null
+Test Limit: null
+Round Limit: 3
+IOMode: true
+Probability of Choosing a New DataValue: 0.1
+Max Runs: 1
+Max Depth for Register Automata: 1
+Reset Runs: true
+Seed transitions: true
+Draw symbols uniformly: true
+
+SulConfig Parameters
+Fuzzing Role: client
+Fuzzing Client: true
+Response Wait: 100
+Input Response Timeout: null
+Command: null
+Terminate Command: null
+Process Dir: null
+Redirect Output Streams: false
+Process Trigger: NEW_TEST
+Start Wait: 0
+
+SulServerConfigStandard Parameters
+Connect to: openssh-mapper8:8080
+
+MapperConfig Parameters
+Mapper Connection Config: null
+Repeating Outputs: null
+Socket Closed as Timeout: false
+Disabled as Timeout: false
+Merge Repeating: true
+
+SulAdapterConfig Parameters
+Adapter Port: null
+Adapter Address: localhost
+
+=== STATISTICS ===
+Learning finished: false
+Reason: Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null
+Size of the input alphabet: 7
+Number of states: 3
+Number of hypotheses: 2
+Number of inputs: 300
+Number of tests: 78
+Number of learning inputs: 87
+Number of learning tests: 40
+Number of inputs up to last hypothesis: 131
+Number of tests up to last hypothesis: 44
+Time (ms) to learn model: 528199
+Counterexamples:
+CE 1:Query[ε|NEWKEYS SR_CONN NEWKEYS SR_CONN KEXINIT UA_PK_NOK NEWKEYS SR_CONN KEXINIT KEX30 SR_CONN / KEXINIT+UNIMPL UNIMPL UNIMPL UNIMPL UNIMPL NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN]
+CE 2:Query[ε|KEX30 NEWKEYS KEX30 NEWKEYS UA_PK_NOK SR_AUTH UA_PK_NOK SR_AUTH UA_PK_NOK NEWKEYS UA_PK_NOK KEXINIT / KEXINIT+UNIMPL UNIMPL KEX31+NEWKEYS+BUFFERED NO_RESP UNIMPL SR_ACCEPT UA_FAILURE SR_ACCEPT UA_FAILURE UNIMPL NO_CONN NO_CONN]
+Number of inputs when hypothesis was generated: [7, 131]
+Number of tests when hypothesis was generated: [7, 44]
+Time (ms) when hypothesis was generated: [15171, 184755]
+Number of inputs when counterexample was found: [51, 213]
+Number of tests when counterexample was found: [11, 52]
+Time (ms) when counterexample was found: [64539, 307408]
diff --git a/experiments/scripts/diff_hyps.sh b/experiments/scripts/diff_hyps.sh
new file mode 100755
index 0000000..54ac29a
--- /dev/null
+++ b/experiments/scripts/diff_hyps.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+dir1=$1
+dir2=$2
+num_rounds=$3
+
+if [ $# != 3 ]; then
+ echo "Usage: ${0##*/} dir1 dir2 num_rounds"
+ echo "Diffs the first num_rounds hypotheses stored in two dirs"
+ exit 1
+fi
+
+if [[ ! -d $dir1 ]]; then
+ echo "$dir1"": No such directory"
+ exit 1
+fi
+if [[ ! -d $dir2 ]]; then
+ echo "$dir2"": No such directory"
+ exit 1
+fi
+
+for ((i = 1 ; i <= num_rounds ; i++)); do
+ if ! diff --unified=0 "$dir1"/hyp$i.dot "$dir2"/hyp$i.dot; then
+ exit 1
+ fi
+done
\ No newline at end of file
diff --git a/experiments/scripts/start_experiment.sh b/experiments/scripts/start_experiment.sh
new file mode 100755
index 0000000..c2249d1
--- /dev/null
+++ b/experiments/scripts/start_experiment.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# Define paths
+SSH_KEY_DIR="../orchestration/ssh-keys"
+SSH_KEY_NAME="learner-ssh"
+DOCKER_COMPOSE_DIR="../orchestration"
+
+# Ensure the ssh-keys directory exists
+mkdir -p "${SSH_KEY_DIR}"
+
+# Check if the SSH keys exist, if not, generate them
+if [[ ! -f "${SSH_KEY_DIR}/${SSH_KEY_NAME}" || ! -f "${SSH_KEY_DIR}/${SSH_KEY_NAME}.pub" ]]; then
+ echo "SSH keys not found. Generating new SSH keys..."
+ ssh-keygen -t rsa -b 4096 -f "${SSH_KEY_DIR}/${SSH_KEY_NAME}" -N ""
+ echo "SSH keys generated at ${SSH_KEY_DIR}"
+else
+ echo "SSH keys already exist. Skipping key generation."
+fi
+
+# Check user input
+if [[ "$#" -ne 1 ]]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+EXPERIMENT=$1
+COMPOSE_FILE="docker-compose-${EXPERIMENT}.yaml"
+
+# Validate input and start corresponding docker-compose
+if [[ "${EXPERIMENT}" == "openssh7" || "${EXPERIMENT}" == "openssh8" || "${EXPERIMENT}" == "dropbear" ]]; then
+ if [[ -f "${DOCKER_COMPOSE_DIR}/${COMPOSE_FILE}" ]]; then
+ pushd "${DOCKER_COMPOSE_DIR}"
+ echo "Starting experiment for ${EXPERIMENT}..."
+ docker compose -f "${DOCKER_COMPOSE_DIR}/${COMPOSE_FILE}" up --build -d
+ else
+ echo "Error: ${COMPOSE_FILE} not found in ${DOCKER_COMPOSE_DIR}"
+ exit 1
+ fi
+else
+ echo "Invalid argument. Use 'openssh' or 'dropbear'."
+ exit 1
+fi
diff --git a/ssh-learner/.gitignore b/ssh-learner/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/ssh-learner/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/ssh-learner/Dockerfile b/ssh-learner/Dockerfile
index 1609480..2d161ab 100644
--- a/ssh-learner/Dockerfile
+++ b/ssh-learner/Dockerfile
@@ -14,7 +14,6 @@ FROM bitnami/java:17
WORKDIR /app
COPY --from=build /app/target/ssh-learner.jar ./ssh-learner.jar
COPY --from=build /app/target/lib/ ./lib/
-COPY resources/ resources/
-COPY inputs/alphabets/ inputs/alphabets/
+
ENTRYPOINT ["java", "-cp", "./ssh-learner.jar:./lib/*", "learner.Main"]
diff --git a/ssh-learner/inputs/alphabets/servers/openssh.xml b/ssh-learner/inputs/alphabets/servers/openssh.xml
new file mode 100644
index 0000000..bfe0111
--- /dev/null
+++ b/ssh-learner/inputs/alphabets/servers/openssh.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ssh-learner/src/learner/Main.java b/ssh-learner/src/learner/Main.java
index 7d071b3..2a2f4f7 100644
--- a/ssh-learner/src/learner/Main.java
+++ b/ssh-learner/src/learner/Main.java
@@ -30,5 +30,6 @@ static void runMealyLearner(String[] args) {
CommandLineParser> commandLineParser = new CommandLineParser<>(mb, mb,
mb, mb);
List>> results = commandLineParser.parse(args);
+ System.out.println("Done with Mealy Machine learning");
}
}
diff --git a/ssh-mapper/mapper/mapper.py b/ssh-mapper/mapper/mapper.py
index 48f352a..b1e6aff 100755
--- a/ssh-mapper/mapper/mapper.py
+++ b/ssh-mapper/mapper/mapper.py
@@ -242,9 +242,13 @@ def listen(self):
for i in range(repeat):
result = ''
for ci, command in enumerate(commands):
- print('[%s]' % self.transport)
- print('Sending %s...' % command.decode('UTF-8'))
- response = self.process_learlib_query(command.decode('UTF-8'))
+ final_cmd = command
+ if type(command) != str:
+ final_cmd = command.decode('UTF-8')
+ # print('transport is: [%s]' % self.transport)
+ if final_cmd != '':
+ print('Sending %s...' %final_cmd)
+ response = self.process_learlib_query(final_cmd)
result += response
# If this is not the last command, add a space
if ci != len(commands)-1: