Mercurial > 510Connectbot
annotate app/src/main/java/com/five_ten_sg/connectbot/service/AuthAgentService.java @ 526:9a8862b87f6e stable-1.9.4-8
bump version
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sat, 01 Jun 2024 10:27:22 -0600 |
parents | d29cce60f393 |
children |
rev | line source |
---|---|
0 | 1 package com.five_ten_sg.connectbot.service; |
2 | |
3 import java.io.IOException; | |
4 import java.security.KeyPair; | |
5 import java.security.PrivateKey; | |
6 import java.security.PublicKey; | |
7 import java.security.interfaces.DSAPrivateKey; | |
8 import java.security.interfaces.DSAPublicKey; | |
9 import java.security.interfaces.ECPrivateKey; | |
10 import java.security.interfaces.ECPublicKey; | |
11 import java.security.interfaces.RSAPrivateKey; | |
12 import java.security.interfaces.RSAPublicKey; | |
13 import java.util.HashMap; | |
14 import java.util.Map; | |
15 import java.util.Map.Entry; | |
16 import java.util.concurrent.locks.Condition; | |
17 import java.util.concurrent.locks.Lock; | |
18 import java.util.concurrent.locks.ReentrantLock; | |
19 | |
20 import com.five_ten_sg.connectbot.service.TerminalManager; | |
21 import com.five_ten_sg.connectbot.service.TerminalManager.KeyHolder; | |
22 import android.app.Service; | |
23 import android.content.ComponentName; | |
24 import android.content.Intent; | |
25 import android.content.ServiceConnection; | |
26 import android.os.IBinder; | |
27 import android.os.RemoteException; | |
28 import android.util.Log; | |
29 | |
30 import com.madgag.ssh.android.authagent.AndroidAuthAgent; | |
344
b40bc65fa09a
compensate for SecureRandom bug on older devices
Carl Byington <carl@five-ten-sg.com>
parents:
297
diff
changeset
|
31 import ch.ethz.ssh2.crypto.SecureRandomFix; |
273
91a31873c42a
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
32 import ch.ethz.ssh2.signature.DSASHA1Verify; |
91a31873c42a
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
33 import ch.ethz.ssh2.signature.ECDSASHA2Verify; |
91a31873c42a
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
0
diff
changeset
|
34 import ch.ethz.ssh2.signature.RSASHA1Verify; |
0 | 35 |
344
b40bc65fa09a
compensate for SecureRandom bug on older devices
Carl Byington <carl@five-ten-sg.com>
parents:
297
diff
changeset
|
36 |
0 | 37 public class AuthAgentService extends Service { |
38 private static final String TAG = "ConnectBot.AuthAgentService"; | |
39 protected TerminalManager manager; | |
40 final Lock lock = new ReentrantLock(); | |
41 final Condition managerReady = lock.newCondition(); | |
42 | |
43 private ServiceConnection connection = new ServiceConnection() { | |
44 public void onServiceConnected(ComponentName className, IBinder service) { | |
45 Log.d(TAG, "Terminal manager available! Hurrah"); | |
46 manager = ((TerminalManager.TerminalBinder) service).getService(); | |
47 lock.lock(); | |
48 | |
49 try { | |
50 managerReady.signal(); | |
51 } | |
52 finally { | |
53 lock.unlock(); | |
54 } | |
55 } | |
56 public void onServiceDisconnected(ComponentName className) { | |
57 manager = null; | |
58 Log.d(TAG, "Terminal manager gone..."); | |
59 } | |
60 }; | |
61 | |
62 @Override | |
63 public IBinder onBind(Intent intent) { | |
64 Log.d(TAG, "onBind() called"); | |
65 bindService(new Intent(this, TerminalManager.class), connection, BIND_AUTO_CREATE); | |
66 return mBinder; | |
67 } | |
68 | |
69 private final AndroidAuthAgent.Stub mBinder = new AndroidAuthAgent.Stub() { | |
70 public Map getIdentities() throws RemoteException { | |
71 Log.d(TAG, "getIdentities() called"); | |
72 waitForTerminalManager(); | |
73 Log.d(TAG, "getIdentities() manager.loadedKeypairs : " + manager.loadedKeypairs); | |
74 return sshEncodedPubKeysFrom(manager.loadedKeypairs); | |
75 } | |
76 public byte[] sign(byte[] publicKey, byte[] data) throws RemoteException { | |
77 Log.d(TAG, "sign() called"); | |
78 waitForTerminalManager(); | |
79 KeyPair pair = keyPairFor(publicKey); | |
80 Log.d(TAG, "sign() - signing keypair found : " + pair); | |
81 | |
82 if (pair == null) { | |
83 return null; | |
84 } | |
85 | |
86 PrivateKey privKey = pair.getPrivate(); | |
87 | |
88 if (privKey instanceof RSAPrivateKey) { | |
89 return sshEncodedSignatureFor(data, (RSAPrivateKey) privKey); | |
90 } | |
91 else if (privKey instanceof DSAPrivateKey) { | |
92 return sshEncodedSignatureFor(data, (DSAPrivateKey) privKey); | |
93 } | |
296
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
94 else if (privKey instanceof ECPrivateKey) { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
95 return sshEncodedSignatureFor(data, (ECPrivateKey) privKey); |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
96 } |
0 | 97 |
98 return null; | |
99 } | |
100 private void waitForTerminalManager() throws RemoteException { | |
101 lock.lock(); | |
102 | |
103 try { | |
104 while (manager == null) { | |
105 Log.d(TAG, "Waiting for TerminalManager..."); | |
106 managerReady.await(); | |
107 } | |
108 } | |
109 catch (InterruptedException e) { | |
110 throw new RemoteException(); | |
111 } | |
112 finally { | |
113 lock.unlock(); | |
114 } | |
115 | |
116 Log.d(TAG, "Got TerminalManager : " + manager); | |
117 } | |
118 private Map<String, byte[]> sshEncodedPubKeysFrom(Map<String, KeyHolder> keypairs) { | |
119 Map<String, byte[]> pubkeys = new HashMap<String, byte[]> (keypairs.size()); | |
120 | |
121 for (Entry<String, KeyHolder> entry : keypairs.entrySet()) { | |
122 byte[] encodedKey = sshEncodedPubKeyFrom(entry.getValue().pair); | |
123 | |
124 if (encodedKey != null) { | |
125 pubkeys.put(entry.getKey(), encodedKey); | |
126 } | |
127 } | |
128 | |
129 return pubkeys; | |
130 } | |
131 private byte[] sshEncodedPubKeyFrom(KeyPair pair) { | |
132 try { | |
133 PrivateKey privKey = pair.getPrivate(); | |
134 | |
135 if (privKey instanceof RSAPrivateKey) { | |
136 RSAPublicKey pubkey = (RSAPublicKey)pair.getPublic(); | |
137 return RSASHA1Verify.encodeSSHRSAPublicKey(pubkey); | |
138 } | |
139 else if (privKey instanceof DSAPrivateKey) { | |
140 DSAPublicKey pubkey = (DSAPublicKey)pair.getPublic(); | |
141 return DSASHA1Verify.encodeSSHDSAPublicKey(pubkey); | |
142 } | |
296
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
143 else if (privKey instanceof ECPrivateKey) { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
144 ECPublicKey pubkey = (ECPublicKey) pair.getPublic(); |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
145 return ECDSASHA2Verify.encodeSSHECDSAPublicKey(pubkey); |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
146 } |
0 | 147 } |
148 catch (IOException e) { | |
149 Log.e(TAG, "Couldn't encode " + pair, e); | |
150 } | |
151 | |
152 return null; | |
153 } | |
154 private byte[] sshEncodedSignatureFor(byte[] data, RSAPrivateKey privKey) { | |
155 try { | |
156 byte[] signature = RSASHA1Verify.generateSignature(data, privKey); | |
157 return RSASHA1Verify.encodeSSHRSASignature(signature); | |
158 } | |
159 catch (IOException e) { | |
160 throw new RuntimeException(e); | |
161 } | |
162 } | |
163 private byte[] sshEncodedSignatureFor(byte[] data, DSAPrivateKey privKey) { | |
164 try { | |
344
b40bc65fa09a
compensate for SecureRandom bug on older devices
Carl Byington <carl@five-ten-sg.com>
parents:
297
diff
changeset
|
165 byte[] signature = DSASHA1Verify.generateSignature(data, privKey, new SecureRandomFix()); |
0 | 166 return DSASHA1Verify.encodeSSHDSASignature(signature); |
167 } | |
168 catch (IOException e) { | |
169 throw new RuntimeException(e); | |
170 } | |
171 } | |
296
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
172 private byte[] sshEncodedSignatureFor(byte[] data, ECPrivateKey privKey) { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
173 try { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
174 byte[] signature = ECDSASHA2Verify.generateSignature(data, privKey); |
297
c1f929cb3dd0
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
296
diff
changeset
|
175 return ECDSASHA2Verify.encodeSSHECDSASignature(signature, privKey.getParams()); |
296
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
176 } |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
177 catch (IOException e) { |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
178 throw new RuntimeException(e); |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
179 } |
8c55d7714d03
start conversion from trilead to ganymed
Carl Byington <carl@five-ten-sg.com>
parents:
273
diff
changeset
|
180 } |
0 | 181 private KeyPair keyPairFor(byte[] publicKey) { |
182 String nickname = manager.getKeyNickname(publicKey); | |
183 | |
184 if (nickname == null) { | |
185 Log.w(TAG, "No key-pair found for public-key."); | |
186 return null; | |
187 } | |
188 | |
189 // check manager.loadedKeypairs.get(nickname).bean.isConfirmUse() and promptForPubkeyUse(nickname) ? | |
190 return manager.getKey(nickname); | |
191 } | |
192 }; | |
193 } |