Source code: cryptix/sasl/rmi/SaslClientSocketFactory.java
1 package cryptix.sasl.rmi;
2
3 // $Id: SaslClientSocketFactory.java,v 1.3 2001/10/17 09:59:20 raif Exp $
4 //
5 // Copyright (c) 2000-2001 The Cryptix Foundation. All rights reserved.
6 //
7 // Use, modification, copying and distribution of this software is subject to
8 // the terms and conditions of the Cryptix General Licence. You should have
9 // received a copy of the Cryptix General License along with this library; if
10 // not, you can download a copy from <http://www.cryptix.org/>.
11
12 import cryptix.sasl.SaslInputStream;
13 import cryptix.sasl.SaslOutputStream;
14
15 import java.io.InputStream;
16 import java.io.IOException;
17 import java.io.OutputStream;
18 import java.io.Serializable;
19 import java.net.Socket;
20 import java.net.SocketException;
21 import java.rmi.server.RMIClientSocketFactory;
22
23 import javax.security.sasl.SaslClient;
24
25 import org.apache.log4j.Category;
26
27 /**
28 * A <tt>SaslClientSocketFactory</tt> instance is used by the RMI runtime in
29 * order to obtain client sockets for RMI calls. A remote object can be
30 * associated with a <tt>SaslClientSocketFactory</tt> when it is created/exported
31 * via the constructors or <tt>exportObject()</tt> methods of
32 * {@link java.rmi.server.UnicastRemoteObject} and {@link java.rmi.activation.Activatable}.<p>
33 *
34 * A <tt>RMIClientSocketFactory</tt> instance associated with a remote object
35 * will be downloaded to clients when the remote object's reference is
36 * transmitted in an RMI call. This <tt>SaslClientSocketFactory</tt> will be
37 * used to create connections to the remote object for remote method calls.<p>
38 *
39 * A <tt>SaslClientSocketFactory</tt> instance can also be associated with a
40 * remote object registry so that clients can use custom socket communication
41 * with a remote object registry.
42 *
43 * @version 1.1
44 */
45 public class SaslClientSocketFactory
46 implements RMIClientSocketFactory, Serializable
47 {
48 // Constants and variables
49 // --------------------------------------------------------------------------
50
51 private static Category cat = Category.getInstance(SaslClientSocketFactory.class);
52
53 /**
54 * A dummy 0-byte message to use with SASL-ified RMI socket for mechanisms
55 * whose client side does not have an initial response. This dummy message
56 * is then supposed to be discarded by their server-side implementations.
57 */
58 private static final byte[] NULL_MESSAGE = new byte[0];
59
60 // Constructor(s)
61 // --------------------------------------------------------------------------
62
63 // Class methods
64 // -------------------------------------------------------------------------
65
66 // Instance methods
67 // -------------------------------------------------------------------------
68
69 /**
70 * Creates a client socket connected to the specified host and port.
71 *
72 * @param host the host name.
73 * @param port the port number.
74 * @return a socket connected to the specified host and port.
75 * @exception IOException if an I/O error occurs during socket creation.
76 */
77 public Socket createSocket(String host, int port) throws IOException {
78 cat.debug("==> createSocket("+String.valueOf(host)+", "+String.valueOf(port)+")");
79
80 SaslSocket result = new SaslSocket(host, port);
81
82 SaslClient client = MechanismSelector.instance().newClient(host);
83 if (client == null) {
84 cat.info("Using default RMI...");
85 } else { // SASL authentication
86 try {
87 cat.info("Doing (client) SASL authentication...");
88
89 String mechanism = client.getMechanismName();
90 cat.info("Chosen mechanism: "+mechanism);
91
92 InputStream in = result.getInputStream();
93 OutputStream out = result.getOutputStream();
94 byte[] challenge, response;
95 if (client.hasInitialResponse()) {
96 response = client.evaluateChallenge(null);
97 // implies that server has last word; ie. client sends nothing
98 // after server sends last challenge
99 do {
100 RMIUtil.writeLV(out, response);
101 if (!client.isComplete()) {
102 challenge = RMIUtil.readLV(in);
103 response = client.evaluateChallenge(challenge);
104 }
105 } while (!client.isComplete());
106 } else
107 // implies that client has last word; ie. server sends nothing
108 // after client sends last response
109 do {
110 RMIUtil.writeLV(out, NULL_MESSAGE);
111 challenge = RMIUtil.readLV(in);
112 response = client.evaluateChallenge(challenge);
113 RMIUtil.writeLV(out, response);
114 } while (!client.isComplete());
115
116 cat.info("Done (client) SASL authentication...");
117
118 InputStream secureIn = new SaslInputStream(client, in);
119 OutputStream secureOut = new SaslOutputStream(client, out);
120
121 result.setSecureInputStream(secureIn);
122 result.setSecureOutputStream(secureOut);
123
124 } catch (IOException x) {
125 cat.error("In createSocket(): "+String.valueOf(x));
126 if (!(x instanceof SocketException)) {
127 cat.debug("createSocket()", x);
128 }
129 throw x;
130 }
131 }
132
133 cat.debug("<== createSocket()");
134 return result;
135 }
136 }