Subversion Repositories Programming Utils

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
86 rm5248 1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
package org.apache.sshd;
20
 
21
import java.security.InvalidKeyException;
22
import java.util.Arrays;
23
import java.util.Iterator;
24
import java.util.LinkedList;
25
import java.util.List;
26
 
27
import org.apache.sshd.client.ServerKeyVerifier;
28
import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
29
import org.apache.sshd.common.AbstractFactoryManager;
30
import org.apache.sshd.common.Channel;
31
import org.apache.sshd.common.Cipher;
32
import org.apache.sshd.common.Compression;
33
import org.apache.sshd.common.Factory;
34
import org.apache.sshd.common.KeyExchange;
35
import org.apache.sshd.common.Mac;
36
import org.apache.sshd.common.NamedFactory;
37
import org.apache.sshd.common.Random;
38
import org.apache.sshd.common.RequestHandler;
39
import org.apache.sshd.common.Signature;
40
import org.apache.sshd.common.TcpipForwarderFactory;
41
import org.apache.sshd.common.cipher.AES128CBC;
42
import org.apache.sshd.common.cipher.AES128CTR;
43
import org.apache.sshd.common.cipher.AES192CBC;
44
import org.apache.sshd.common.cipher.AES192CTR;
45
import org.apache.sshd.common.cipher.AES256CBC;
46
import org.apache.sshd.common.cipher.AES256CTR;
47
import org.apache.sshd.common.cipher.ARCFOUR128;
48
import org.apache.sshd.common.cipher.ARCFOUR256;
49
import org.apache.sshd.common.cipher.BlowfishCBC;
50
import org.apache.sshd.common.cipher.TripleDESCBC;
51
import org.apache.sshd.common.compression.CompressionNone;
52
import org.apache.sshd.common.file.FileSystemFactory;
53
import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
54
import org.apache.sshd.common.forward.DefaultTcpipForwarderFactory;
55
import org.apache.sshd.common.forward.TcpipServerChannel;
56
import org.apache.sshd.common.mac.HMACMD5;
57
import org.apache.sshd.common.mac.HMACMD596;
58
import org.apache.sshd.common.mac.HMACSHA1;
59
import org.apache.sshd.common.mac.HMACSHA196;
60
import org.apache.sshd.common.mac.HMACSHA256;
61
import org.apache.sshd.common.mac.HMACSHA512;
62
import org.apache.sshd.common.random.BouncyCastleRandom;
63
import org.apache.sshd.common.random.JceRandom;
64
import org.apache.sshd.common.random.SingletonRandomFactory;
65
import org.apache.sshd.common.session.ConnectionService;
66
import org.apache.sshd.common.signature.SignatureDSA;
67
import org.apache.sshd.common.signature.SignatureECDSA;
68
import org.apache.sshd.common.signature.SignatureRSA;
69
import org.apache.sshd.common.util.SecurityUtils;
70
import org.apache.sshd.server.channel.ChannelSession;
71
import org.apache.sshd.server.global.CancelTcpipForwardHandler;
72
import org.apache.sshd.server.global.KeepAliveHandler;
73
import org.apache.sshd.server.global.NoMoreSessionsHandler;
74
import org.apache.sshd.server.global.TcpipForwardHandler;
75
 
76
/**
77
 * A builder object for creating SshServer instances.
78
 *
79
 * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
80
 */
