[gcr/wip/dueno/ssh-agent: 3/5] gcr: Port ssh-agent tests from gnome-keyring
- From: Daiki Ueno <dueno src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcr/wip/dueno/ssh-agent: 3/5] gcr: Port ssh-agent tests from gnome-keyring
- Date: Fri, 12 Feb 2021 17:00:22 +0000 (UTC)
commit 38dcf0097abacc7e0198c8dcc13f280648d2c58e
Author: Daiki Ueno <dueno src gnome org>
Date: Thu Feb 11 16:18:32 2021 +0100
gcr: Port ssh-agent tests from gnome-keyring
This copies most of the tests and fixtures from gnome-keyring,
exercising ssh-agent functionality. Currently
test-gkd-ssh-agent-interaction has not been ported yet, because the
new implementation interacts with secret-service.
gcr/fixtures/ssh-agent/id_dsa_encrypted | 15 +
gcr/fixtures/ssh-agent/id_dsa_encrypted.pub | 1 +
gcr/fixtures/ssh-agent/id_dsa_plain | 12 +
gcr/fixtures/ssh-agent/id_dsa_plain.pub | 1 +
gcr/fixtures/ssh-agent/id_dsa_test.pub | 7 +
gcr/fixtures/ssh-agent/id_ecdsa_384 | 6 +
gcr/fixtures/ssh-agent/id_ecdsa_384.pub | 1 +
gcr/fixtures/ssh-agent/id_ecdsa_521 | 7 +
gcr/fixtures/ssh-agent/id_ecdsa_521.pub | 1 +
gcr/fixtures/ssh-agent/id_ecdsa_encrypted | 8 +
gcr/fixtures/ssh-agent/id_ecdsa_encrypted.pub | 1 +
gcr/fixtures/ssh-agent/id_ecdsa_plain | 5 +
gcr/fixtures/ssh-agent/id_ecdsa_plain.pub | 1 +
gcr/fixtures/ssh-agent/id_ecdsa_test.pub | 1 +
gcr/fixtures/ssh-agent/id_rsa_encrypted | 30 ++
gcr/fixtures/ssh-agent/id_rsa_encrypted.pub | 1 +
gcr/fixtures/ssh-agent/id_rsa_plain | 27 ++
gcr/fixtures/ssh-agent/id_rsa_plain.pub | 1 +
gcr/fixtures/ssh-agent/id_rsa_test.pub | 1 +
gcr/fixtures/ssh-agent/identity.pub | 1 +
gcr/gcr-ssh-agent-service.c | 19 +-
gcr/gcr-ssh-agent-test.c | 334 ++++++++++++++
gcr/gcr-ssh-agent-test.h | 94 ++++
gcr/meson.build | 43 +-
gcr/test-ssh-agent-common.c | 334 ++++++++++++++
gcr/test-ssh-agent-common.h | 94 ++++
gcr/test-ssh-agent-preload.c | 166 +++++++
gcr/test-ssh-agent-process.c | 219 +++++++++
gcr/test-ssh-agent-service.c | 618 ++++++++++++++++++++++++++
gcr/test-ssh-agent-util.c | 119 +++++
30 files changed, 2163 insertions(+), 5 deletions(-)
---
diff --git a/gcr/fixtures/ssh-agent/id_dsa_encrypted b/gcr/fixtures/ssh-agent/id_dsa_encrypted
new file mode 100644
index 0000000..c17fb80
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_dsa_encrypted
@@ -0,0 +1,15 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1ED7C6189634877B
+
+lex6pFMAspyvnqSktXA1NX/x80/Ebb9BGFaIcJAPvLduCrDR02fgwc3oE+dwSwwe
+PXZ8vJK8+AP+Z8Rkedya/3OT4vaAuSENZFCfJA+P6lXglVQplA57R4U5/P9580Ee
+l/VTumnh5Gz84hJ5TuEspDOLrq8atkc31qFbEJ+zjMLygGNGbIOzecLou2pBt1Ol
+ncx1MPIznoJl2b1NQt7rgPpcbqzCHo+/qgLgvGs7osIg8xzzp+E2ifWuwCnY4NmW
+dxLRABi4I97q7kShH7OblBQLKxDreg28sojJQ0h0y0fd6xVcoscFCvfanFh8xx/D
+rI+JV3HCRCrlB9YS6U3zB5vpbc1UQ1EaE4AxSmrSLdKsvrPGc7M+grwy/DjYerqO
+WGwFWnz/OrlXruJG9Nwyltq/YmXAxFGoSWrunkm42xUxYs8RElddQOFC0ZyfVWOi
+IOS2Bv2HkNW+lMTRoR/RIbDc90wzO0HL0Xx4v6LYSbVBZIcaOJU+stoNLeE8Fu53
+G47YU+Fd7WswdlIdXtrPjyyiWapf6+xNdhRrqB+40JJQRi2mL1NyYZ2bZkjEd0Or
+DsfFH/+DlZrjEdlqWTK2ow==
+-----END DSA PRIVATE KEY-----
diff --git a/gcr/fixtures/ssh-agent/id_dsa_encrypted.pub b/gcr/fixtures/ssh-agent/id_dsa_encrypted.pub
new file mode 100644
index 0000000..a64acac
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_dsa_encrypted.pub
@@ -0,0 +1 @@
+ssh-dss
AAAAB3NzaC1kc3MAAACBANHNmw2YHEodUj4Ae27i8Rm8uoLnpS68QEiCJx8bv9P1o0AaD0w55sH+TBzlo7vtAEDlAzIOBY3PMpy5WarELTIeXmFPzKfHL8tuxMbOPaN/wDkDZNnJZsqlyRwlQKStPcAlvLBNuMjA53u2ndMTVghtUHXETQzwxKhXf7TmvfLBAAAAFQDnF/Y8MgFCP0PpRC5ZAQo1dyDEwwAAAIEAr4iOpTeZx8i1QgQpRl+dmbBAtHTXbPiophzNJBge9lixqF0T3egN2B9wGGnumIXmnst9RPPjuu+cHCLfxhXHzLlW8MLwoiF6ZQOx9M8WcfWIl5oiGyr2e969woRf5OcMGQPOQBdws6MEtemRqq5gu6dqDqVl3xfhSZSP9LpqAI8AAACAUjiuQ3qGErsCz++qd0qrR++QA185XGXAPZqQEHcr4iKSlO17hSUYA03kOWtDaeRtJOlxjIjl9iLo3juKGFgxUfo2StScOSO2saTWFGjA4MybHCK1+mIYXRcYrq314yK2Tmbql/UGDWpcCCGXLWpSFHTaXTbJjPd6VL+TO9/8tFk=
diff --git a/gcr/fixtures/ssh-agent/id_dsa_plain b/gcr/fixtures/ssh-agent/id_dsa_plain
new file mode 100644
index 0000000..2687623
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_dsa_plain
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQDCyZij6148cb6Gp2XazVJr+zrcfSkbN1MyeR5hCgACTqcn1D4R
+huf79uWe7lvyYuPyXNedfde0iFP7Ff9k1T9i3thyYjs1scdwpbqxnAVnmN4SNv/v
+fFXPp6w0EDNqmAOwg+Pqwue7juiPVJyPBcsSPZZKTOMDCS/2fVibFCXgswIVAOW6
+ngNCg6d4Cn+GHQtEbNVtZpRdAoGAP2LhEH+zUCYri0xi32l9bMnlqDCBdw2zOMbe
+G2XDRt40W4ObiE1+PPNp/CDFuYrOjD4s7Cl4s/U+iop4DKsPcLwbdr3CoWE6hEuO
+dH0jkzcvt8kZ5Ymtm3OiqEW2ARi8rUwVJ9+bRbkfRerNrDeH/PQzwCWf7Lzp9lPT
+NVjCDtsCgYANW+HtuJWVmfXRRDJ1goMK+GXixDvBLBbFSDf74kYInt3vUBm4MKpr
+HbmC27TLRymb6IOH1ENpYT3MffZJusQTqqZJKPba5nwLvPP9lzN60bJAtqiWUsqf
+wHEh6Jx+qoMggm8i6ogJJO2zDlki5Twf1ilN+tinHdOL/2CmPPRMgAIVALKfUS61
+xqFTOY5fG1+rLwlPGvL9
+-----END DSA PRIVATE KEY-----
diff --git a/gcr/fixtures/ssh-agent/id_dsa_plain.pub b/gcr/fixtures/ssh-agent/id_dsa_plain.pub
new file mode 100644
index 0000000..3b4717d
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_dsa_plain.pub
@@ -0,0 +1 @@
+ssh-dss
AAAAB3NzaC1kc3MAAACBAMLJmKPrXjxxvoanZdrNUmv7Otx9KRs3UzJ5HmEKAAJOpyfUPhGG5/v25Z7uW/Ji4/Jc151917SIU/sV/2TVP2Le2HJiOzWxx3ClurGcBWeY3hI2/+98Vc+nrDQQM2qYA7CD4+rC57uO6I9UnI8FyxI9lkpM4wMJL/Z9WJsUJeCzAAAAFQDlup4DQoOneAp/hh0LRGzVbWaUXQAAAIA/YuEQf7NQJiuLTGLfaX1syeWoMIF3DbM4xt4bZcNG3jRbg5uITX4882n8IMW5is6MPizsKXiz9T6KingMqw9wvBt2vcKhYTqES450fSOTNy+3yRnlia2bc6KoRbYBGLytTBUn35tFuR9F6s2sN4f89DPAJZ/svOn2U9M1WMIO2wAAAIANW+HtuJWVmfXRRDJ1goMK+GXixDvBLBbFSDf74kYInt3vUBm4MKprHbmC27TLRymb6IOH1ENpYT3MffZJusQTqqZJKPba5nwLvPP9lzN60bJAtqiWUsqfwHEh6Jx+qoMggm8i6ogJJO2zDlki5Twf1ilN+tinHdOL/2CmPPRMgA==
diff --git a/gcr/fixtures/ssh-agent/id_dsa_test.pub b/gcr/fixtures/ssh-agent/id_dsa_test.pub
new file mode 100644
index 0000000..33653b2
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_dsa_test.pub
@@ -0,0 +1,7 @@
+# A comment should be ignored
+
+# Blank lines should be ignored
+
+ssh-dss
AAAAB3NzaC1kc3MAAACBANHNmw2YHEodUj4Ae27i8Rm8uoLnpS68QEiCJx8bv9P1o0AaD0w55sH+TBzlo7vtAEDlAzIOBY3PMpy5WarELTIeXmFPzKfHL8tuxMbOPaN/wDkDZNnJZsqlyRwlQKStPcAlvLBNuMjA53u2ndMTVghtUHXETQzwxKhXf7TmvfLBAAAAFQDnF/Y8MgFCP0PpRC5ZAQo1dyDEwwAAAIEAr4iOpTeZx8i1QgQpRl+dmbBAtHTXbPiophzNJBge9lixqF0T3egN2B9wGGnumIXmnst9RPPjuu+cHCLfxhXHzLlW8MLwoiF6ZQOx9M8WcfWIl5oiGyr2e969woRf5OcMGQPOQBdws6MEtemRqq5gu6dqDqVl3xfhSZSP9LpqAI8AAACAUjiuQ3qGErsCz++qd0qrR++QA185XGXAPZqQEHcr4iKSlO17hSUYA03kOWtDaeRtJOlxjIjl9iLo3juKGFgxUfo2StScOSO2saTWFGjA4MybHCK1+mIYXRcYrq314yK2Tmbql/UGDWpcCCGXLWpSFHTaXTbJjPd6VL+TO9/8tFk=
A public key comment
+
+# blah blah
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_384 b/gcr/fixtures/ssh-agent/id_ecdsa_384
new file mode 100644
index 0000000..7d12859
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_384
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDBAcQcqfgI1Oc9lkcuvD7tQUVmjI2w1E122EO7olpF560alvAk9/hhu
+eTZpAgl3HRugBwYFK4EEACKhZANiAARoa4Enyu7wC6QYrwPrOkhTljfmen/pF2x7
+Lf+SlCpAX5w69KAXcbNPiDncXpckecfQusf/KA9KAMFQXa/eQmXkyZOjhiWkFKTz
+4TklDF2ehBhE83riZFl+JAlaQOcFka0=
+-----END EC PRIVATE KEY-----
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_384.pub b/gcr/fixtures/ssh-agent/id_ecdsa_384.pub
new file mode 100644
index 0000000..0ca36a4
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_384.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384
AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBGhrgSfK7vALpBivA+s6SFOWN+Z6f+kXbHst/5KUKkBfnDr0oBdxs0+IOdxelyR5x9C6x/8oD0oAwVBdr95CZeTJk6OGJaQUpPPhOSUMXZ6EGETzeuJkWX4kCVpA5wWRrQ==
A public key comment
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_521 b/gcr/fixtures/ssh-agent/id_ecdsa_521
new file mode 100644
index 0000000..32f2251
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_521
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBLLaP4NDe6/pO69bC8xRzKcRKZ/HFebSnl6IYerSBv1uXSuIwhK5s
+6xhFUfecUCrImZYaDwFoeB8pa5D66siqWsygBwYFK4EEACOhgYkDgYYABAEuCDfR
+6i7TTI99PeX85cbIhzaO3ho/s9QIdAIeut5ybrTUTgDepo3A+PxHLgAwIxMgtkB6
+0HVSE+NL47ewKUWSOAAQP16XBWjpJHtTZrsy3he+aUw5728tCjI4/TPqF6ANdRw0
+FjAj7Q0SQvTQl9CqBW68beETcBXK9y8YtO+pHnVmYA==
+-----END EC PRIVATE KEY-----
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_521.pub b/gcr/fixtures/ssh-agent/id_ecdsa_521.pub
new file mode 100644
index 0000000..e57832d
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_521.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521
AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAEuCDfR6i7TTI99PeX85cbIhzaO3ho/s9QIdAIeut5ybrTUTgDepo3A+PxHLgAwIxMgtkB60HVSE+NL47ewKUWSOAAQP16XBWjpJHtTZrsy3he+aUw5728tCjI4/TPqF6ANdRw0FjAj7Q0SQvTQl9CqBW68beETcBXK9y8YtO+pHnVmYA==
A public key comment
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_encrypted b/gcr/fixtures/ssh-agent/id_ecdsa_encrypted
new file mode 100644
index 0000000..3955d0f
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_encrypted
@@ -0,0 +1,8 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,739A7A7A93FC8D8932F08886D4E00A28
+
+R993QL3hLEDT9eav5CGOEAfpp87WXwwfUQBDX6tQLT9AfKawIx9ywWEVDP858YvH
+7DVftJjfMEJPTprMunH/b+lzG20C5UkXFJSV6Mjb1vfYh55tMn5BkzUswzMtHiXw
+C8T+HqpuKI5jTGDbW9m5A0VvFHvWgktj6BYCprpldtI=
+-----END EC PRIVATE KEY-----
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_encrypted.pub b/gcr/fixtures/ssh-agent/id_ecdsa_encrypted.pub
new file mode 100644
index 0000000..d589462
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_encrypted.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNgFMnVkKhrkaU7FhRLHKstw6YrXHZ5o0hnoKu32Zup0JCegz9GGARlSDf8shWYNi+jGHJ+cIkgvmi92x2QNiAo=
A public key comment
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_plain b/gcr/fixtures/ssh-agent/id_ecdsa_plain
new file mode 100644
index 0000000..6423c0d
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_plain
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIMYWoyDjg5vGlG5DLo6EmnzXK4OGfnA+2GrL9p3xfvu+oAoGCCqGSM49
+AwEHoUQDQgAEqOtZpbYB2DmsI3PDGXRArS3XLf4GhOQr4VxXJHIv7L8Ow2dWlc79
+nR2GSnS2QsXGRVkBOAPH5ZdfvVLrI1zLnA==
+-----END EC PRIVATE KEY-----
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_plain.pub b/gcr/fixtures/ssh-agent/id_ecdsa_plain.pub
new file mode 100644
index 0000000..7d4b2d4
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_plain.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKjrWaW2Adg5rCNzwxl0QK0t1y3+BoTkK+FcVyRyL+y/DsNnVpXO/Z0dhkp0tkLFxkVZATgDx+WXX71S6yNcy5w=
A public key comment
diff --git a/gcr/fixtures/ssh-agent/id_ecdsa_test.pub b/gcr/fixtures/ssh-agent/id_ecdsa_test.pub
new file mode 100644
index 0000000..7d4b2d4
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_ecdsa_test.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKjrWaW2Adg5rCNzwxl0QK0t1y3+BoTkK+FcVyRyL+y/DsNnVpXO/Z0dhkp0tkLFxkVZATgDx+WXX71S6yNcy5w=
A public key comment
diff --git a/gcr/fixtures/ssh-agent/id_rsa_encrypted b/gcr/fixtures/ssh-agent/id_rsa_encrypted
new file mode 100644
index 0000000..2c72860
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_rsa_encrypted
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C7CA72E4022D0E83
+
+me0oewaJEzC9jiS1EaEN1dgXwc6QpVa9YeZLOmuhWbKhJI7B4eB7ZzdCRZv07wKv
+kCSkM+/rk6Env7QjkRhREF2Uc1jGwZAh5SttP/eGlWe4tcJ0o246rNgtPmyrlmh4
+7jESkZICnv7kv9nam4W0GU/4UHTGZsx4z6l0XUnbI5mDwUC4QL7mF9Bu3tZ3+hlY
+V4Pr7OklILzopGuoaYaJABhbu/EtU3R8+g9gXJZFkLJUo41Q53BjBlZb1XEKSBE/
+3TL+sDVklBOZlqgIiBnN7buGeC/0VFzmworpMvti1SIBtfKCuYGYcrqoeUmP8+CK
+lAOpfFGWuh89YpVsWG57pJg6YJo8SrqwmUO0ksv3SA2Lf4hoecX3Ikp6vNKYlZ27
+uKWtmWV79gtsOKARh2v72ZFChRS6AQFkU1ZMA56rKEaW/Mvlm/7HF9G4k7SEftR1
+r06FUKp5uUCbvWOfyYM/69HdB8aZROU24zUPkYu49kZ/QCl7q7LxG+ODJIybyklR
+RxZVO0qcb14umRP0iC+9jNw3J/hECS6JzHW7NbCplzi/AEbXZGUrhfzpri3CTs81
+l9WSywbZINUyesYO4TfttfmCgBuLRc0x2C/wrn8MG09Gl7c2aw2pxhaMPGF3j/G8
+shV7FwTGsKm8G+eMSiFXkm58Biz/nAITimAqe36VsmkcqjAuX0YVAiLVkux9YmQ2
+5hmCoBaZIx88YGgCwsigwPQPGQrXlZinlFfYluG6trA42pl2BD/6U/AJEZ8RUsD0
+OshlvRxxR0/zCqMufRWxBb1BUftglKunfiF6iHgTshIoOUmvLblzaEDB8Jf5UMS1
+tZMH0RQSLH3gQ+kp7/2mW2jGbdIhusru729yykb/9iinoGMEgdsfFr62nDj5zPYb
+kltEUwjVWnuL/O/38exZjrIZkf1uaFkjLXqrHIz3MuoHSoVd/AVBeEU4BvKO4aoM
+mgcT/Nc+jNWhOOewDtvtYxcPjrvmg69huLG0XoCgQ8P2GQJD2rSVc2MTe3hqmJj8
+SKqSUdlq4Sb+8K/hh++gCQkrJb5q7zIdXxULA7xf8PD2yhrVgO/h9mzaDxR77zBJ
+lab2dSxEH9vdGQKqGT6ZndEZo6Gopn2pXtn7bYVN2K0GojYa2MiLNbuhqxtZvg5Z
+Y49acItEd49objc40IU6WAAwz5w6jl6lybTq6EiNSMsmtekugUwyFQCOpTfYdOwZ
+9zrbmzwiWWAiQQTYuPESS1FpQEvAilzoSmwmbNkaAbMZfguX429+cSW1Kdu0/AWq
+SGx7AFpZpbKLd7hdKy25ZRIyRqu0goTsqA/r28faLKhjhKMF2Dl+Pgtkny7t/k1Z
+ZJXGmt++mHIck1UvGZR37thqpqd5IF9e96Pos1nQPfkV3cxXOT6mMOf9F3yCYW6d
+VclJPaM0lTEobbt2q/cDIM86Mo7G3cYHtfe7O+ard5Uhz+KVXhczduXeiwR4XNmP
+xQj/mgGTGCZIEWMJ32576B/vjEThY1RkA/wvdiMmV4gskXBbu/rhcX/RX51yBalP
+FU0DCN56t7vrXacEcdilMJIWLFZiqQCvYFHigNhwVsfBhNZHDxRODg==
+-----END RSA PRIVATE KEY-----
diff --git a/gcr/fixtures/ssh-agent/id_rsa_encrypted.pub b/gcr/fixtures/ssh-agent/id_rsa_encrypted.pub
new file mode 100644
index 0000000..5883b32
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_rsa_encrypted.pub
@@ -0,0 +1 @@
+ssh-rsa
AAAAB3NzaC1yc2EAAAABIwAAAQEA4+W0j6ubMFOkdaQ+bSZ5UQCa/HztFKajLjAmJBjiQ2HxMkYTyVhgel1+VXzEMF0mFJx+FML5kF2sf7GA6EXCz7f1A/UiUBfFkD2BYI8WE6o71iFUQ0UK7q8gnPfckSunGdUbb3MZUz+04K6ovR8XQKaOel0EP5rZ4qF457JRg4/w7jrQU9wOuL9m05aaFbPUemACa2M0Yw49PKu6pO8RcjQ3pKokFHkigqTtoRtbk186Rponw4btFt1bQfxxyDWMA1PHz4Gts+EHgOoLfwEN/IErfpYMamgff+1O74qamOTb9LnEkgnWh0UVyf3LcMJLB/fJaEEnoqX0mzf2yon28w==
diff --git a/gcr/fixtures/ssh-agent/id_rsa_plain b/gcr/fixtures/ssh-agent/id_rsa_plain
new file mode 100644
index 0000000..2e184e4
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_rsa_plain
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAoD6VKqkhay6pKHSRjAGWWfFPU8xfsi2gnOwP/B1UHDoztx3c
+zhO+py/fTlhCnSP1jsjkrVIZcnzah2fUNFFRgS4+jROBtvbgHsS72V1E6+ZogV+m
+BJWWAhw0iPrmQ3Kvm38D3PByo5Y7yKO5kIG2LloYLjosJ5F4sx2xh0uz2wXNtnY1
+b5xhe2+VEksm9OB+FXaUkZC2fQrTNo8ZGFJQSFd8kUhIfbUDJmlYuZ+vvHM+A3Lc
+9rHyW4IPaRyxFQciRmb+ZQqU2uSdOXAhg17lskuX/q8yCI5Hy5eDicC222oUMdJT
+tYgwX4dQCU8TICWhxb3x4RCV+g7D99+tkIvv+wIBIwKCAQEAm6qCRrLtQ4xpz4cu
+TX3ig0Ivzb84Y/HPOVpYq8S4G2u9NYq5PTfAhScwsoGfy9nJ+GthzPCrAYCZxV2M
+UBR7D8aF6CGT85C8dakrgrJgNZ3/HpduExT4H06Zbx+d2x7zu5/1H8UBpjorcnMp
+SoyiWOnOWMrLzqqSghzYV4teQnkhDmMTDgP/L39k9oLh/gvDHkxQET/IirrM3iT3
+rpZsXjsA+vAOrDrrsauPP9uAswaRGOH1O+xdAc/QH6/j2RK6ew/uICl0V9xYddSw
+9LSkk0gre2sdd7zz/r2t1oMFFsq+MaQ5Uynz0zmwpe/wyQjWY1ILy/wcIdOpLyOS
+PUaMSwKBgQDMULEsX+QChX3Od9gnwfbu4it7KYOV8V495al1YsaEyZcmcPQNKGrG
+iHyjDTWjj9w0THhrzF2ZfkWw3+N3SHfYqRx0+bzMgttEEJbaACOqBJPMmOwmi30I
+9ILcmsSMyOk+W9bHKPQ4OjwIVruiyvsFoLfhcFm0hispibWCKnlhUQKBgQDIx+aT
+kFnnVBvPnLAHgDfN32X0KR5Kk3PRe0cdNoeJHb/VHgLC0SuzZwdl+bzLdEyDaKht
+MGiPtblEhrjeTvwCHpwFOyMb33lYc1En8L2DNDjL0CASzRoHbvcKkin/L78wKmkV
+TY5uFyZ7Q/5S0YNlGSKL02+XURE/F/4FzKRJiwKBgQC6zW7JfD4uMOgNOl86SvBl
+YRHPsO1V4/5kejSIlNLCjGzv8j436nBAfMm5pa1iV6TCGgezA/3OKk5Yki8N+R0d
+3HHKCOchYbKHX5/dQfS4s7pUqRJsYkZulmkENbsEX+sxsw2C4511PI6oidAfz4Zr
+i6DOHZPYQCd2b0bdaKl9iwKBgQCD8RPdUDsUW9fC8fAE7duHSall7yKIx0wb8ezn
+T7gm56nycs6dR6Bf8z9gRQcJWw21cKkxz1qnlKzyhGrbOzfkIr5MlJNqFoLw+1KW
+luLv0dwuKa6tRPPY/8bpsIH/dyXd0roVUDkGhD3b+Xs9vOFREIRqg6EaSzc4FxSk
+ua3J7QKBgBVAzKSD3ya+VYKFD3E8GaiLQoClJF2t9Zkzr3yyJ657CwugA/2uU2/x
+3YNU3vK9hyypTXulbtteifRceSLDxEBQ67f0F3gvBqU6ZU2FmD7YTTv82Jvl0Ue2
+49ouxRjON9nXmr+6qe/yr5vIRlcRjKlfaIxDL7V6OTgwedUwqCuY
+-----END RSA PRIVATE KEY-----
diff --git a/gcr/fixtures/ssh-agent/id_rsa_plain.pub b/gcr/fixtures/ssh-agent/id_rsa_plain.pub
new file mode 100644
index 0000000..a00a1e9
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_rsa_plain.pub
@@ -0,0 +1 @@
+ssh-rsa
AAAAB3NzaC1yc2EAAAABIwAAAQEAoD6VKqkhay6pKHSRjAGWWfFPU8xfsi2gnOwP/B1UHDoztx3czhO+py/fTlhCnSP1jsjkrVIZcnzah2fUNFFRgS4+jROBtvbgHsS72V1E6+ZogV+mBJWWAhw0iPrmQ3Kvm38D3PByo5Y7yKO5kIG2LloYLjosJ5F4sx2xh0uz2wXNtnY1b5xhe2+VEksm9OB+FXaUkZC2fQrTNo8ZGFJQSFd8kUhIfbUDJmlYuZ+vvHM+A3Lc9rHyW4IPaRyxFQciRmb+ZQqU2uSdOXAhg17lskuX/q8yCI5Hy5eDicC222oUMdJTtYgwX4dQCU8TICWhxb3x4RCV+g7D99+tkIvv+w==
diff --git a/gcr/fixtures/ssh-agent/id_rsa_test.pub b/gcr/fixtures/ssh-agent/id_rsa_test.pub
new file mode 100644
index 0000000..61870b3
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/id_rsa_test.pub
@@ -0,0 +1 @@
+ssh-rsa
AAAAB3NzaC1yc2EAAAABIwAAAQEAoD6VKqkhay6pKHSRjAGWWfFPU8xfsi2gnOwP/B1UHDoztx3czhO+py/fTlhCnSP1jsjkrVIZcnzah2fUNFFRgS4+jROBtvbgHsS72V1E6+ZogV+mBJWWAhw0iPrmQ3Kvm38D3PByo5Y7yKO5kIG2LloYLjosJ5F4sx2xh0uz2wXNtnY1b5xhe2+VEksm9OB+FXaUkZC2fQrTNo8ZGFJQSFd8kUhIfbUDJmlYuZ+vvHM+A3Lc9rHyW4IPaRyxFQciRmb+ZQqU2uSdOXAhg17lskuX/q8yCI5Hy5eDicC222oUMdJTtYgwX4dQCU8TICWhxb3x4RCV+g7D99+tkIvv+w==
A public key comment
diff --git a/gcr/fixtures/ssh-agent/identity.pub b/gcr/fixtures/ssh-agent/identity.pub
new file mode 100644
index 0000000..64f0092
--- /dev/null
+++ b/gcr/fixtures/ssh-agent/identity.pub
@@ -0,0 +1 @@
+2048 65537
24441362561658402203833950446201855344021432187363502135808306611576487614688480997306138918965620875403280637443583435371977323903269172664531450582985454519164856071918921465780900234446084102021505343856321702549268936741458077623280683630954129182173904049746029183391563757599728238653932509919193037170161958394083453355955428766928687086643512804493287104481453268463186578945838089020355657752804348513609803384640933423383046464181883782074377289700592413463972335302845592904197813072122904513007851760502305134812488745575825428292149365221963416490618044666955554129518253460898036309102204336193271317821
miles@centos7
diff --git a/gcr/gcr-ssh-agent-service.c b/gcr/gcr-ssh-agent-service.c
index f0133fb..f7e11fe 100644
--- a/gcr/gcr-ssh-agent-service.c
+++ b/gcr/gcr-ssh-agent-service.c
@@ -49,7 +49,8 @@ static const GcrSshAgentOperation operations[GCR_SSH_OP_MAX];
enum {
PROP_0,
PROP_PATH,
- PROP_PRELOAD
+ PROP_PRELOAD,
+ PROP_INTERACTION
};
struct _GcrSshAgentService
@@ -58,6 +59,8 @@ struct _GcrSshAgentService
gchar *path;
GcrSshAgentPreload *preload;
GcrSshAgentProcess *process;
+ /* for mocking */
+ GTlsInteraction *interaction;
GSocketAddress *address;
GSocketListener *listener;
GHashTable *keys;
@@ -106,6 +109,9 @@ gcr_ssh_agent_service_set_property (GObject *object,
case PROP_PRELOAD:
self->preload = g_value_dup_object (value);
break;
+ case PROP_INTERACTION:
+ self->interaction = g_value_dup_object (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -119,6 +125,7 @@ gcr_ssh_agent_service_finalize (GObject *object)
g_free (self->path);
g_object_unref (self->preload);
+ g_clear_object (&self->interaction);
g_object_unref (self->process);
g_object_unref (self->listener);
@@ -145,6 +152,10 @@ gcr_ssh_agent_service_class_init (GcrSshAgentServiceClass *klass)
g_param_spec_object ("preload", "Preload", "Preload",
GCR_TYPE_SSH_AGENT_PRELOAD,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+ g_object_class_install_property (gobject_class, PROP_INTERACTION,
+ g_param_spec_object ("interaction", "Interaction", "Interaction",
+ G_TYPE_TLS_INTERACTION,
+ G_PARAM_WRITABLE));
}
static gboolean
@@ -243,7 +254,11 @@ ensure_key (GcrSshAgentService *self,
label = info->comment[0] != '\0' ? info->comment : _("Unnamed");
- interaction = gcr_ssh_agent_interaction_new (NULL, label, fields);
+ if (self->interaction) {
+ interaction = g_object_ref (self->interaction);
+ } else {
+ interaction = gcr_ssh_agent_interaction_new (NULL, label, fields);
+ }
askpass = gcr_ssh_askpass_new (interaction);
g_object_unref (interaction);
diff --git a/gcr/gcr-ssh-agent-test.c b/gcr/gcr-ssh-agent-test.c
new file mode 100644
index 0000000..6196e8f
--- /dev/null
+++ b/gcr/gcr-ssh-agent-test.c
@@ -0,0 +1,334 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daiki Ueno
+ */
+
+#include "config.h"
+
+#include "gcr-ssh-agent-test.h"
+
+#include "gcr-ssh-agent-private.h"
+#include "gcr-ssh-agent-util.h"
+
+/* RSA private key blob decoded from fixtures/ssh-agent/id_rsa_plain */
+static const guint8 private_blob[4*6 + 0x101 + 0x1 + 0x101 + 0x80 + 0x81 + 0x81] = {
+ /* n */
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x3e, 0x95, 0x2a, 0xa9, 0x21, 0x6b,
+ 0x2e, 0xa9, 0x28, 0x74, 0x91, 0x8c, 0x01, 0x96, 0x59, 0xf1, 0x4f, 0x53,
+ 0xcc, 0x5f, 0xb2, 0x2d, 0xa0, 0x9c, 0xec, 0x0f, 0xfc, 0x1d, 0x54, 0x1c,
+ 0x3a, 0x33, 0xb7, 0x1d, 0xdc, 0xce, 0x13, 0xbe, 0xa7, 0x2f, 0xdf, 0x4e,
+ 0x58, 0x42, 0x9d, 0x23, 0xf5, 0x8e, 0xc8, 0xe4, 0xad, 0x52, 0x19, 0x72,
+ 0x7c, 0xda, 0x87, 0x67, 0xd4, 0x34, 0x51, 0x51, 0x81, 0x2e, 0x3e, 0x8d,
+ 0x13, 0x81, 0xb6, 0xf6, 0xe0, 0x1e, 0xc4, 0xbb, 0xd9, 0x5d, 0x44, 0xeb,
+ 0xe6, 0x68, 0x81, 0x5f, 0xa6, 0x04, 0x95, 0x96, 0x02, 0x1c, 0x34, 0x88,
+ 0xfa, 0xe6, 0x43, 0x72, 0xaf, 0x9b, 0x7f, 0x03, 0xdc, 0xf0, 0x72, 0xa3,
+ 0x96, 0x3b, 0xc8, 0xa3, 0xb9, 0x90, 0x81, 0xb6, 0x2e, 0x5a, 0x18, 0x2e,
+ 0x3a, 0x2c, 0x27, 0x91, 0x78, 0xb3, 0x1d, 0xb1, 0x87, 0x4b, 0xb3, 0xdb,
+ 0x05, 0xcd, 0xb6, 0x76, 0x35, 0x6f, 0x9c, 0x61, 0x7b, 0x6f, 0x95, 0x12,
+ 0x4b, 0x26, 0xf4, 0xe0, 0x7e, 0x15, 0x76, 0x94, 0x91, 0x90, 0xb6, 0x7d,
+ 0x0a, 0xd3, 0x36, 0x8f, 0x19, 0x18, 0x52, 0x50, 0x48, 0x57, 0x7c, 0x91,
+ 0x48, 0x48, 0x7d, 0xb5, 0x03, 0x26, 0x69, 0x58, 0xb9, 0x9f, 0xaf, 0xbc,
+ 0x73, 0x3e, 0x03, 0x72, 0xdc, 0xf6, 0xb1, 0xf2, 0x5b, 0x82, 0x0f, 0x69,
+ 0x1c, 0xb1, 0x15, 0x07, 0x22, 0x46, 0x66, 0xfe, 0x65, 0x0a, 0x94, 0xda,
+ 0xe4, 0x9d, 0x39, 0x70, 0x21, 0x83, 0x5e, 0xe5, 0xb2, 0x4b, 0x97, 0xfe,
+ 0xaf, 0x32, 0x08, 0x8e, 0x47, 0xcb, 0x97, 0x83, 0x89, 0xc0, 0xb6, 0xdb,
+ 0x6a, 0x14, 0x31, 0xd2, 0x53, 0xb5, 0x88, 0x30, 0x5f, 0x87, 0x50, 0x09,
+ 0x4f, 0x13, 0x20, 0x25, 0xa1, 0xc5, 0xbd, 0xf1, 0xe1, 0x10, 0x95, 0xfa,
+ 0x0e, 0xc3, 0xf7, 0xdf, 0xad, 0x90, 0x8b, 0xef, 0xfb,
+ /* e */
+ 0x00, 0x00, 0x00, 0x01, 0x23,
+ /* d */
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x9b, 0xaa, 0x82, 0x46, 0xb2, 0xed, 0x43,
+ 0x8c, 0x69, 0xcf, 0x87, 0x2e, 0x4d, 0x7d, 0xe2, 0x83, 0x42, 0x2f, 0xcd,
+ 0xbf, 0x38, 0x63, 0xf1, 0xcf, 0x39, 0x5a, 0x58, 0xab, 0xc4, 0xb8, 0x1b,
+ 0x6b, 0xbd, 0x35, 0x8a, 0xb9, 0x3d, 0x37, 0xc0, 0x85, 0x27, 0x30, 0xb2,
+ 0x81, 0x9f, 0xcb, 0xd9, 0xc9, 0xf8, 0x6b, 0x61, 0xcc, 0xf0, 0xab, 0x01,
+ 0x80, 0x99, 0xc5, 0x5d, 0x8c, 0x50, 0x14, 0x7b, 0x0f, 0xc6, 0x85, 0xe8,
+ 0x21, 0x93, 0xf3, 0x90, 0xbc, 0x75, 0xa9, 0x2b, 0x82, 0xb2, 0x60, 0x35,
+ 0x9d, 0xff, 0x1e, 0x97, 0x6e, 0x13, 0x14, 0xf8, 0x1f, 0x4e, 0x99, 0x6f,
+ 0x1f, 0x9d, 0xdb, 0x1e, 0xf3, 0xbb, 0x9f, 0xf5, 0x1f, 0xc5, 0x01, 0xa6,
+ 0x3a, 0x2b, 0x72, 0x73, 0x29, 0x4a, 0x8c, 0xa2, 0x58, 0xe9, 0xce, 0x58,
+ 0xca, 0xcb, 0xce, 0xaa, 0x92, 0x82, 0x1c, 0xd8, 0x57, 0x8b, 0x5e, 0x42,
+ 0x79, 0x21, 0x0e, 0x63, 0x13, 0x0e, 0x03, 0xff, 0x2f, 0x7f, 0x64, 0xf6,
+ 0x82, 0xe1, 0xfe, 0x0b, 0xc3, 0x1e, 0x4c, 0x50, 0x11, 0x3f, 0xc8, 0x8a,
+ 0xba, 0xcc, 0xde, 0x24, 0xf7, 0xae, 0x96, 0x6c, 0x5e, 0x3b, 0x00, 0xfa,
+ 0xf0, 0x0e, 0xac, 0x3a, 0xeb, 0xb1, 0xab, 0x8f, 0x3f, 0xdb, 0x80, 0xb3,
+ 0x06, 0x91, 0x18, 0xe1, 0xf5, 0x3b, 0xec, 0x5d, 0x01, 0xcf, 0xd0, 0x1f,
+ 0xaf, 0xe3, 0xd9, 0x12, 0xba, 0x7b, 0x0f, 0xee, 0x20, 0x29, 0x74, 0x57,
+ 0xdc, 0x58, 0x75, 0xd4, 0xb0, 0xf4, 0xb4, 0xa4, 0x93, 0x48, 0x2b, 0x7b,
+ 0x6b, 0x1d, 0x77, 0xbc, 0xf3, 0xfe, 0xbd, 0xad, 0xd6, 0x83, 0x05, 0x16,
+ 0xca, 0xbe, 0x31, 0xa4, 0x39, 0x53, 0x29, 0xf3, 0xd3, 0x39, 0xb0, 0xa5,
+ 0xef, 0xf0, 0xc9, 0x08, 0xd6, 0x63, 0x52, 0x0b, 0xcb, 0xfc, 0x1c, 0x21,
+ 0xd3, 0xa9, 0x2f, 0x23, 0x92, 0x3d, 0x46, 0x8c, 0x4b,
+ /* iqmp */
+ 0x00, 0x00, 0x00, 0x80, 0x15, 0x40, 0xcc, 0xa4, 0x83, 0xdf, 0x26, 0xbe,
+ 0x55, 0x82, 0x85, 0x0f, 0x71, 0x3c, 0x19, 0xa8, 0x8b, 0x42, 0x80, 0xa5,
+ 0x24, 0x5d, 0xad, 0xf5, 0x99, 0x33, 0xaf, 0x7c, 0xb2, 0x27, 0xae, 0x7b,
+ 0x0b, 0x0b, 0xa0, 0x03, 0xfd, 0xae, 0x53, 0x6f, 0xf1, 0xdd, 0x83, 0x54,
+ 0xde, 0xf2, 0xbd, 0x87, 0x2c, 0xa9, 0x4d, 0x7b, 0xa5, 0x6e, 0xdb, 0x5e,
+ 0x89, 0xf4, 0x5c, 0x79, 0x22, 0xc3, 0xc4, 0x40, 0x50, 0xeb, 0xb7, 0xf4,
+ 0x17, 0x78, 0x2f, 0x06, 0xa5, 0x3a, 0x65, 0x4d, 0x85, 0x98, 0x3e, 0xd8,
+ 0x4d, 0x3b, 0xfc, 0xd8, 0x9b, 0xe5, 0xd1, 0x47, 0xb6, 0xe3, 0xda, 0x2e,
+ 0xc5, 0x18, 0xce, 0x37, 0xd9, 0xd7, 0x9a, 0xbf, 0xba, 0xa9, 0xef, 0xf2,
+ 0xaf, 0x9b, 0xc8, 0x46, 0x57, 0x11, 0x8c, 0xa9, 0x5f, 0x68, 0x8c, 0x43,
+ 0x2f, 0xb5, 0x7a, 0x39, 0x38, 0x30, 0x79, 0xd5, 0x30, 0xa8, 0x2b, 0x98,
+ /* p */
+ 0x00, 0x00, 0x00, 0x81, 0x00, 0xcc, 0x50, 0xb1, 0x2c, 0x5f, 0xe4, 0x02,
+ 0x85, 0x7d, 0xce, 0x77, 0xd8, 0x27, 0xc1, 0xf6, 0xee, 0xe2, 0x2b, 0x7b,
+ 0x29, 0x83, 0x95, 0xf1, 0x5e, 0x3d, 0xe5, 0xa9, 0x75, 0x62, 0xc6, 0x84,
+ 0xc9, 0x97, 0x26, 0x70, 0xf4, 0x0d, 0x28, 0x6a, 0xc6, 0x88, 0x7c, 0xa3,
+ 0x0d, 0x35, 0xa3, 0x8f, 0xdc, 0x34, 0x4c, 0x78, 0x6b, 0xcc, 0x5d, 0x99,
+ 0x7e, 0x45, 0xb0, 0xdf, 0xe3, 0x77, 0x48, 0x77, 0xd8, 0xa9, 0x1c, 0x74,
+ 0xf9, 0xbc, 0xcc, 0x82, 0xdb, 0x44, 0x10, 0x96, 0xda, 0x00, 0x23, 0xaa,
+ 0x04, 0x93, 0xcc, 0x98, 0xec, 0x26, 0x8b, 0x7d, 0x08, 0xf4, 0x82, 0xdc,
+ 0x9a, 0xc4, 0x8c, 0xc8, 0xe9, 0x3e, 0x5b, 0xd6, 0xc7, 0x28, 0xf4, 0x38,
+ 0x3a, 0x3c, 0x08, 0x56, 0xbb, 0xa2, 0xca, 0xfb, 0x05, 0xa0, 0xb7, 0xe1,
+ 0x70, 0x59, 0xb4, 0x86, 0x2b, 0x29, 0x89, 0xb5, 0x82, 0x2a, 0x79, 0x61,
+ 0x51,
+ /* q */
+ 0x00, 0x00, 0x00, 0x81, 0x00, 0xc8, 0xc7, 0xe6, 0x93, 0x90, 0x59, 0xe7,
+ 0x54, 0x1b, 0xcf, 0x9c, 0xb0, 0x07, 0x80, 0x37, 0xcd, 0xdf, 0x65, 0xf4,
+ 0x29, 0x1e, 0x4a, 0x93, 0x73, 0xd1, 0x7b, 0x47, 0x1d, 0x36, 0x87, 0x89,
+ 0x1d, 0xbf, 0xd5, 0x1e, 0x02, 0xc2, 0xd1, 0x2b, 0xb3, 0x67, 0x07, 0x65,
+ 0xf9, 0xbc, 0xcb, 0x74, 0x4c, 0x83, 0x68, 0xa8, 0x6d, 0x30, 0x68, 0x8f,
+ 0xb5, 0xb9, 0x44, 0x86, 0xb8, 0xde, 0x4e, 0xfc, 0x02, 0x1e, 0x9c, 0x05,
+ 0x3b, 0x23, 0x1b, 0xdf, 0x79, 0x58, 0x73, 0x51, 0x27, 0xf0, 0xbd, 0x83,
+ 0x34, 0x38, 0xcb, 0xd0, 0x20, 0x12, 0xcd, 0x1a, 0x07, 0x6e, 0xf7, 0x0a,
+ 0x92, 0x29, 0xff, 0x2f, 0xbf, 0x30, 0x2a, 0x69, 0x15, 0x4d, 0x8e, 0x6e,
+ 0x17, 0x26, 0x7b, 0x43, 0xfe, 0x52, 0xd1, 0x83, 0x65, 0x19, 0x22, 0x8b,
+ 0xd3, 0x6f, 0x97, 0x51, 0x11, 0x3f, 0x17, 0xfe, 0x05, 0xcc, 0xa4, 0x49,
+ 0x8b
+};
+
+void
+prepare_request_identities (EggBuffer *req)
+{
+ gboolean ret;
+
+ egg_buffer_reset (req);
+
+ ret = egg_buffer_add_uint32 (req, 1);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_REQUEST_IDENTITIES);
+ g_assert_true (ret);
+}
+
+void
+check_identities_answer (EggBuffer *resp, gsize count)
+{
+ uint32_t length;
+ unsigned char code;
+ size_t offset;
+ gboolean ret;
+
+ offset = 0;
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+ g_assert_cmpint (length, ==, resp->len - 4);
+
+ code = 0;
+ ret = egg_buffer_get_byte (resp, offset, &offset, &code);
+ g_assert_true (ret);
+ g_assert_cmpint (code, ==, GCR_SSH_RES_IDENTITIES_ANSWER);
+
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+ g_assert_cmpint (length, ==, count);
+}
+
+void
+prepare_add_identity (EggBuffer *req)
+{
+ gboolean ret;
+
+ egg_buffer_reset (req);
+
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_ADD_IDENTITY);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (req, "ssh-rsa");
+ g_assert_true (ret);
+
+ ret = egg_buffer_append (req, private_blob, G_N_ELEMENTS(private_blob));
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (req, "comment");
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
+ g_assert_true (ret);
+}
+
+GBytes *
+public_key_from_file (const gchar *path, gchar **comment)
+{
+ GBytes *public_bytes;
+ GBytes *public_key;
+
+ GError *error = NULL;
+ gchar *contents;
+ gsize length;
+
+ if (!g_file_get_contents (path, &contents, &length, &error)) {
+ g_message ("couldn't read file: %s: %s", path, error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ public_bytes = g_bytes_new_take (contents, length);
+ public_key = _gcr_ssh_agent_parse_public_key (public_bytes, comment);
+ g_bytes_unref (public_bytes);
+
+ return public_key;
+}
+
+void
+prepare_remove_identity (EggBuffer *req)
+{
+ GBytes *public_key;
+ gchar *comment;
+ gsize length;
+ const guchar *blob;
+ gboolean ret;
+
+ public_key = public_key_from_file (SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_plain.pub", &comment);
+ g_free (comment);
+ blob = g_bytes_get_data (public_key, &length);
+
+ egg_buffer_reset (req);
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_REMOVE_IDENTITY);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte_array (req, blob, length);
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
+ g_assert_true (ret);
+
+ g_bytes_unref (public_key);
+}
+
+void
+prepare_remove_all_identities (EggBuffer *req)
+{
+ gboolean ret;
+
+ egg_buffer_reset (req);
+ ret = egg_buffer_add_uint32 (req, 1);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_REMOVE_ALL_IDENTITIES);
+ g_assert_true (ret);
+}
+
+void
+check_response (EggBuffer *resp, unsigned char expected)
+{
+ uint32_t length;
+ unsigned char code;
+ size_t offset;
+ gboolean ret;
+
+ offset = 0;
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+ g_assert_cmpint (length, ==, resp->len - 4);
+
+ code = 0;
+ ret = egg_buffer_get_byte (resp, offset, &offset, &code);
+ g_assert_true (ret);
+ g_assert_cmpint (expected, ==, code);
+}
+
+void
+check_success (EggBuffer *resp)
+{
+ check_response (resp, GCR_SSH_RES_SUCCESS);
+}
+
+void
+check_failure (EggBuffer *resp)
+{
+ check_response (resp, GCR_SSH_RES_FAILURE);
+}
+
+void
+prepare_sign_request (EggBuffer *req)
+{
+ GBytes *public_key;
+ gchar *comment;
+ gsize length;
+ const guchar *blob;
+ gboolean ret;
+
+ public_key = public_key_from_file (SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_plain.pub", &comment);
+ g_free (comment);
+ blob = g_bytes_get_data (public_key, &length);
+
+ egg_buffer_reset (req);
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_SIGN_REQUEST);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte_array (req, blob, length);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (req, "data");
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
+ g_assert_true (ret);
+
+ g_bytes_unref (public_key);
+}
+
+void
+check_sign_response (EggBuffer *resp)
+{
+ uint32_t length;
+ unsigned char code;
+ size_t offset;
+ gboolean ret;
+
+ offset = 0;
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+ g_assert_cmpint (length, ==, resp->len - 4);
+
+ code = 0;
+ ret = egg_buffer_get_byte (resp, offset, &offset, &code);
+ g_assert_true (ret);
+ g_assert_cmpint (code, ==, GCR_SSH_RES_SIGN_RESPONSE);
+
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+}
diff --git a/gcr/gcr-ssh-agent-test.h b/gcr/gcr-ssh-agent-test.h
new file mode 100644
index 0000000..f4849fd
--- /dev/null
+++ b/gcr/gcr-ssh-agent-test.h
@@ -0,0 +1,94 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daiki Ueno
+ */
+
+#include <glib.h>
+#include "egg/egg-buffer.h"
+
+void prepare_request_identities (EggBuffer *req);
+void prepare_add_identity (EggBuffer *req);
+void prepare_remove_identity (EggBuffer *req);
+void prepare_remove_all_identities (EggBuffer *req);
+void prepare_sign_request (EggBuffer *req);
+
+void check_identities_answer (EggBuffer *resp, gsize count);
+void check_sign_response (EggBuffer *resp);
+void check_response (EggBuffer *resp, unsigned char expected);
+void check_success (EggBuffer *resp);
+void check_failure (EggBuffer *resp);
+
+GBytes *public_key_from_file (const gchar *path, gchar **comment);
+
+#define DEFINE_CALL_FUNCS(Test, Call) \
+static inline void \
+call_request_identities (Test *test, gsize count) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_request_identities (&test->req); \
+ Call (test); \
+ check_identities_answer (&test->resp, count); \
+} \
+ \
+static inline void \
+call_add_identity (Test *test) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_add_identity (&test->req); \
+ Call (test); \
+ check_success (&test->resp); \
+} \
+ \
+static inline void \
+call_remove_identity (Test *test) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_remove_identity (&test->req); \
+ Call (test); \
+ check_success (&test->resp); \
+} \
+ \
+static inline void \
+call_remove_all_identities (Test *test) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_remove_all_identities (&test->req); \
+ Call (test); \
+ check_success (&test->resp); \
+} \
+ \
+static inline void \
+call_sign (Test *test) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_sign_request (&test->req); \
+ Call (test); \
+ check_sign_response (&test->resp); \
+}
diff --git a/gcr/meson.build b/gcr/meson.build
index b6bcd0a..87923f3 100644
--- a/gcr/meson.build
+++ b/gcr/meson.build
@@ -240,16 +240,16 @@ gcr_ssh_askpass = executable('gcr-ssh-askpass',
if get_option('ssh_agent')
# gcr-ssh-agent binary
- gcr_ssh_agent_sources = [
- 'gcr-ssh-agent.c',
+ gcr_ssh_agent_lib_sources = [
'gcr-ssh-agent-interaction.c',
'gcr-ssh-agent-preload.c',
'gcr-ssh-agent-process.c',
'gcr-ssh-agent-service.c',
'gcr-ssh-agent-util.c',
]
+
gcr_ssh_agent = executable('gcr-ssh-agent',
- gcr_ssh_agent_sources,
+ gcr_ssh_agent_lib_sources + [ 'gcr-ssh-agent.c' ],
dependencies: [ gcr_base_deps, gcr_base_dep, libsecret_dep ],
c_args: [
'-DGCR_COMPILATION',
@@ -259,6 +259,43 @@ if get_option('ssh_agent')
install: true,
install_dir: get_option('libexecdir'),
)
+
+ gcr_ssh_agent_test_cflags = [
+ '-DSRCDIR="@0@"'.format(source_root),
+ '-D_GCR_TEST_SSH_ASKPASS_PATH="@0@"'.format(gcr_ssh_askpass.full_path()),
+ ]
+
+ gcr_ssh_agent_test_lib = static_library('gcr-ssh-agent-test',
+ sources: gcr_ssh_agent_lib_sources + [ 'gcr-ssh-agent-test.c' ],
+ dependencies: [ gcr_base_deps, gcr_base_dep, libsecret_dep ],
+ c_args: [
+ '-DGCR_COMPILATION',
+ '-DGCR_API_SUBJECT_TO_CHANGE',
+ ] + gcr_ssh_agent_test_cflags,
+ include_directories: config_h_dir,
+ )
+
+ gcr_ssh_agent_test_names = [
+ 'preload',
+ 'process',
+ 'service',
+ 'util',
+ ]
+
+ foreach _test : gcr_ssh_agent_test_names
+ test_bin = executable('test-ssh-agent-'+_test,
+ 'test-ssh-agent-@0@.c'.format(_test),
+ dependencies: [ gcr_base_deps, gcr_base_dep ],
+ link_with: [ gcr_ssh_agent_test_lib, egg_test_lib ],
+ c_args: [ gcr_base_cflags, gcr_ssh_agent_test_cflags ],
+ include_directories: config_h_dir,
+ )
+
+ test(_test, test_bin,
+ suite: 'gcr-ssh-agent',
+ depends: gcr_ssh_askpass,
+ )
+ endforeach
endif
# Services
diff --git a/gcr/test-ssh-agent-common.c b/gcr/test-ssh-agent-common.c
new file mode 100644
index 0000000..bc17a77
--- /dev/null
+++ b/gcr/test-ssh-agent-common.c
@@ -0,0 +1,334 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daiki Ueno
+ */
+
+#include "config.h"
+
+#include "test-common.h"
+
+#include "gcr-ssh-agent-private.h"
+#include "gcr-ssh-agent-util.h"
+
+/* RSA private key blob decoded from pkcs11/ssh-store/fixtures/id_rsa_plain */
+static const guint8 private_blob[4*6 + 0x101 + 0x1 + 0x101 + 0x80 + 0x81 + 0x81] = {
+ /* n */
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x3e, 0x95, 0x2a, 0xa9, 0x21, 0x6b,
+ 0x2e, 0xa9, 0x28, 0x74, 0x91, 0x8c, 0x01, 0x96, 0x59, 0xf1, 0x4f, 0x53,
+ 0xcc, 0x5f, 0xb2, 0x2d, 0xa0, 0x9c, 0xec, 0x0f, 0xfc, 0x1d, 0x54, 0x1c,
+ 0x3a, 0x33, 0xb7, 0x1d, 0xdc, 0xce, 0x13, 0xbe, 0xa7, 0x2f, 0xdf, 0x4e,
+ 0x58, 0x42, 0x9d, 0x23, 0xf5, 0x8e, 0xc8, 0xe4, 0xad, 0x52, 0x19, 0x72,
+ 0x7c, 0xda, 0x87, 0x67, 0xd4, 0x34, 0x51, 0x51, 0x81, 0x2e, 0x3e, 0x8d,
+ 0x13, 0x81, 0xb6, 0xf6, 0xe0, 0x1e, 0xc4, 0xbb, 0xd9, 0x5d, 0x44, 0xeb,
+ 0xe6, 0x68, 0x81, 0x5f, 0xa6, 0x04, 0x95, 0x96, 0x02, 0x1c, 0x34, 0x88,
+ 0xfa, 0xe6, 0x43, 0x72, 0xaf, 0x9b, 0x7f, 0x03, 0xdc, 0xf0, 0x72, 0xa3,
+ 0x96, 0x3b, 0xc8, 0xa3, 0xb9, 0x90, 0x81, 0xb6, 0x2e, 0x5a, 0x18, 0x2e,
+ 0x3a, 0x2c, 0x27, 0x91, 0x78, 0xb3, 0x1d, 0xb1, 0x87, 0x4b, 0xb3, 0xdb,
+ 0x05, 0xcd, 0xb6, 0x76, 0x35, 0x6f, 0x9c, 0x61, 0x7b, 0x6f, 0x95, 0x12,
+ 0x4b, 0x26, 0xf4, 0xe0, 0x7e, 0x15, 0x76, 0x94, 0x91, 0x90, 0xb6, 0x7d,
+ 0x0a, 0xd3, 0x36, 0x8f, 0x19, 0x18, 0x52, 0x50, 0x48, 0x57, 0x7c, 0x91,
+ 0x48, 0x48, 0x7d, 0xb5, 0x03, 0x26, 0x69, 0x58, 0xb9, 0x9f, 0xaf, 0xbc,
+ 0x73, 0x3e, 0x03, 0x72, 0xdc, 0xf6, 0xb1, 0xf2, 0x5b, 0x82, 0x0f, 0x69,
+ 0x1c, 0xb1, 0x15, 0x07, 0x22, 0x46, 0x66, 0xfe, 0x65, 0x0a, 0x94, 0xda,
+ 0xe4, 0x9d, 0x39, 0x70, 0x21, 0x83, 0x5e, 0xe5, 0xb2, 0x4b, 0x97, 0xfe,
+ 0xaf, 0x32, 0x08, 0x8e, 0x47, 0xcb, 0x97, 0x83, 0x89, 0xc0, 0xb6, 0xdb,
+ 0x6a, 0x14, 0x31, 0xd2, 0x53, 0xb5, 0x88, 0x30, 0x5f, 0x87, 0x50, 0x09,
+ 0x4f, 0x13, 0x20, 0x25, 0xa1, 0xc5, 0xbd, 0xf1, 0xe1, 0x10, 0x95, 0xfa,
+ 0x0e, 0xc3, 0xf7, 0xdf, 0xad, 0x90, 0x8b, 0xef, 0xfb,
+ /* e */
+ 0x00, 0x00, 0x00, 0x01, 0x23,
+ /* d */
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x9b, 0xaa, 0x82, 0x46, 0xb2, 0xed, 0x43,
+ 0x8c, 0x69, 0xcf, 0x87, 0x2e, 0x4d, 0x7d, 0xe2, 0x83, 0x42, 0x2f, 0xcd,
+ 0xbf, 0x38, 0x63, 0xf1, 0xcf, 0x39, 0x5a, 0x58, 0xab, 0xc4, 0xb8, 0x1b,
+ 0x6b, 0xbd, 0x35, 0x8a, 0xb9, 0x3d, 0x37, 0xc0, 0x85, 0x27, 0x30, 0xb2,
+ 0x81, 0x9f, 0xcb, 0xd9, 0xc9, 0xf8, 0x6b, 0x61, 0xcc, 0xf0, 0xab, 0x01,
+ 0x80, 0x99, 0xc5, 0x5d, 0x8c, 0x50, 0x14, 0x7b, 0x0f, 0xc6, 0x85, 0xe8,
+ 0x21, 0x93, 0xf3, 0x90, 0xbc, 0x75, 0xa9, 0x2b, 0x82, 0xb2, 0x60, 0x35,
+ 0x9d, 0xff, 0x1e, 0x97, 0x6e, 0x13, 0x14, 0xf8, 0x1f, 0x4e, 0x99, 0x6f,
+ 0x1f, 0x9d, 0xdb, 0x1e, 0xf3, 0xbb, 0x9f, 0xf5, 0x1f, 0xc5, 0x01, 0xa6,
+ 0x3a, 0x2b, 0x72, 0x73, 0x29, 0x4a, 0x8c, 0xa2, 0x58, 0xe9, 0xce, 0x58,
+ 0xca, 0xcb, 0xce, 0xaa, 0x92, 0x82, 0x1c, 0xd8, 0x57, 0x8b, 0x5e, 0x42,
+ 0x79, 0x21, 0x0e, 0x63, 0x13, 0x0e, 0x03, 0xff, 0x2f, 0x7f, 0x64, 0xf6,
+ 0x82, 0xe1, 0xfe, 0x0b, 0xc3, 0x1e, 0x4c, 0x50, 0x11, 0x3f, 0xc8, 0x8a,
+ 0xba, 0xcc, 0xde, 0x24, 0xf7, 0xae, 0x96, 0x6c, 0x5e, 0x3b, 0x00, 0xfa,
+ 0xf0, 0x0e, 0xac, 0x3a, 0xeb, 0xb1, 0xab, 0x8f, 0x3f, 0xdb, 0x80, 0xb3,
+ 0x06, 0x91, 0x18, 0xe1, 0xf5, 0x3b, 0xec, 0x5d, 0x01, 0xcf, 0xd0, 0x1f,
+ 0xaf, 0xe3, 0xd9, 0x12, 0xba, 0x7b, 0x0f, 0xee, 0x20, 0x29, 0x74, 0x57,
+ 0xdc, 0x58, 0x75, 0xd4, 0xb0, 0xf4, 0xb4, 0xa4, 0x93, 0x48, 0x2b, 0x7b,
+ 0x6b, 0x1d, 0x77, 0xbc, 0xf3, 0xfe, 0xbd, 0xad, 0xd6, 0x83, 0x05, 0x16,
+ 0xca, 0xbe, 0x31, 0xa4, 0x39, 0x53, 0x29, 0xf3, 0xd3, 0x39, 0xb0, 0xa5,
+ 0xef, 0xf0, 0xc9, 0x08, 0xd6, 0x63, 0x52, 0x0b, 0xcb, 0xfc, 0x1c, 0x21,
+ 0xd3, 0xa9, 0x2f, 0x23, 0x92, 0x3d, 0x46, 0x8c, 0x4b,
+ /* iqmp */
+ 0x00, 0x00, 0x00, 0x80, 0x15, 0x40, 0xcc, 0xa4, 0x83, 0xdf, 0x26, 0xbe,
+ 0x55, 0x82, 0x85, 0x0f, 0x71, 0x3c, 0x19, 0xa8, 0x8b, 0x42, 0x80, 0xa5,
+ 0x24, 0x5d, 0xad, 0xf5, 0x99, 0x33, 0xaf, 0x7c, 0xb2, 0x27, 0xae, 0x7b,
+ 0x0b, 0x0b, 0xa0, 0x03, 0xfd, 0xae, 0x53, 0x6f, 0xf1, 0xdd, 0x83, 0x54,
+ 0xde, 0xf2, 0xbd, 0x87, 0x2c, 0xa9, 0x4d, 0x7b, 0xa5, 0x6e, 0xdb, 0x5e,
+ 0x89, 0xf4, 0x5c, 0x79, 0x22, 0xc3, 0xc4, 0x40, 0x50, 0xeb, 0xb7, 0xf4,
+ 0x17, 0x78, 0x2f, 0x06, 0xa5, 0x3a, 0x65, 0x4d, 0x85, 0x98, 0x3e, 0xd8,
+ 0x4d, 0x3b, 0xfc, 0xd8, 0x9b, 0xe5, 0xd1, 0x47, 0xb6, 0xe3, 0xda, 0x2e,
+ 0xc5, 0x18, 0xce, 0x37, 0xd9, 0xd7, 0x9a, 0xbf, 0xba, 0xa9, 0xef, 0xf2,
+ 0xaf, 0x9b, 0xc8, 0x46, 0x57, 0x11, 0x8c, 0xa9, 0x5f, 0x68, 0x8c, 0x43,
+ 0x2f, 0xb5, 0x7a, 0x39, 0x38, 0x30, 0x79, 0xd5, 0x30, 0xa8, 0x2b, 0x98,
+ /* p */
+ 0x00, 0x00, 0x00, 0x81, 0x00, 0xcc, 0x50, 0xb1, 0x2c, 0x5f, 0xe4, 0x02,
+ 0x85, 0x7d, 0xce, 0x77, 0xd8, 0x27, 0xc1, 0xf6, 0xee, 0xe2, 0x2b, 0x7b,
+ 0x29, 0x83, 0x95, 0xf1, 0x5e, 0x3d, 0xe5, 0xa9, 0x75, 0x62, 0xc6, 0x84,
+ 0xc9, 0x97, 0x26, 0x70, 0xf4, 0x0d, 0x28, 0x6a, 0xc6, 0x88, 0x7c, 0xa3,
+ 0x0d, 0x35, 0xa3, 0x8f, 0xdc, 0x34, 0x4c, 0x78, 0x6b, 0xcc, 0x5d, 0x99,
+ 0x7e, 0x45, 0xb0, 0xdf, 0xe3, 0x77, 0x48, 0x77, 0xd8, 0xa9, 0x1c, 0x74,
+ 0xf9, 0xbc, 0xcc, 0x82, 0xdb, 0x44, 0x10, 0x96, 0xda, 0x00, 0x23, 0xaa,
+ 0x04, 0x93, 0xcc, 0x98, 0xec, 0x26, 0x8b, 0x7d, 0x08, 0xf4, 0x82, 0xdc,
+ 0x9a, 0xc4, 0x8c, 0xc8, 0xe9, 0x3e, 0x5b, 0xd6, 0xc7, 0x28, 0xf4, 0x38,
+ 0x3a, 0x3c, 0x08, 0x56, 0xbb, 0xa2, 0xca, 0xfb, 0x05, 0xa0, 0xb7, 0xe1,
+ 0x70, 0x59, 0xb4, 0x86, 0x2b, 0x29, 0x89, 0xb5, 0x82, 0x2a, 0x79, 0x61,
+ 0x51,
+ /* q */
+ 0x00, 0x00, 0x00, 0x81, 0x00, 0xc8, 0xc7, 0xe6, 0x93, 0x90, 0x59, 0xe7,
+ 0x54, 0x1b, 0xcf, 0x9c, 0xb0, 0x07, 0x80, 0x37, 0xcd, 0xdf, 0x65, 0xf4,
+ 0x29, 0x1e, 0x4a, 0x93, 0x73, 0xd1, 0x7b, 0x47, 0x1d, 0x36, 0x87, 0x89,
+ 0x1d, 0xbf, 0xd5, 0x1e, 0x02, 0xc2, 0xd1, 0x2b, 0xb3, 0x67, 0x07, 0x65,
+ 0xf9, 0xbc, 0xcb, 0x74, 0x4c, 0x83, 0x68, 0xa8, 0x6d, 0x30, 0x68, 0x8f,
+ 0xb5, 0xb9, 0x44, 0x86, 0xb8, 0xde, 0x4e, 0xfc, 0x02, 0x1e, 0x9c, 0x05,
+ 0x3b, 0x23, 0x1b, 0xdf, 0x79, 0x58, 0x73, 0x51, 0x27, 0xf0, 0xbd, 0x83,
+ 0x34, 0x38, 0xcb, 0xd0, 0x20, 0x12, 0xcd, 0x1a, 0x07, 0x6e, 0xf7, 0x0a,
+ 0x92, 0x29, 0xff, 0x2f, 0xbf, 0x30, 0x2a, 0x69, 0x15, 0x4d, 0x8e, 0x6e,
+ 0x17, 0x26, 0x7b, 0x43, 0xfe, 0x52, 0xd1, 0x83, 0x65, 0x19, 0x22, 0x8b,
+ 0xd3, 0x6f, 0x97, 0x51, 0x11, 0x3f, 0x17, 0xfe, 0x05, 0xcc, 0xa4, 0x49,
+ 0x8b
+};
+
+void
+prepare_request_identities (EggBuffer *req)
+{
+ gboolean ret;
+
+ egg_buffer_reset (req);
+
+ ret = egg_buffer_add_uint32 (req, 1);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_REQUEST_IDENTITIES);
+ g_assert_true (ret);
+}
+
+void
+check_identities_answer (EggBuffer *resp, gsize count)
+{
+ uint32_t length;
+ unsigned char code;
+ size_t offset;
+ gboolean ret;
+
+ offset = 0;
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+ g_assert_cmpint (length, ==, resp->len - 4);
+
+ code = 0;
+ ret = egg_buffer_get_byte (resp, offset, &offset, &code);
+ g_assert_true (ret);
+ g_assert_cmpint (code, ==, GCR_SSH_RES_IDENTITIES_ANSWER);
+
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+ g_assert_cmpint (length, ==, count);
+}
+
+void
+prepare_add_identity (EggBuffer *req)
+{
+ gboolean ret;
+
+ egg_buffer_reset (req);
+
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_ADD_IDENTITY);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (req, "ssh-rsa");
+ g_assert_true (ret);
+
+ ret = egg_buffer_append (req, private_blob, G_N_ELEMENTS(private_blob));
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (req, "comment");
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
+ g_assert_true (ret);
+}
+
+GBytes *
+public_key_from_file (const gchar *path, gchar **comment)
+{
+ GBytes *public_bytes;
+ GBytes *public_key;
+
+ GError *error = NULL;
+ gchar *contents;
+ gsize length;
+
+ if (!g_file_get_contents (path, &contents, &length, &error)) {
+ g_message ("couldn't read file: %s: %s", path, error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ public_bytes = g_bytes_new_take (contents, length);
+ public_key = _gcr_ssh_agent_parse_public_key (public_bytes, comment);
+ g_bytes_unref (public_bytes);
+
+ return public_key;
+}
+
+void
+prepare_remove_identity (EggBuffer *req)
+{
+ GBytes *public_key;
+ gchar *comment;
+ gsize length;
+ const guchar *blob;
+ gboolean ret;
+
+ public_key = public_key_from_file (SRCDIR "/pkcs11/ssh-store/fixtures/id_rsa_plain.pub", &comment);
+ g_free (comment);
+ blob = g_bytes_get_data (public_key, &length);
+
+ egg_buffer_reset (req);
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_REMOVE_IDENTITY);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte_array (req, blob, length);
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
+ g_assert_true (ret);
+
+ g_bytes_unref (public_key);
+}
+
+void
+prepare_remove_all_identities (EggBuffer *req)
+{
+ gboolean ret;
+
+ egg_buffer_reset (req);
+ ret = egg_buffer_add_uint32 (req, 1);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_REMOVE_ALL_IDENTITIES);
+ g_assert_true (ret);
+}
+
+void
+check_response (EggBuffer *resp, unsigned char expected)
+{
+ uint32_t length;
+ unsigned char code;
+ size_t offset;
+ gboolean ret;
+
+ offset = 0;
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+ g_assert_cmpint (length, ==, resp->len - 4);
+
+ code = 0;
+ ret = egg_buffer_get_byte (resp, offset, &offset, &code);
+ g_assert_true (ret);
+ g_assert_cmpint (expected, ==, code);
+}
+
+void
+check_success (EggBuffer *resp)
+{
+ check_response (resp, GCR_SSH_RES_SUCCESS);
+}
+
+void
+check_failure (EggBuffer *resp)
+{
+ check_response (resp, GCR_SSH_RES_FAILURE);
+}
+
+void
+prepare_sign_request (EggBuffer *req)
+{
+ GBytes *public_key;
+ gchar *comment;
+ gsize length;
+ const guchar *blob;
+ gboolean ret;
+
+ public_key = public_key_from_file (SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_plain.pub", &comment);
+ g_free (comment);
+ blob = g_bytes_get_data (public_key, &length);
+
+ egg_buffer_reset (req);
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_SIGN_REQUEST);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte_array (req, blob, length);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (req, "data");
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
+ g_assert_true (ret);
+
+ g_bytes_unref (public_key);
+}
+
+void
+check_sign_response (EggBuffer *resp)
+{
+ uint32_t length;
+ unsigned char code;
+ size_t offset;
+ gboolean ret;
+
+ offset = 0;
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+ g_assert_cmpint (length, ==, resp->len - 4);
+
+ code = 0;
+ ret = egg_buffer_get_byte (resp, offset, &offset, &code);
+ g_assert_true (ret);
+ g_assert_cmpint (code, ==, GCR_SSH_RES_SIGN_RESPONSE);
+
+ ret = egg_buffer_get_uint32 (resp, offset, &offset, &length);
+ g_assert_true (ret);
+}
diff --git a/gcr/test-ssh-agent-common.h b/gcr/test-ssh-agent-common.h
new file mode 100644
index 0000000..f4849fd
--- /dev/null
+++ b/gcr/test-ssh-agent-common.h
@@ -0,0 +1,94 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daiki Ueno
+ */
+
+#include <glib.h>
+#include "egg/egg-buffer.h"
+
+void prepare_request_identities (EggBuffer *req);
+void prepare_add_identity (EggBuffer *req);
+void prepare_remove_identity (EggBuffer *req);
+void prepare_remove_all_identities (EggBuffer *req);
+void prepare_sign_request (EggBuffer *req);
+
+void check_identities_answer (EggBuffer *resp, gsize count);
+void check_sign_response (EggBuffer *resp);
+void check_response (EggBuffer *resp, unsigned char expected);
+void check_success (EggBuffer *resp);
+void check_failure (EggBuffer *resp);
+
+GBytes *public_key_from_file (const gchar *path, gchar **comment);
+
+#define DEFINE_CALL_FUNCS(Test, Call) \
+static inline void \
+call_request_identities (Test *test, gsize count) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_request_identities (&test->req); \
+ Call (test); \
+ check_identities_answer (&test->resp, count); \
+} \
+ \
+static inline void \
+call_add_identity (Test *test) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_add_identity (&test->req); \
+ Call (test); \
+ check_success (&test->resp); \
+} \
+ \
+static inline void \
+call_remove_identity (Test *test) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_remove_identity (&test->req); \
+ Call (test); \
+ check_success (&test->resp); \
+} \
+ \
+static inline void \
+call_remove_all_identities (Test *test) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_remove_all_identities (&test->req); \
+ Call (test); \
+ check_success (&test->resp); \
+} \
+ \
+static inline void \
+call_sign (Test *test) \
+{ \
+ egg_buffer_reset (&test->req); \
+ egg_buffer_reset (&test->resp); \
+ \
+ prepare_sign_request (&test->req); \
+ Call (test); \
+ check_sign_response (&test->resp); \
+}
diff --git a/gcr/test-ssh-agent-preload.c b/gcr/test-ssh-agent-preload.c
new file mode 100644
index 0000000..ddf27c4
--- /dev/null
+++ b/gcr/test-ssh-agent-preload.c
@@ -0,0 +1,166 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daiki Ueno
+ */
+
+#include "config.h"
+
+#include "gcr-ssh-agent-preload.h"
+#include "egg/egg-testing.h"
+
+#include <glib/gstdio.h>
+#include <unistd.h>
+
+typedef struct {
+ gchar *directory;
+ GcrSshAgentPreload *preload;
+} Test;
+
+static void
+setup (Test *test, gconstpointer unused)
+{
+ test->directory = egg_tests_create_scratch_directory (NULL, NULL);
+
+ egg_tests_copy_scratch_file (test->directory, SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_plain");
+ egg_tests_copy_scratch_file (test->directory, SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_plain.pub");
+
+ test->preload = gcr_ssh_agent_preload_new (test->directory);
+}
+
+static void
+teardown (Test *test, gconstpointer unused)
+{
+ g_object_unref (test->preload);
+
+ egg_tests_remove_scratch_directory (test->directory);
+ g_free (test->directory);
+}
+
+static void
+test_list (Test *test, gconstpointer unused)
+{
+ GList *keys;
+
+ keys = gcr_ssh_agent_preload_get_keys (test->preload);
+ g_assert_cmpint (1, ==, g_list_length (keys));
+ g_list_free_full (keys, (GDestroyNotify)gcr_ssh_agent_key_info_free);
+}
+
+static void
+test_added (Test *test, gconstpointer unused)
+{
+ GList *keys;
+
+ keys = gcr_ssh_agent_preload_get_keys (test->preload);
+ g_assert_cmpint (1, ==, g_list_length (keys));
+ g_list_free_full (keys, (GDestroyNotify)gcr_ssh_agent_key_info_free);
+
+ /* Mtime must change so wait between tests */
+ sleep (1);
+
+ egg_tests_copy_scratch_file (test->directory, SRCDIR "/gcr/fixtures/ssh-agent/id_ecdsa_plain");
+ egg_tests_copy_scratch_file (test->directory, SRCDIR "/gcr/fixtures/ssh-agent/id_ecdsa_plain.pub");
+
+ keys = gcr_ssh_agent_preload_get_keys (test->preload);
+ g_assert_cmpint (2, ==, g_list_length (keys));
+ g_list_free_full (keys, (GDestroyNotify)gcr_ssh_agent_key_info_free);
+}
+
+static void
+test_removed (Test *test, gconstpointer unused)
+{
+ GList *keys;
+ gchar *path;
+
+ keys = gcr_ssh_agent_preload_get_keys (test->preload);
+ g_assert_cmpint (1, ==, g_list_length (keys));
+ g_list_free_full (keys, (GDestroyNotify)gcr_ssh_agent_key_info_free);
+
+ /* Mtime must change so wait between tests */
+ sleep (1);
+
+ path = g_build_filename (test->directory, "id_rsa_plain.pub", NULL);
+ g_unlink (path);
+ g_free (path);
+
+ path = g_build_filename (test->directory, "id_rsa_plain", NULL);
+ g_unlink (path);
+ g_free (path);
+
+ keys = gcr_ssh_agent_preload_get_keys (test->preload);
+ g_assert_cmpint (0, ==, g_list_length (keys));
+ g_list_free_full (keys, (GDestroyNotify)gcr_ssh_agent_key_info_free);
+}
+
+static void
+test_changed (Test *test, gconstpointer unused)
+{
+ GList *keys;
+ gchar *path;
+ gchar *contents;
+ gsize length;
+ GError *error;
+ gchar *p;
+ gboolean ret;
+
+ keys = gcr_ssh_agent_preload_get_keys (test->preload);
+ g_assert_cmpint (1, ==, g_list_length (keys));
+ g_list_free_full (keys, (GDestroyNotify)gcr_ssh_agent_key_info_free);
+
+ /* Mtime must change so wait between tests */
+ sleep (1);
+
+ path = g_build_filename (test->directory, "id_rsa_plain.pub", NULL);
+ error = NULL;
+ ret = g_file_get_contents (path, &contents, &length, &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+
+#define COMMENT "comment"
+ contents = g_realloc (contents, length + strlen (COMMENT) + 1);
+ p = strchr (contents, '\n');
+ g_assert_nonnull (p);
+ memcpy (p, " " COMMENT "\n", strlen (COMMENT) + 2);
+ error = NULL;
+ ret = g_file_set_contents (path, contents, length + strlen (COMMENT), &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+ g_free (path);
+ g_free (contents);
+
+ keys = gcr_ssh_agent_preload_get_keys (test->preload);
+ g_assert_cmpint (1, ==, g_list_length (keys));
+ g_assert_cmpstr (COMMENT, ==, ((GcrSshAgentKeyInfo *)keys->data)->comment);
+ g_list_free_full (keys, (GDestroyNotify)gcr_ssh_agent_key_info_free);
+#undef COMMENT
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/ssh-agent/preload/list", Test, NULL, setup, test_list, teardown);
+ g_test_add ("/ssh-agent/preload/added", Test, NULL, setup, test_added, teardown);
+ g_test_add ("/ssh-agent/preload/removed", Test, NULL, setup, test_removed, teardown);
+ g_test_add ("/ssh-agent/preload/changed", Test, NULL, setup, test_changed, teardown);
+
+ return g_test_run ();
+}
diff --git a/gcr/test-ssh-agent-process.c b/gcr/test-ssh-agent-process.c
new file mode 100644
index 0000000..8136d35
--- /dev/null
+++ b/gcr/test-ssh-agent-process.c
@@ -0,0 +1,219 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daiki Ueno
+ */
+
+#include "config.h"
+
+#include "gcr-ssh-agent-private.h"
+#include "gcr-ssh-agent-process.h"
+#include "gcr-ssh-agent-util.h"
+#include "gcr-ssh-agent-test.h"
+#include "egg/egg-testing.h"
+
+#include <glib.h>
+
+typedef struct {
+ gchar *directory;
+ EggBuffer req;
+ EggBuffer resp;
+ GcrSshAgentProcess *process;
+ GSocketConnection *connection;
+ GMainLoop *loop;
+} Test;
+
+static void
+setup (Test *test, gconstpointer unused)
+{
+ gchar *path;
+
+ test->directory = egg_tests_create_scratch_directory (NULL, NULL);
+
+ egg_buffer_init_full (&test->req, 128, (EggBufferAllocator)g_realloc);
+ egg_buffer_init_full (&test->resp, 128, (EggBufferAllocator)g_realloc);
+
+ path = g_strdup_printf ("%s/.ssh.sock", test->directory);
+ test->process = gcr_ssh_agent_process_new (path);
+ g_free (path);
+ g_assert_nonnull (test->process);
+ test->connection = NULL;
+}
+
+static void
+teardown (Test *test, gconstpointer unused)
+{
+ g_clear_object (&test->process);
+ g_clear_object (&test->connection);
+
+ egg_buffer_uninit (&test->req);
+ egg_buffer_uninit (&test->resp);
+
+ egg_tests_remove_scratch_directory (test->directory);
+ free (test->directory);
+}
+
+static void
+connect_to_process (Test *test)
+{
+ GError *error;
+
+ error = NULL;
+ test->connection = gcr_ssh_agent_process_connect (test->process, NULL, &error);
+ g_assert_nonnull (test->connection);
+ g_assert_no_error (error);
+}
+
+static void
+test_connect (Test *test, gconstpointer unused)
+{
+ connect_to_process (test);
+}
+
+static void
+call (Test *test)
+{
+ GError *error;
+ gboolean ret;
+
+ error = NULL;
+ ret = _gcr_ssh_agent_call (test->connection, &test->req, &test->resp, NULL, &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+}
+
+DEFINE_CALL_FUNCS(Test, call)
+
+static void
+test_list (Test *test, gconstpointer unused)
+{
+ connect_to_process (test);
+ call_request_identities(test, 0);
+}
+
+static void
+test_add (Test *test, gconstpointer unused)
+{
+ connect_to_process (test);
+ call_add_identity (test);
+ call_request_identities (test, 1);
+}
+
+static void
+test_remove (Test *test, gconstpointer unused)
+{
+ connect_to_process (test);
+ call_add_identity (test);
+ call_request_identities (test, 1);
+
+ call_remove_identity (test);
+ call_request_identities (test, 0);
+}
+
+static void
+test_remove_all (Test *test, gconstpointer unused)
+{
+ connect_to_process (test);
+ call_add_identity (test);
+ call_request_identities (test, 1);
+
+ call_remove_all_identities (test);
+ call_request_identities (test, 0);
+}
+
+static void
+test_sign (Test *test, gconstpointer unused)
+{
+ connect_to_process (test);
+ call_add_identity (test);
+ call_request_identities (test, 1);
+
+ call_sign (test);
+
+ call_remove_all_identities (test);
+ call_request_identities (test, 0);
+}
+
+static gpointer
+kill_thread (gpointer data)
+{
+ Test *test = data;
+ GPid pid;
+
+ pid = gcr_ssh_agent_process_get_pid (test->process);
+ g_assert_cmpint (-1, !=, pid);
+
+ kill (pid, SIGTERM);
+
+ return NULL;
+}
+
+static void
+on_closed (GcrSshAgentProcess *self, gpointer data)
+{
+ GMainLoop *loop = data;
+
+ g_main_loop_quit (loop);
+ g_main_loop_unref (loop);
+}
+
+static void
+test_restart (Test *test, gconstpointer unused)
+{
+ GPid pid;
+ GMainLoop *loop;
+ GThread *thread;
+
+ connect_to_process (test);
+
+ pid = gcr_ssh_agent_process_get_pid (test->process);
+ g_assert_cmpint (0, !=, pid);
+
+ thread = g_thread_new ("kill", kill_thread, test);
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (test->process, "closed", G_CALLBACK (on_closed), loop);
+ g_main_loop_run (loop);
+
+ g_thread_join (thread);
+
+ pid = gcr_ssh_agent_process_get_pid (test->process);
+ g_assert_cmpint (0, ==, pid);
+
+ connect_to_process (test);
+
+ pid = gcr_ssh_agent_process_get_pid (test->process);
+ g_assert_cmpint (0, !=, pid);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/ssh-agent/process/connect", Test, NULL, setup, test_connect, teardown);
+ g_test_add ("/ssh-agent/process/list", Test, NULL, setup, test_list, teardown);
+ g_test_add ("/ssh-agent/process/add", Test, NULL, setup, test_add, teardown);
+ g_test_add ("/ssh-agent/process/remove", Test, NULL, setup, test_remove, teardown);
+ g_test_add ("/ssh-agent/process/remove_all", Test, NULL, setup, test_remove_all, teardown);
+ g_test_add ("/ssh-agent/process/sign", Test, NULL, setup, test_sign, teardown);
+ g_test_add ("/ssh-agent/process/restart", Test, NULL, setup, test_restart, teardown);
+
+ return g_test_run ();
+}
diff --git a/gcr/test-ssh-agent-service.c b/gcr/test-ssh-agent-service.c
new file mode 100644
index 0000000..80afc79
--- /dev/null
+++ b/gcr/test-ssh-agent-service.c
@@ -0,0 +1,618 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daiki Ueno
+ */
+
+#include "config.h"
+
+#include "gcr-ssh-agent-service.h"
+#include "gcr-ssh-agent-private.h"
+#include "gcr-ssh-agent-util.h"
+#include "gcr-ssh-agent-test.h"
+#include "egg/egg-testing.h"
+#include "egg/mock-interaction.h"
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gunixsocketaddress.h>
+
+typedef struct {
+ gchar *directory;
+ EggBuffer req;
+ EggBuffer resp;
+ GcrSshAgentService *service;
+ GMainContext *server_thread_context;
+ volatile gint server_thread_stop;
+ GSocketConnection *connection;
+ GThread *thread;
+ GMutex lock;
+ GCond cond;
+} Test;
+
+static gpointer
+server_thread (gpointer data)
+{
+ Test *test = data;
+ gboolean ret;
+
+ g_main_context_push_thread_default (test->server_thread_context);
+
+ ret = gcr_ssh_agent_service_start (test->service);
+ g_assert_true (ret);
+
+ g_mutex_lock (&test->lock);
+ g_cond_signal (&test->cond);
+ g_mutex_unlock (&test->lock);
+
+ while (g_atomic_int_get (&test->server_thread_stop) == 0)
+ g_main_context_iteration (test->server_thread_context, TRUE);
+
+ g_main_context_pop_thread_default (test->server_thread_context);
+
+ return NULL;
+}
+
+static void
+connect_to_server (Test *test)
+{
+ const gchar *envvar;
+ GSocketClient *client;
+ GSocketAddress *address;
+ GError *error;
+
+ envvar = g_getenv ("SSH_AUTH_SOCK");
+ g_assert_nonnull (envvar);
+ address = g_unix_socket_address_new (envvar);
+
+ client = g_socket_client_new ();
+
+ error = NULL;
+ test->connection = g_socket_client_connect (client,
+ G_SOCKET_CONNECTABLE (address),
+ NULL,
+ &error);
+ g_assert_nonnull (test->connection);
+ g_assert_no_error (error);
+
+ g_object_unref (address);
+ g_object_unref (client);
+}
+
+static void
+setup (Test *test, gconstpointer unused)
+{
+ GTlsInteraction *interaction;
+ GcrSshAgentPreload *preload;
+ gchar *sockets_path;
+ gchar *preload_path;
+ gchar *path;
+
+ test->directory = egg_tests_create_scratch_directory (NULL, NULL);
+
+ sockets_path = g_build_filename (test->directory, "sockets", NULL);
+ g_mkdir (sockets_path, 0700);
+
+ preload_path = g_build_filename (test->directory, "preload", NULL);
+ g_mkdir (preload_path, 0700);
+
+ egg_tests_copy_scratch_file (preload_path, SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_plain");
+ egg_tests_copy_scratch_file (preload_path, SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_plain.pub");
+
+ path = g_build_filename (preload_path, "id_rsa_plain", NULL);
+ g_chmod (path, 0600);
+ g_free (path);
+
+ egg_buffer_init_full (&test->req, 128, (EggBufferAllocator)g_realloc);
+ egg_buffer_init_full (&test->resp, 128, (EggBufferAllocator)g_realloc);
+
+ preload = gcr_ssh_agent_preload_new (preload_path);
+ g_free (preload_path);
+
+ test->service = gcr_ssh_agent_service_new (sockets_path, preload);
+ g_free (sockets_path);
+
+ interaction = mock_interaction_new ("password");
+ g_object_set (test->service, "interaction", interaction, NULL);
+
+ g_object_unref (interaction);
+ g_object_unref (preload);
+
+ g_mutex_init (&test->lock);
+ g_cond_init (&test->cond);
+ test->server_thread_context = g_main_context_new ();
+
+ test->thread = g_thread_new ("ssh-agent", server_thread, test);
+
+ /* Wait until the server is up */
+ g_mutex_lock (&test->lock);
+ g_cond_wait (&test->cond, &test->lock);
+ g_mutex_unlock (&test->lock);
+}
+
+static void
+teardown (Test *test, gconstpointer unused)
+{
+ g_atomic_int_set (&test->server_thread_stop, 1);
+ g_main_context_wakeup (test->server_thread_context);
+ g_thread_join (test->thread);
+
+ g_main_context_unref (test->server_thread_context);
+
+ g_clear_object (&test->connection);
+
+ gcr_ssh_agent_service_stop (test->service);
+ g_object_unref (test->service);
+
+ egg_buffer_uninit (&test->req);
+ egg_buffer_uninit (&test->resp);
+
+ egg_tests_remove_scratch_directory (test->directory);
+ g_free (test->directory);
+
+ g_cond_clear (&test->cond);
+ g_mutex_clear (&test->lock);
+}
+
+static void
+call (Test *test)
+{
+ GError *error;
+ gboolean ret;
+
+ error = NULL;
+ ret = _gcr_ssh_agent_write_packet (test->connection, &test->req, NULL, &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+
+ error = NULL;
+ ret = _gcr_ssh_agent_read_packet (test->connection, &test->resp, NULL, &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+}
+
+static void
+call_error_or_failure (Test *test, gint dom, gint code)
+{
+ GError *error;
+ gboolean ret;
+
+ error = NULL;
+ ret = _gcr_ssh_agent_write_packet (test->connection, &test->req, NULL, &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+
+ error = NULL;
+ ret = _gcr_ssh_agent_read_packet (test->connection, &test->resp, NULL, &error);
+ if (ret)
+ check_failure (&test->resp);
+ else {
+ g_assert_false (ret);
+ g_assert_error (error, dom, code);
+ }
+}
+
+DEFINE_CALL_FUNCS(Test, call)
+
+static void
+call_unparseable_add (Test *test)
+{
+ egg_buffer_reset (&test->req);
+ egg_buffer_reset (&test->resp);
+
+ prepare_add_identity (&test->req);
+ egg_buffer_set_uint32 (&test->req, 5, 0x80000000);
+ call_error_or_failure (test, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED);
+}
+
+static void
+call_unparseable_remove (Test *test)
+{
+ egg_buffer_reset (&test->req);
+ egg_buffer_reset (&test->resp);
+
+ prepare_remove_identity (&test->req);
+ egg_buffer_set_uint32 (&test->req, 5, 0x80000000);
+ call_error_or_failure (test, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED);
+}
+
+static void
+call_unparseable_sign (Test *test)
+{
+ egg_buffer_reset (&test->req);
+ egg_buffer_reset (&test->resp);
+
+ prepare_sign_request (&test->req);
+ egg_buffer_set_uint32 (&test->req, 5, 0x80000000);
+ call_error_or_failure (test, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED);
+}
+
+static void
+prepare_sign_request_unknown (EggBuffer *req)
+{
+ GBytes *public_key;
+ gchar *comment;
+ gsize length;
+ const guchar *blob;
+ gboolean ret;
+
+ public_key = public_key_from_file (SRCDIR "/gcr/fixtures/ssh-agent/id_ecdsa_plain.pub", &comment);
+ g_free (comment);
+ blob = g_bytes_get_data (public_key, &length);
+
+ egg_buffer_reset (req);
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (req, GCR_SSH_OP_SIGN_REQUEST);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte_array (req, blob, length);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (req, "data");
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_uint32 (req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (req, 0, req->len - 4);
+ g_assert_true (ret);
+
+ g_bytes_unref (public_key);
+}
+
+static void
+call_sign_unknown (Test *test)
+{
+ egg_buffer_reset (&test->req);
+ egg_buffer_reset (&test->resp);
+
+ prepare_sign_request_unknown (&test->req);
+ call (test);
+ check_failure (&test->resp);
+}
+
+static void
+call_empty (Test *test)
+{
+ GError *error;
+ gboolean ret;
+
+ egg_buffer_reset (&test->req);
+ egg_buffer_reset (&test->resp);
+
+ ret = egg_buffer_add_uint32 (&test->req, 0);
+ g_assert_true (ret);
+
+ error = NULL;
+ ret = _gcr_ssh_agent_write_packet (test->connection, &test->req, NULL, &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+
+ error = NULL;
+ ret = _gcr_ssh_agent_read_packet (test->connection, &test->resp, NULL, &error);
+ g_assert_false (ret);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED);
+}
+
+static void
+call_unknown (Test *test)
+{
+ GError *error;
+ gboolean ret;
+
+ egg_buffer_reset (&test->req);
+ egg_buffer_reset (&test->resp);
+
+ ret = egg_buffer_add_uint32 (&test->req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (&test->req, 255);
+ g_assert_true (ret);
+
+ error = NULL;
+ ret = _gcr_ssh_agent_write_packet (test->connection, &test->req, NULL, &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+
+ error = NULL;
+ ret = _gcr_ssh_agent_read_packet (test->connection, &test->resp, NULL, &error);
+ g_assert_true (ret);
+ g_assert_no_error (error);
+
+ check_failure (&test->resp);
+}
+
+static void
+call_lock (Test *test)
+{
+ gboolean ret;
+
+ egg_buffer_reset (&test->req);
+ egg_buffer_reset (&test->resp);
+
+ ret = egg_buffer_add_uint32 (&test->req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (&test->req, GCR_SSH_OP_LOCK);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (&test->req, "password");
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (&test->req, 0, test->req.len - 4);
+ g_assert_true (ret);
+
+ call (test);
+
+ check_success (&test->resp);
+}
+
+static void
+call_unlock (Test *test)
+{
+ gboolean ret;
+
+ egg_buffer_reset (&test->req);
+ egg_buffer_reset (&test->resp);
+
+ ret = egg_buffer_add_uint32 (&test->req, 0);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_byte (&test->req, GCR_SSH_OP_UNLOCK);
+ g_assert_true (ret);
+
+ ret = egg_buffer_add_string (&test->req, "password");
+ g_assert_true (ret);
+
+ ret = egg_buffer_set_uint32 (&test->req, 0, test->req.len - 4);
+ g_assert_true (ret);
+
+ call (test);
+
+ check_success (&test->resp);
+}
+
+static void
+test_startup_shutdown (Test *test, gconstpointer unused)
+{
+}
+
+static void
+test_list (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_request_identities (test, 1);
+}
+
+static void
+test_add (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ /* Adding an identity from the preloaded location doesn't
+ * change the total number of keys returned from
+ * GCR_SSH_OP_REQUEST_IDENTITIES */
+ call_add_identity (test);
+ call_request_identities (test, 1);
+}
+
+static void
+test_unparseable_add (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_unparseable_add (test);
+}
+
+static void
+test_unparseable_remove (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_unparseable_remove (test); /* This closes the connection */
+}
+
+static void
+test_unparseable_sign (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_unparseable_sign (test); /* This closes the connection */
+}
+
+static void
+test_remove (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ /* Adding an identity from the preloaded location doesn't
+ * change the total number of keys returned from
+ * GCR_SSH_OP_REQUEST_IDENTITIES */
+ call_add_identity (test);
+ call_request_identities (test, 1);
+
+ /* Removing an identity from the preloaded location doesn't
+ * change the total number of keys returned from
+ * GCR_SSH_OP_REQUEST_IDENTITIES */
+ call_remove_identity (test);
+ call_request_identities (test, 1);
+}
+
+static void
+test_remove_all (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ /* Adding an identity from the preloaded location doesn't
+ * change the total number of keys returned from
+ * GCR_SSH_OP_REQUEST_IDENTITIES */
+ call_add_identity (test);
+ call_request_identities (test, 1);
+
+ /* Removing an identity from the preloaded location doesn't
+ * change the total number of keys returned from
+ * GCR_SSH_OP_REQUEST_IDENTITIES */
+ call_remove_all_identities (test);
+ call_request_identities (test, 1);
+}
+
+static void
+test_sign_loaded (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ /* Adding an identity from the preloaded location doesn't
+ * change the total number of keys returned from
+ * GCR_SSH_OP_REQUEST_IDENTITIES */
+ call_add_identity (test);
+ call_request_identities (test, 1);
+
+ call_sign (test);
+}
+
+static void
+test_sign (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_sign (test);
+}
+
+static void
+test_sign_unknown (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_sign_unknown (test);
+}
+
+static gpointer
+kill_thread (gpointer data)
+{
+ Test *test = data;
+ GcrSshAgentProcess *process;
+ GPid pid;
+
+ process = gcr_ssh_agent_service_get_process (test->service);
+ pid = gcr_ssh_agent_process_get_pid (process);
+ g_assert_cmpint (-1, !=, pid);
+
+ kill (pid, SIGTERM);
+
+ return NULL;
+}
+
+static void
+on_closed (GcrSshAgentProcess *self, gpointer data)
+{
+ GMainLoop *loop = data;
+
+ g_main_loop_quit (loop);
+ g_main_loop_unref (loop);
+}
+
+static void
+test_restart (Test *test, gconstpointer unused)
+{
+ GcrSshAgentProcess *process;
+ GThread *thread;
+ GMainLoop *loop;
+ GBytes *public_key;
+ gchar *comment;
+
+ connect_to_server (test);
+
+ public_key = public_key_from_file (SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_plain.pub", &comment);
+ g_free (comment);
+
+ call_add_identity (test);
+ call_request_identities (test, 1);
+
+ g_assert_true (gcr_ssh_agent_service_lookup_key (test->service, public_key));
+
+ thread = g_thread_new ("kill", kill_thread, test);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ process = gcr_ssh_agent_service_get_process (test->service);
+ g_signal_connect (process, "closed", G_CALLBACK (on_closed), loop);
+ g_main_loop_run (loop);
+
+ g_thread_join (thread);
+
+ g_assert_false (gcr_ssh_agent_service_lookup_key (test->service, public_key));
+
+ call_add_identity (test);
+ call_request_identities (test, 1);
+
+ g_assert_true (gcr_ssh_agent_service_lookup_key (test->service, public_key));
+ g_bytes_unref (public_key);
+}
+
+static void
+test_empty (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_empty (test);
+}
+
+static void
+test_unknown (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_unknown (test);
+}
+
+static void
+test_lock (Test *test, gconstpointer unused)
+{
+ connect_to_server (test);
+
+ call_lock (test);
+ call_unlock (test);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/ssh-agent/service/startup_shutdown", Test, NULL, setup, test_startup_shutdown,
teardown);
+ g_test_add ("/ssh-agent/service/list", Test, NULL, setup, test_list, teardown);
+ g_test_add ("/ssh-agent/service/add", Test, NULL, setup, test_add, teardown);
+ g_test_add ("/ssh-agent/service/remove", Test, NULL, setup, test_remove, teardown);
+ g_test_add ("/ssh-agent/service/remove_all", Test, NULL, setup, test_remove_all, teardown);
+ g_test_add ("/ssh-agent/service/sign_loaded", Test, NULL, setup, test_sign_loaded, teardown);
+ g_test_add ("/ssh-agent/service/sign", Test, NULL, setup, test_sign, teardown);
+ g_test_add ("/ssh-agent/service/sign_unknown", Test, NULL, setup, test_sign_unknown, teardown);
+ g_test_add ("/ssh-agent/service/empty", Test, NULL, setup, test_empty, teardown);
+ g_test_add ("/ssh-agent/service/unknown", Test, NULL, setup, test_unknown, teardown);
+ g_test_add ("/ssh-agent/service/unparseable_add", Test, NULL, setup, test_unparseable_add, teardown);
+ g_test_add ("/ssh-agent/service/unparseable_remove", Test, NULL, setup, test_unparseable_remove,
teardown);
+ g_test_add ("/ssh-agent/service/unparseable_sign", Test, NULL, setup, test_unparseable_sign,
teardown);
+ g_test_add ("/ssh-agent/service/restart", Test, NULL, setup, test_restart, teardown);
+ g_test_add ("/ssh-agent/service/lock", Test, NULL, setup, test_lock, teardown);
+
+ return g_test_run ();
+}
diff --git a/gcr/test-ssh-agent-util.c b/gcr/test-ssh-agent-util.c
new file mode 100644
index 0000000..ef4b202
--- /dev/null
+++ b/gcr/test-ssh-agent-util.c
@@ -0,0 +1,119 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Stef Walter <stef thewalter net>
+ */
+
+#include "config.h"
+
+#include "gcr-ssh-agent-util.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static struct {
+ const char *filename;
+ const char *encoded;
+} PUBLIC_FILES[] = {
+ { SRCDIR "/gcr/fixtures/ssh-agent/id_rsa_test.pub",
+
"AAAAB3NzaC1yc2EAAAABIwAAAQEAoD6VKqkhay6pKHSRjAGWWfFPU8xfsi2gnOwP/B1UHDoztx3czhO+py/fTlhCnSP1jsjkrVIZcnzah2fUNFFRgS4+jROBtvbgHsS72V1E6+ZogV+mBJWWAhw0iPrmQ3Kvm38D3PByo5Y7yKO5kIG2LloYLjosJ5F4sx2xh0uz2wXNtnY1b5xhe2+VEksm9OB+FXaUkZC2fQrTNo8ZGFJQSFd8kUhIfbUDJmlYuZ+vvHM+A3Lc9rHyW4IPaRyxFQciRmb+ZQqU2uSdOXAhg17lskuX/q8yCI5Hy5eDicC222oUMdJTtYgwX4dQCU8TICWhxb3x4RCV+g7D99+tkIvv+w=="
},
+ { SRCDIR "/gcr/fixtures/ssh-agent/id_dsa_test.pub",
+
"AAAAB3NzaC1kc3MAAACBANHNmw2YHEodUj4Ae27i8Rm8uoLnpS68QEiCJx8bv9P1o0AaD0w55sH+TBzlo7vtAEDlAzIOBY3PMpy5WarELTIeXmFPzKfHL8tuxMbOPaN/wDkDZNnJZsqlyRwlQKStPcAlvLBNuMjA53u2ndMTVghtUHXETQzwxKhXf7TmvfLBAAAAFQDnF/Y8MgFCP0PpRC5ZAQo1dyDEwwAAAIEAr4iOpTeZx8i1QgQpRl+dmbBAtHTXbPiophzNJBge9lixqF0T3egN2B9wGGnumIXmnst9RPPjuu+cHCLfxhXHzLlW8MLwoiF6ZQOx9M8WcfWIl5oiGyr2e969woRf5OcMGQPOQBdws6MEtemRqq5gu6dqDqVl3xfhSZSP9LpqAI8AAACAUjiuQ3qGErsCz++qd0qrR++QA185XGXAPZqQEHcr4iKSlO17hSUYA03kOWtDaeRtJOlxjIjl9iLo3juKGFgxUfo2StScOSO2saTWFGjA4MybHCK1+mIYXRcYrq314yK2Tmbql/UGDWpcCCGXLWpSFHTaXTbJjPd6VL+TO9/8tFk="
},
+ { SRCDIR "/gcr/fixtures/ssh-agent/identity.pub",
+ NULL }
+};
+
+#define COMMENT "A public key comment"
+
+static void
+test_parse_public (void)
+{
+ GBytes *input_bytes, *output_bytes;
+ gchar *comment;
+ guchar *data;
+ const guchar *blob;
+ gsize n_data;
+ gchar *encoded;
+ gsize i;
+
+ for (i = 0; i < G_N_ELEMENTS (PUBLIC_FILES); ++i) {
+ if (!g_file_get_contents (PUBLIC_FILES[i].filename, (gchar **)&data, &n_data, NULL))
+ g_assert_not_reached ();
+
+ input_bytes = g_bytes_new_take (data, n_data);
+ output_bytes = _gcr_ssh_agent_parse_public_key (input_bytes, &comment);
+ g_bytes_unref (input_bytes);
+ if (PUBLIC_FILES[i].encoded == NULL) {
+ g_assert (output_bytes == NULL);
+ } else {
+ g_assert (output_bytes);
+
+ blob = g_bytes_get_data (output_bytes, &n_data);
+ encoded = g_base64_encode (blob, n_data);
+ g_bytes_unref (output_bytes);
+ g_assert_cmpstr (encoded, ==, PUBLIC_FILES[i].encoded);
+ g_free (encoded);
+
+ g_assert_cmpstr (comment, ==, COMMENT);
+ g_free (comment);
+ }
+ }
+}
+
+static void
+test_canon_error (void)
+{
+ static const gchar input[] =
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n"
+ "@ WARNING: UNPROTECTED PRIVATE KEY FILE! @\r\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "Permissions 0620 for '/home/foo/.ssh/id_rsa' are too open.\r\n"
+ "It is required that your private key files are NOT accessible by others.\r\n"
+ "This private key will be ignored.\r\n";
+ static const gchar expected[] =
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@ WARNING: UNPROTECTED PRIVATE KEY FILE! @\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "Permissions 0620 for '/home/foo/.ssh/id_rsa' are too open.\n"
+ "It is required that your private key files are NOT accessible by others.\n"
+ "This private key will be ignored.\n";
+ gchar *p, *output;
+
+ p = g_strdup (input);
+ output = _gcr_ssh_agent_canon_error (p);
+
+ g_assert (output == p);
+ g_assert_cmpstr (expected, ==, output);
+
+ g_free (p);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/ssh-agent/util/parse_public", test_parse_public);
+ g_test_add_func ("/ssh-agent/util/canon_error", test_canon_error);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]