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