81
public class SshBuilder {
82
 
83
    public static ClientBuilder client() {
84
        return new ClientBuilder();
85
    }
86
 
87
    public static ServerBuilder server() {
88
        return new ServerBuilder();
89
    }
90
 
91
    protected static class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder<T, S>> {
92
 
93
        protected Factory<T> factory = null;
94
 
95
        protected List<NamedFactory<KeyExchange>> keyExchangeFactories = null;
96
        protected List<NamedFactory<Cipher>> cipherFactories = null;
97
        protected List<NamedFactory<Compression>> compressionFactories = null;
98
        protected List<NamedFactory<Mac>> macFactories = null;
99
        protected List<NamedFactory<Signature>> signatureFactories = null;
100
        protected Factory<Random> randomFactory = null;
101
        protected List<NamedFactory<Channel>> channelFactories = null;
102
        protected FileSystemFactory fileSystemFactory = null;
103
        protected TcpipForwarderFactory tcpipForwarderFactory = null;
104
        protected List<RequestHandler<ConnectionService>> globalRequestHandlers = null;
105
 
106
        protected S fillWithDefaultValues() {
107
            if (SecurityUtils.isBouncyCastleRegistered()) {
108
                if (signatureFactories == null) {
109
                    signatureFactories = Arrays.asList(
110
                            new SignatureECDSA.NISTP256Factory(),
111
                            new SignatureECDSA.NISTP384Factory(),
112
                            new SignatureECDSA.NISTP521Factory(),
113
                            new SignatureDSA.Factory(),
114
                            new SignatureRSA.Factory());
115
                }
116
                if (randomFactory == null) {
117
                    randomFactory = new SingletonRandomFactory(new BouncyCastleRandom.Factory());
118
                }
119
                // EC keys are not supported until OpenJDK 7
120
            } else if (SecurityUtils.hasEcc()) {
121
                if (signatureFactories == null) {
122
                    signatureFactories = Arrays.asList(
123
                            new SignatureECDSA.NISTP256Factory(),
124
                            new SignatureECDSA.NISTP384Factory(),
125
                            new SignatureECDSA.NISTP521Factory(),
126
                            new SignatureDSA.Factory(),
127
                            new SignatureRSA.Factory());
128
                }
129
                if (randomFactory == null) {
130
                    randomFactory = new SingletonRandomFactory(new JceRandom.Factory());
131
                }
132
            } else {
133
                if (signatureFactories == null) {
134
                    signatureFactories = Arrays.asList(
135
                            new SignatureDSA.Factory(),
136
                            new SignatureRSA.Factory());
137
                }
138
                if (randomFactory == null) {
139
                    randomFactory = new SingletonRandomFactory(new JceRandom.Factory());
140
                }
141
            }
142
 
143
            if (cipherFactories == null) {
144
                cipherFactories = setUpDefaultCiphers();
145
            }
146
 
147
            // Compression is not enabled by default
148
            //if (compressionFactories == null) {
149
            //    compressionFactories = Arrays.<NamedFactory<Compression>>asList(
150
            //            new CompressionNone.Factory(),
151
            //            new CompressionZlib.Factory(),
152
            //            new CompressionDelayedZlib.Factory());
153
            //}
154
            if (compressionFactories == null) {
155
                compressionFactories = Arrays.<NamedFactory<Compression>>asList(
156
                        new CompressionNone.Factory());
157
            }
158
            if (macFactories == null) {
159
                macFactories = Arrays.asList(
160
                        new HMACSHA256.Factory(),
161
                        new HMACSHA512.Factory(),
162
                        new HMACSHA1.Factory(),
163
                        new HMACMD5.Factory(),
164
                        new HMACSHA196.Factory(),
165
                        new HMACMD596.Factory());
166
            }
167
            if (fileSystemFactory == null) {
168
                fileSystemFactory = new NativeFileSystemFactory();
169
            }
170
            if (tcpipForwarderFactory == null) {
171
                tcpipForwarderFactory = new DefaultTcpipForwarderFactory();
172
            }
173
 
174
            return me();
175
        }
176
 
177
        public S keyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
178
            this.keyExchangeFactories = keyExchangeFactories;
179
            return me();
180
        }
181
 
182
        public S signatureFactories(final List<NamedFactory<Signature>> signatureFactories) {
183
            this.signatureFactories = signatureFactories;
184
            return me();
185
        }
186
 
187
        public S randomFactory(final Factory<Random> randomFactory) {
188
            this.randomFactory = randomFactory;
189
            return me();
190
        }
191
 
192
        public S cipherFactories(final List<NamedFactory<Cipher>> cipherFactories) {
193
            this.cipherFactories = cipherFactories;
194
            return me();
195
        }
196
 
197
        public S compressionFactories(final List<NamedFactory<Compression>> compressionFactories) {
198
            this.compressionFactories = compressionFactories;
199
            return me();
200
        }
201
 
202
        public S macFactories(final List<NamedFactory<Mac>> macFactories) {
203
            this.macFactories = macFactories;
204
            return me();
205
        }
206
 
207
        public S channelFactories(final List<NamedFactory<Channel>> channelFactories) {
208
            this.channelFactories = channelFactories;
209
            return me();
210
        }
211
 
212
        public S fileSystemFactory(final FileSystemFactory fileSystemFactory) {
213
            this.fileSystemFactory = fileSystemFactory;
214
            return me();
215
        }
216
 
217
        public S tcpipForwarderFactory(final TcpipForwarderFactory tcpipForwarderFactory) {
218
            this.tcpipForwarderFactory = tcpipForwarderFactory;
219
            return me();
220
        }
221
 
222
        public S globalRequestHandlers(final List<RequestHandler<ConnectionService>> globalRequestHandlers) {
223
            this.globalRequestHandlers = globalRequestHandlers;
224
            return me();
225
        }
226
 
227
        public S factory(final Factory<T> factory) {
228
            this.factory = factory;
229
            return me();
230
        }
231
 
232
        public T build(final boolean isFillWithDefaultValues) {
233
            if (isFillWithDefaultValues) {
234
                fillWithDefaultValues();
235
            }
236
 
237
            T ssh = factory.create();
238
 
239
            ssh.setKeyExchangeFactories(keyExchangeFactories);
240
            ssh.setSignatureFactories(signatureFactories);
241
            ssh.setRandomFactory(randomFactory);
242
            ssh.setCipherFactories(cipherFactories);
243
            ssh.setCompressionFactories(compressionFactories);
244
            ssh.setMacFactories(macFactories);
245
            ssh.setChannelFactories(channelFactories);
246
            ssh.setFileSystemFactory(fileSystemFactory);
247
            ssh.setTcpipForwarderFactory(tcpipForwarderFactory);
248
            ssh.setGlobalRequestHandlers(globalRequestHandlers);
249
 
250
            return ssh;
251
        }
252
 
253
        public T build() {
254
            return build(true);
255
        }
256
 
257
        @SuppressWarnings("unchecked")
258
        protected S me() {
259
            return (S) this;
260
        }
261
 
262
        protected static List<NamedFactory<Cipher>> setUpDefaultCiphers() {
263
            List<NamedFactory<Cipher>> avail = new LinkedList<NamedFactory<Cipher>>();
264
            avail.add(new AES128CTR.Factory());
265
            avail.add(new AES192CTR.Factory());
266
            avail.add(new AES256CTR.Factory());
267
            avail.add(new ARCFOUR128.Factory());
268
            avail.add(new ARCFOUR256.Factory());
269
            avail.add(new AES128CBC.Factory());
270
            avail.add(new TripleDESCBC.Factory());
271
            avail.add(new BlowfishCBC.Factory());
272
            avail.add(new AES192CBC.Factory());
273
            avail.add(new AES256CBC.Factory());
274
 
275
            for (Iterator<NamedFactory<Cipher>> i = avail.iterator(); i.hasNext(); ) {
276
                final NamedFactory<Cipher> f = i.next();
277
                try {
278
                    final Cipher c = f.create();
279
                    final byte[] key = new byte[c.getBlockSize()];
280
                    final byte[] iv = new byte[c.getIVSize()];
281
                    c.init(Cipher.Mode.Encrypt, key, iv);
282
                } catch (InvalidKeyException e) {
283
                    i.remove();
284
                } catch (Exception e) {
285
                    i.remove();
286
                }
287
            }
288
            return avail;
289
        }
290
    }
