001: // %Z%%M% %I% "%W% %E% Sun Microsystems"
002:
003: package com.sun.portal.netlet.client.common;
004:
005: import java.awt.*;
006: import java.awt.event.ActionEvent;
007: import java.awt.event.ActionListener;
008: import java.io.*;
009: import java.net.*;
010: import java.util.Enumeration;
011: import java.util.Hashtable;
012:
013: class SClient implements Runnable, ActionListener {
014:
015: private Socket inconnection;
016: private ServerSocket sconnection = null;
017:
018: private volatile boolean go = true;
019: public boolean stopped = false;
020:
021: private int srcPortInRule;
022: private int srcPort;
023: private String serverPort;
024: private String serverHost;
025: private SClientMgr scm;
026: private boolean trans;
027:
028: /*
029: * Added for Lihue Pluggable Cipher requirement
030: *
031: * @ date 28/12/2001
032: * @ author Rajesh T
033: */
034:
035: private int keyLength;
036: private String cipherName;
037:
038: // Hashtable so we can have n number of connections, and we need to
039: // track them between methods for the IE-cancel-ability.
040: private Hashtable rwgroup;
041:
042: private Thread t = null;
043: private String t_name;
044:
045: private Frame f = new Frame();
046: private PortWarning pw;
047: private ReauthDialog rad;
048: private NetletErrorDialog ned;
049: private int lastIEIndex;
050:
051: // use this to get out of port warning awt thread so we can show proxy auth
052: // dialog
053: private volatile boolean start = false;
054:
055: private int connectionType = ClientConfig.NORMAL;
056:
057: public SClient(int srcp, String srvdest, String srvhost,
058: String name, SClientMgr scm, boolean _trans,
059: String ciphername, int keylength) {
060: if (srcp == 30021) {
061: connectionType = ClientConfig.FTP;
062: } else if (srcp == 135) {
063: connectionType = ClientConfig.EXCHANGE;
064: }
065: trans = _trans;
066: srcPortInRule = srcp;
067: srcPort = srcp;
068: serverPort = new String(srvdest);
069: serverHost = new String(srvhost);
070: t_name = new String(name);
071: this .scm = scm;
072: cipherName = ciphername;
073: keyLength = keylength;
074: rwgroup = new Hashtable(20);
075: }
076:
077: /*
078: * Make the server socket at srcPort and listen for connections.
079: */
080: public void start() {
081: stopped = false;
082:
083: BrowserType browser = BrowserType.getInstance();
084: if (browser.getNetscapeBrowser()
085: && browser.getJavaVMVersion() == 1) {
086: // enable the netscape privelege
087: try {
088: BrowserType.SecurityCall sc = browser
089: .enablePermission(BrowserType.NETSCAPE_UNIVERSAL_CONNECT);
090: sc.getMethod().invoke(null, sc.getArgs());
091: sc = browser
092: .enablePermission(BrowserType.NETSCAPE_UNIVERSAL_LISTEN);
093: sc.getMethod().invoke(null, sc.getArgs());
094: sc = browser
095: .enablePermission(BrowserType.NETSCAPE_UNIVERSAL_ACCEPT);
096: sc.getMethod().invoke(null, sc.getArgs());
097: } catch (Exception e) {
098: System.out
099: .println("SClient exception (start) (no privilege): "
100: + e);
101: }
102: }
103:
104: if (sconnection == null) {
105: sconnection = makeServerSocket();
106: }
107: go = true;
108: if (t == null) {
109: t = new Thread(this , t_name);
110: t.start();
111: }
112: }
113:
114: /*
115: * If the user grants all the necessary privileges,
116: * waits in a loop to accept the client connections.
117: */
118: public void run() {
119: BrowserType browser = BrowserType.getInstance();
120: if (browser.getNetscapeBrowser()
121: && browser.getJavaVMVersion() == 1) {
122: // enable the netscape privelege
123: try {
124: BrowserType.SecurityCall sc = browser
125: .enablePermission(BrowserType.NETSCAPE_UNIVERSAL_CONNECT);
126: sc.getMethod().invoke(null, sc.getArgs());
127: sc = browser
128: .enablePermission(BrowserType.NETSCAPE_UNIVERSAL_LISTEN);
129: sc.getMethod().invoke(null, sc.getArgs());
130: sc = browser
131: .enablePermission(BrowserType.NETSCAPE_UNIVERSAL_ACCEPT);
132: sc.getMethod().invoke(null, sc.getArgs());
133: } catch (Exception e) {
134: System.out
135: .println("SClient exception (run) (no privilege): "
136: + e);
137: }
138: }
139: pw = new PortWarning(f, this , srcPort);
140: rad = new ReauthDialog(f, this , srcPort);
141: ned = new NetletErrorDialog(f, this , null, null);
142: while (go) {
143: // wait for incoming connection request
144: if (sconnection == null) {
145: go = false;
146: } else {
147: try {
148: inconnection = sconnection.accept();
149: } catch (IOException e) {
150: try {
151: sconnection.close();
152: Thread.sleep(5);
153: if (go == false) {
154: break;
155: }
156: // hack, if io error, retry?
157: } catch (IOException ee) {
158: System.out
159: .println("SClient serversocket accept problem close error:");
160: ee.printStackTrace();
161: } catch (InterruptedException ee) {
162: // do nothing
163: } catch (NullPointerException ee) {
164: // hack for netscape < 4.0.5
165: return;
166: }
167:
168: // now, reopen the connection and listen for requests...
169: if (go == true) {
170: sconnection = makeServerSocket();
171: continue;
172: }
173: }
174: try {
175: inconnection.setTcpNoDelay(true);
176: } catch (SocketException e) {
177: System.out
178: .println("SClient accept socket error setting tcpNoDelay");
179: e.printStackTrace();
180: go = false;
181: }
182:
183: if (inconnection != null) {
184: if (trans) {
185: closeServerSocket();
186: }
187: System.out
188: .println("Netlet got connection on port: "
189: + inconnection.getLocalPort()
190: + " from port:"
191: + inconnection.getPort());
192: if (ClientConfig.doReauth()) {
193: System.out
194: .println("Netlet showing reauthentication dialog : "
195: + inconnection.getLocalPort());
196: rad.showWarning();
197: rad.waitForAction();
198: if (start)
199: startConnection();
200: } else if (ClientConfig.doPortWarning()) {
201: // - For IE, start conn now, and tear down later if
202: // portwarning is not ok IE will crash windows if conn
203: // is killed in mid-setup - For Netscape, wait for
204: // warning to come back before finishing conn setup
205: if (BrowserType.getInstance().getIEBrowser()) {
206: startConnection();
207: }
208: System.out
209: .println("Netlet showing port warning dialog:"
210: + inconnection.getLocalPort());
211: pw.showWarning();
212: pw.waitForAction();
213: // start set in actionPerformed(), global flag used so
214: // we can get out of portwarning awt thread before we
215: // fire up proxyauth dialog - retry startConnection()
216: if (start)
217: startConnection();
218: } else {
219: startConnection();
220: }
221: if (trans) {
222: return;
223: }
224:
225: }
226: }
227: }
228: stop();
229: }
230:
231: public boolean isTrans() {
232: return trans;
233: }
234:
235: /*
236: * Starts a new connection, and registers the newly created
237: * RWGroupCrypt with the rwgroup Hashtable.
238: */
239: public void startConnection() {
240: // reset flag
241: start = false;
242: int empty = getRWindex();
243: lastIEIndex = empty;
244: rwgroup.remove("" + empty);
245: RWGroupCrypt rwg = new RWGroupCrypt(inconnection,
246: connectionType, srcPort, serverPort, serverHost, scm,
247: this , cipherName, keyLength);
248: rwgroup.put("" + empty, rwg);
249: }
250:
251: /*
252: * Stops the thread listening for connections.
253: * Stops all the active RWGroups, closes the serverSocket,
254: * Cleans the memory.
255: */
256: public synchronized void stop() {
257: if (stopped) {
258: return;
259: }
260:
261: stopped = true;
262:
263: if (t != null) {
264: // t.stop();
265: // t = null;
266: go = false;
267: }
268:
269: stopRWGroup();
270: closeConnection();
271: closeServerSocket();
272: cleanup();
273: }
274:
275: /*
276: * Handles OK button request of Reauth dialog box.
277: * Read the password from the Dialog box, and try to authenticate
278: * @ Set start flag to true if password is valid.
279: */
280: public void handleReauthOKButtonRequest() {
281: String result = "FAILED";
282: String password = rad.getPassword();
283: if (password == null || password.trim().length() == 0) {
284: result = "FAILED";
285: } else {
286: InputStream inStream = ClientUtil.sendByPost("doReauth",
287: "&password=" + URLEncoder.encode(password));
288: /*
289: * Added to FIX 4710021 - Reauth hangs after logout.
290: */
291: if (inStream != null) {
292: BufferedReader br = new BufferedReader(
293: new InputStreamReader(inStream));
294: try {
295: result = br.readLine();
296: System.out.println("SClient: Reauth " + result);
297: br.close();
298: } catch (IOException ioe) {
299: result = "FAILED";
300: }
301: }
302: }
303: if (result != null && result.equals("SUCCESS")) {
304: start = true;
305: rad.notifyAction();
306: rad.setVisible(false);
307: } else {
308: rad.notifyAction();
309: rad.setVisible(false);
310: ned.setErrorMessage(ResourceProperties
311: .getString("reauth.error"));
312: ned.setVisible(true);
313: closeConnection();
314: }
315: }
316:
317: /*
318: * Handles Cancel button request of Reauth dialog.
319: */
320: public void handleReauthCancelButtonRequest() {
321: closeConnection();
322: rad.notifyAction();
323: rad.setVisible(false);
324: }
325:
326: /*
327: * Handles OK button request of Portwarn dialog box.
328: */
329: public void handlePortWarnOKButtonRequest() {
330: if (!BrowserType.getInstance().getIEBrowser()) {
331: start = true;
332: }
333: pw.notifyAction();
334: pw.setVisible(false);
335: }
336:
337: /*
338: * Handles Cancel button request of Portwarn dialog.
339: */
340: public void handlePortWarnCancelButtonRequest() {
341: if (BrowserType.getInstance().getIEBrowser()) {
342: // For IE, if they said no, then break down that
343: // already formed connection
344: if (lastIEIndex != -1) {
345: RWGroupCrypt rwg = (RWGroupCrypt) rwgroup.get(""
346: + lastIEIndex);
347: if (rwg != null) {
348: rwg.stopAll();
349: rwgroup.remove("" + lastIEIndex);
350: }
351: }
352: }
353: closeConnection();
354: // pw.setDontShow(false);
355: pw.notifyAction();
356: pw.setVisible(false);
357: }
358:
359: /*
360: * Closes the connection if already established.
361: */
362: public void closeConnection() {
363: try {
364: if (inconnection != null) {
365: inconnection.close();
366: inconnection = null;
367: }
368: } catch (IOException e) {
369: System.out
370: .println("Unable to close the connection -> " + e);
371: }
372: }
373:
374: /*
375: * Closes the server socket listening at srcPort.
376: */
377: public void closeServerSocket() {
378: try {
379: if (sconnection != null) {
380: sconnection.close();
381: sconnection = null;
382: }
383: } catch (IOException e) {
384: System.out.println("Unable to close the server socket -> "
385: + e);
386: }
387: }
388:
389: /*
390: * Handles the Portwarn and Reauth dialog button requests
391: */
392: public void actionPerformed(ActionEvent evt) {
393: Object obj = evt.getSource();
394: if ("OK".equals(evt.getActionCommand())) {
395: if (obj == rad.ok) { // For reauth dialog box
396: handleReauthOKButtonRequest();
397: } else if (obj == pw.ok) { // For portwarn dialog
398: handlePortWarnOKButtonRequest();
399: } else if (obj == ned.okButton) {
400: ned.setVisible(false);
401: }
402: } else if ("Cancel".equals(evt.getActionCommand())) {
403: if (obj == rad.cancel) {
404: handleReauthCancelButtonRequest();
405: } else if (obj == pw.cancel) {
406: handlePortWarnCancelButtonRequest();
407: }
408: }
409: }
410:
411: /*
412: * Makes the server socket at srcPort.
413: * Throws an Error Dialog if the port is already in use.
414: * @ Returns null if ServerSocket can not be created at srcPort.
415: */
416: public ServerSocket makeServerSocket() {
417: ServerSocket sock = null;
418: boolean go = true;
419: int retries = 5; // Max 5 retries for port hunting.
420:
421: while (go) {
422: try {
423: InetAddress bindAddr = null;
424: bindAddr = InetAddress.getByName(ClientConfig
425: .getClientBindIP());
426: sock = new ServerSocket(srcPort, 10, bindAddr);
427: srcPort = sock.getLocalPort();
428: go = false;
429: } catch (UnknownHostException uhe) {
430: System.out
431: .println("Unable to make server socket at port "
432: + srcPort
433: + " and host "
434: + ClientConfig.getClientBindIP()
435: + " "
436: + uhe);
437: sock = null;
438: srcPort = 0;
439: go = false;
440: } catch (IOException ioe) {
441: System.out
442: .println("Unable to make server socket at port "
443: + srcPort
444: + " and host "
445: + ClientConfig.getClientBindIP()
446: + " "
447: + ioe);
448: sock = null;
449: srcPort = 0;
450: // Try binding to a freely availble port.
451: go = retries > 0 ? true : false;
452: --retries;
453: }
454: }
455: return sock;
456: }
457:
458: /*
459: * Gets the NEXT INDEX for rwgroup Hashtable.
460: */
461: public int getRWindex() {
462: int i = 0;
463: boolean found = false;
464: Enumeration e = rwgroup.elements();
465: while (!found && e.hasMoreElements()) {
466: // fill any null/done connections
467: RWGroupCrypt rwg = (RWGroupCrypt) e.nextElement();
468: if (rwg == null) {
469: found = true;
470: } else if (rwg.done == true) {
471: found = true;
472: } else {
473: i++;
474: }
475: }
476: return i;
477: }
478:
479: /*
480: * Stops all the RWGroupCrypt threads running for srcPort.
481: */
482: public void stopRWGroup() {
483: for (Enumeration e = rwgroup.elements(); e.hasMoreElements();) {
484: RWGroupCrypt rwg = (RWGroupCrypt) e.nextElement();
485: if (rwg != null) {
486: if (!rwg.done) {
487: rwg.stopAll();
488: }
489: }
490: }
491: // reset hashtable
492: rwgroup.clear();
493: }
494:
495: /*
496: * Cleans the memory
497: */
498: private void cleanup() {
499: serverHost = null;
500: if (pw != null) {
501: pw.dispose();
502: pw = null;
503: }
504: if (rad != null) {
505: rad.dispose();
506: rad = null;
507: }
508: t_name = null;
509: }
510:
511: /*
512: * Returns the name of the Current SClient thread.
513: */
514: public String getName() {
515: if (t != null) {
516: return (t.getName());
517: } else {
518: return (null);
519: }
520: }
521:
522: /**
523: * Return the port at which this thread is listening on.
524: */
525: public int getSrcPort() {
526: return srcPort;
527: }
528:
529: public int getSrcPortInRule() {
530: return srcPortInRule;
531: }
532: }
|