1
1
use log:: info;
2
2
3
- use ssh_agent:: proto :: { from_bytes , to_bytes } ;
3
+ use ssh_agent:: agent :: Agent ;
4
4
use ssh_agent:: proto:: message:: { self , Message , SignRequest } ;
5
- use ssh_agent:: proto:: signature:: { self , Signature } ;
6
- use ssh_agent:: proto:: public_key:: PublicKey ;
7
5
use ssh_agent:: proto:: private_key:: { PrivateKey , RsaPrivateKey } ;
8
- use ssh_agent:: agent:: Agent ;
6
+ use ssh_agent:: proto:: public_key:: PublicKey ;
7
+ use ssh_agent:: proto:: signature:: { self , Signature } ;
8
+ use ssh_agent:: proto:: { from_bytes, to_bytes} ;
9
9
10
- use std:: sync:: RwLock ;
11
10
use std:: error:: Error ;
12
11
use std:: fs:: remove_file;
12
+ use std:: sync:: RwLock ;
13
13
14
- use openssl:: sign:: Signer ;
15
- use openssl:: rsa:: Rsa ;
16
- use openssl:: pkey:: PKey ;
17
- use openssl:: hash:: MessageDigest ;
18
14
use openssl:: bn:: BigNum ;
15
+ use openssl:: hash:: MessageDigest ;
16
+ use openssl:: pkey:: PKey ;
19
17
use openssl:: pkey:: Private ;
18
+ use openssl:: rsa:: Rsa ;
19
+ use openssl:: sign:: Signer ;
20
20
21
21
#[ derive( Clone , PartialEq , Debug ) ]
22
22
struct Identity {
23
23
pubkey : PublicKey ,
24
24
privkey : PrivateKey ,
25
- comment : String
25
+ comment : String ,
26
26
}
27
27
28
28
struct KeyStorage {
29
- identities : RwLock < Vec < Identity > >
29
+ identities : RwLock < Vec < Identity > > ,
30
30
}
31
31
32
32
impl KeyStorage {
33
33
fn new ( ) -> Self {
34
34
Self {
35
- identities : RwLock :: new ( vec ! [ ] )
35
+ identities : RwLock :: new ( vec ! [ ] ) ,
36
36
}
37
37
}
38
-
39
- fn identity_index_from_pubkey (
40
- identities : & Vec < Identity > ,
41
- pubkey : & PublicKey
42
- ) -> Option < usize > {
38
+
39
+ fn identity_index_from_pubkey ( identities : & Vec < Identity > , pubkey : & PublicKey ) -> Option < usize > {
43
40
for ( index, identity) in identities. iter ( ) . enumerate ( ) {
44
41
if & identity. pubkey == pubkey {
45
42
return Some ( index) ;
46
43
}
47
44
}
48
45
return None ;
49
46
}
50
-
47
+
51
48
fn identity_from_pubkey ( & self , pubkey : & PublicKey ) -> Option < Identity > {
52
49
let identities = self . identities . read ( ) . unwrap ( ) ;
53
-
50
+
54
51
let index = Self :: identity_index_from_pubkey ( & identities, pubkey) ?;
55
52
Some ( identities[ index] . clone ( ) )
56
53
}
57
-
54
+
58
55
fn identity_add ( & self , identity : Identity ) {
59
56
let mut identities = self . identities . write ( ) . unwrap ( ) ;
60
57
if Self :: identity_index_from_pubkey ( & identities, & identity. pubkey ) == None {
61
58
identities. push ( identity) ;
62
59
}
63
60
}
64
-
61
+
65
62
fn identity_remove ( & self , pubkey : & PublicKey ) -> Result < ( ) , Box < dyn Error > > {
66
63
let mut identities = self . identities . write ( ) . unwrap ( ) ;
67
-
64
+
68
65
if let Some ( index) = Self :: identity_index_from_pubkey ( & identities, & pubkey) {
69
66
identities. remove ( index) ;
70
67
Ok ( ( ) )
71
68
} else {
72
69
Err ( From :: from ( "Failed to remove identity: identity not found" ) )
73
70
}
74
71
}
75
-
72
+
76
73
fn sign ( & self , sign_request : & SignRequest ) -> Result < Signature , Box < dyn Error > > {
77
74
let pubkey: PublicKey = from_bytes ( & sign_request. pubkey_blob ) ?;
78
-
75
+
79
76
if let Some ( identity) = self . identity_from_pubkey ( & pubkey) {
80
77
match identity. privkey {
81
78
PrivateKey :: Rsa ( ref key) => {
82
79
let algorithm;
83
80
let digest;
84
-
81
+
85
82
if sign_request. flags & signature:: RSA_SHA2_512 != 0 {
86
83
algorithm = "rsa-sha2-512" ;
87
84
digest = MessageDigest :: sha512 ( ) ;
@@ -92,54 +89,54 @@ impl KeyStorage {
92
89
algorithm = "ssh-rsa" ;
93
90
digest = MessageDigest :: sha1 ( ) ;
94
91
}
95
-
92
+
96
93
let keypair = PKey :: from_rsa ( rsa_openssl_from_ssh ( key) ?) ?;
97
94
let mut signer = Signer :: new ( digest, & keypair) ?;
98
95
signer. update ( & sign_request. data ) ?;
99
-
96
+
100
97
Ok ( Signature {
101
98
algorithm : algorithm. to_string ( ) ,
102
- blob : signer. sign_to_vec ( ) ?
99
+ blob : signer. sign_to_vec ( ) ?,
103
100
} )
104
- } ,
105
- _ => Err ( From :: from ( "Signature for key type not implemented" ) )
101
+ }
102
+ _ => Err ( From :: from ( "Signature for key type not implemented" ) ) ,
106
103
}
107
104
} else {
108
105
Err ( From :: from ( "Failed to create signature: identity not found" ) )
109
106
}
110
107
}
111
-
112
- fn handle_message ( & self , request : Message ) -> Result < Message , Box < dyn Error > > {
108
+
109
+ fn handle_message ( & self , request : Message ) -> Result < Message , Box < dyn Error > > {
113
110
info ! ( "Request: {:?}" , request) ;
114
111
let response = match request {
115
112
Message :: RequestIdentities => {
116
113
let mut identities = vec ! [ ] ;
117
114
for identity in self . identities . read ( ) . unwrap ( ) . iter ( ) {
118
115
identities. push ( message:: Identity {
119
116
pubkey_blob : to_bytes ( & identity. pubkey ) ?,
120
- comment : identity. comment . clone ( )
117
+ comment : identity. comment . clone ( ) ,
121
118
} )
122
119
}
123
120
Ok ( Message :: IdentitiesAnswer ( identities) )
124
- } ,
121
+ }
125
122
Message :: RemoveIdentity ( identity) => {
126
123
let pubkey: PublicKey = from_bytes ( & identity. pubkey_blob ) ?;
127
124
self . identity_remove ( & pubkey) ?;
128
125
Ok ( Message :: Success )
129
- } ,
126
+ }
130
127
Message :: AddIdentity ( identity) => {
131
128
self . identity_add ( Identity {
132
129
pubkey : PublicKey :: from ( & identity. privkey ) ,
133
130
privkey : identity. privkey ,
134
- comment : identity. comment
131
+ comment : identity. comment ,
135
132
} ) ;
136
133
Ok ( Message :: Success )
137
- } ,
134
+ }
138
135
Message :: SignRequest ( request) => {
139
136
let signature = to_bytes ( & self . sign ( & request) ?) ?;
140
137
Ok ( Message :: SignResponse ( signature) )
141
- } ,
142
- _ => Err ( From :: from ( format ! ( "Unknown message: {:?}" , request) ) )
138
+ }
139
+ _ => Err ( From :: from ( format ! ( "Unknown message: {:?}" , request) ) ) ,
143
140
} ;
144
141
info ! ( "Response {:?}" , response) ;
145
142
return response;
@@ -148,7 +145,7 @@ impl KeyStorage {
148
145
149
146
impl Agent for KeyStorage {
150
147
type Error = ( ) ;
151
-
148
+
152
149
fn handle ( & self , message : Message ) -> Result < Message , ( ) > {
153
150
self . handle_message ( message) . or_else ( |error| {
154
151
println ! ( "Error handling message - {:?}" , error) ;
@@ -157,7 +154,6 @@ impl Agent for KeyStorage {
157
154
}
158
155
}
159
156
160
-
161
157
fn rsa_openssl_from_ssh ( ssh_rsa : & RsaPrivateKey ) -> Result < Rsa < Private > , Box < dyn Error > > {
162
158
let n = BigNum :: from_slice ( & ssh_rsa. n ) ?;
163
159
let e = BigNum :: from_slice ( & ssh_rsa. e ) ?;
@@ -167,15 +163,15 @@ fn rsa_openssl_from_ssh(ssh_rsa: &RsaPrivateKey) -> Result<Rsa<Private>, Box<dyn
167
163
let q = BigNum :: from_slice ( & ssh_rsa. q ) ?;
168
164
let dp = & d % & ( & p - & BigNum :: from_u32 ( 1 ) ?) ;
169
165
let dq = & d % & ( & q - & BigNum :: from_u32 ( 1 ) ?) ;
170
-
166
+
171
167
Ok ( Rsa :: from_private_components ( n, e, d, p, q, dp, dq, qi) ?)
172
168
}
173
169
174
170
fn main ( ) -> Result < ( ) , Box < dyn Error + Send + Sync > > {
175
171
let agent = KeyStorage :: new ( ) ;
176
172
let socket = "connect.sock" ;
177
173
let _ = remove_file ( socket) ;
178
-
174
+
179
175
env_logger:: init ( ) ;
180
176
agent. run_unix ( socket) ?;
181
177
Ok ( ( ) )
0 commit comments