291
 
292
    /**
293
     * SshClient builder
294
     */
295
    public static class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
296
 
297
        protected ServerKeyVerifier serverKeyVerifier;
298
 
299
        public ClientBuilder serverKeyVerifier(ServerKeyVerifier serverKeyVerifier) {
300
            this.serverKeyVerifier = serverKeyVerifier;
301
            return me();
302
        }
303
 
304
        @Override
305
        protected ClientBuilder fillWithDefaultValues() {
306
            super.fillWithDefaultValues();
307
            if (SecurityUtils.isBouncyCastleRegistered()) {
308
                if (keyExchangeFactories == null) {
309
                    keyExchangeFactories = Arrays.asList(
310
                            new org.apache.sshd.client.kex.DHGEX256.Factory(),
311
                            new org.apache.sshd.client.kex.DHGEX.Factory(),
312
                            new org.apache.sshd.client.kex.ECDHP256.Factory(),
313
                            new org.apache.sshd.client.kex.ECDHP384.Factory(),
314
                            new org.apache.sshd.client.kex.ECDHP521.Factory(),
315
                            new org.apache.sshd.client.kex.DHG14.Factory(),
316
                            new org.apache.sshd.client.kex.DHG1.Factory());
317
                }
318
            // EC keys are not supported until OpenJDK 7
319
            } else if (SecurityUtils.hasEcc()) {
320
                if (keyExchangeFactories == null) {
321
                    keyExchangeFactories = Arrays.asList(
322
                            new org.apache.sshd.client.kex.DHGEX256.Factory(),
323
                            new org.apache.sshd.client.kex.DHGEX.Factory(),
324
                            new org.apache.sshd.client.kex.ECDHP256.Factory(),
325
                            new org.apache.sshd.client.kex.ECDHP384.Factory(),
326
                            new org.apache.sshd.client.kex.ECDHP521.Factory(),
327
                            new org.apache.sshd.client.kex.DHG1.Factory());
328
                }
329
            } else {
330
                if (keyExchangeFactories == null) {
331
                    keyExchangeFactories = Arrays.asList(
332
                            new org.apache.sshd.client.kex.DHGEX256.Factory(),
333
                            new org.apache.sshd.client.kex.DHGEX.Factory(),
334
                            new org.apache.sshd.client.kex.DHG1.Factory());
335
                }
336
            }
337
            if (channelFactories == null) {
338
                channelFactories = Arrays.<NamedFactory<Channel>>asList(
339
                        new TcpipServerChannel.ForwardedTcpipFactory());
340
            }
341
            if (serverKeyVerifier == null) {
342
                serverKeyVerifier = AcceptAllServerKeyVerifier.INSTANCE;
343
            }
344
            if (factory == null) {
345
                factory = SshClient.DEFAULT_SSH_CLIENT_FACTORY;
346
            }
347
            return me();
348
        }
