View Javadoc

1   /***
2    * 
3    */
4   package de.cohesion.bssh.impl;
5   
6   import java.io.IOException;
7   
8   import ch.ethz.ssh2.Connection;
9   import de.cohesion.bssh.Member;
10  import de.cohesion.bssh.PasswordStore;
11  import de.cohesion.bssh.impl.io.Console;
12  import de.cohesion.bssh.impl.io.PasswordHelper;
13  
14  /***
15   * @author schulzs
16   * 
17   */
18  public class SSHConnectionFactory implements Factory<Member, Connection> {
19  
20  	private final PasswordStore store;
21  
22  	private final int retries;
23  
24  	public SSHConnectionFactory(int retries, final PasswordStore store) {
25  		this.retries = retries;
26  		this.store = store;
27  	}
28  
29  	public Connection create(final Member m) throws InstantiationException {
30  
31  		Member credMember = m;
32  		if (m instanceof GatewayMemberImpl) {
33  			credMember = GatewayMemberImpl.class.cast(m).getProxied();
34  		}
35  
36  		/*
37  		 * Get the password from the secure store or ask for one, if none is
38  		 * available.
39  		 */
40  		char[] password = null;
41  		try {
42  			password = store.getPassword(credMember);
43  		} catch (Exception e) {
44  			/*
45  			 * No password available for the given member. Prompt on console and
46  			 * store result.
47  			 */
48  			Console.getLock().lock();
49  			try {
50  				password = PasswordHelper.getPassword(System.in,
51  						"Provide password for " + credMember + ": ");
52  				store.store(credMember, password);
53  			} catch (IOException ioe) {
54  				InstantiationException ie = new InstantiationException(
55  						"storing password failed");
56  				ie.initCause(ioe);
57  				throw ie;
58  			} finally {
59  				Console.getLock().unlock();
60  			}
61  		}
62  
63  		Connection c = new Connection(m.getHost().getHostAddress(), m.getPort());
64  
65  		try {
66  
67  			/* Try to connect. */
68  			boolean connected = false;
69  			int tries = 0;
70  			while (!connected) {
71  				try {
72  					c.connect();
73  					connected = true;
74  					break;
75  				} catch (IOException ioe) {
76  					if (tries >= retries - 1) {
77  						throw ioe;
78  					}
79  				}
80  
81  				tries++;
82  
83  				/*
84  				 * May be contention wait for a few seconds (exponential
85  				 * falloff).
86  				 */
87  				try {
88  					long duration = Math.round(Math.pow(2, tries)) * 1000;
89  					Thread.sleep(duration);
90  				} catch (InterruptedException ie) {
91  					/* Ignore. */
92  				}
93  
94  			}
95  
96  			/* Authenticate. */
97  			boolean success = false;
98  			if (c.isAuthMethodAvailable(m.getUserName(), "password")) {
99  				success = c.authenticateWithPassword(m.getUserName(),
100 						new String(password));
101 			} else if (c.isAuthMethodAvailable(m.getUserName(),
102 					"keyboard-interactive")) {
103 				ChallengeHandler h = new PasswordChallengeHandler(password);
104 				success = c.authenticateWithKeyboardInteractive(
105 						m.getUserName(), new ChallengeHandlerAdapter(h));
106 			}
107 			if (success == false) {
108 				throw new IOException("authentication failed.");
109 			}
110 		} catch (IOException ioe) {
111 			InstantiationException ie = new InstantiationException(
112 					"connection refused");
113 			ie.initCause(ioe);
114 			throw ie;
115 		}
116 
117 		return c;
118 
119 	}
120 
121 	public void destroy(final Connection c) {
122 		c.close();
123 	}
124 
125 }