349
 
350
        @Override
351
        public SshClient build(boolean isFillWithDefaultValues) {
352
            SshClient client = super.build(isFillWithDefaultValues);
353
            client.setServerKeyVerifier(serverKeyVerifier);
354
            return client;
355
        }
356
    }
357
 
358
    /**
359
     * SshServer builder
360
     */
361
    public static class ServerBuilder extends BaseBuilder<SshServer, ServerBuilder> {
362
 
363
        @Override
364
        protected ServerBuilder fillWithDefaultValues() {
365
            super.fillWithDefaultValues();
366
            if (SecurityUtils.isBouncyCastleRegistered()) {
367
                if (keyExchangeFactories == null) {
368
                    keyExchangeFactories = Arrays.asList(
369
                            new org.apache.sshd.server.kex.DHGEX256.Factory(),
370
                            new org.apache.sshd.server.kex.DHGEX.Factory(),
371
                            new org.apache.sshd.server.kex.ECDHP256.Factory(),
372
                            new org.apache.sshd.server.kex.ECDHP384.Factory(),
373
                            new org.apache.sshd.server.kex.ECDHP521.Factory(),
374
                            new org.apache.sshd.server.kex.DHG14.Factory(),
375
                            new org.apache.sshd.server.kex.DHG1.Factory());
376
                }
377
            // EC keys are not supported until OpenJDK 7
378
            } else if (SecurityUtils.hasEcc()) {
379
                if (keyExchangeFactories == null) {
380
                    keyExchangeFactories = Arrays.asList(
381
                            new org.apache.sshd.server.kex.DHGEX256.Factory(),
382
                            new org.apache.sshd.server.kex.DHGEX.Factory(),
383
                            new org.apache.sshd.server.kex.ECDHP256.Factory(),
384
                            new org.apache.sshd.server.kex.ECDHP384.Factory(),
385
                            new org.apache.sshd.server.kex.ECDHP521.Factory(),
386
                            new org.apache.sshd.server.kex.DHG1.Factory());
387
                }
388
            } else {
389
                if (keyExchangeFactories == null) {
390
                    keyExchangeFactories = Arrays.asList(
391
                            new org.apache.sshd.server.kex.DHGEX256.Factory(),
392
                            new org.apache.sshd.server.kex.DHGEX.Factory(),
393
                            new org.apache.sshd.server.kex.DHG1.Factory());
394
                }
395
            }
396
            if (channelFactories == null) {
397
                channelFactories = Arrays.asList(
398
                        new ChannelSession.Factory(),
399
                        new TcpipServerChannel.DirectTcpipFactory());
400
            }
401
            if (globalRequestHandlers == null) {
402
                globalRequestHandlers = Arrays.asList(
403
                        new KeepAliveHandler(),
404
                        new NoMoreSessionsHandler(),
405
                        new TcpipForwardHandler(),
406
                        new CancelTcpipForwardHandler());
407
            }
408
            if (factory == null) {
409
                factory = SshServer.DEFAULT_SSH_SERVER_FACTORY;
410
            }
411
            return me();
412
        }
413
    }
414
 
415
}