001: /*
002: * RProxyConnection.java
003: *
004: * Created on March 20, 2002, 10:31 PM
005: */
006:
007: package com.sun.portal.netlet.eproxy;
008:
009: import java.io.BufferedReader;
010: import java.io.DataInputStream;
011: import java.io.IOException;
012: import java.io.InputStream;
013: import java.io.InputStreamReader;
014: import java.net.InetAddress;
015: import java.net.ServerSocket;
016: import java.net.Socket;
017: import java.net.SocketException;
018: import java.net.URLDecoder;
019: import java.util.logging.Level;
020: import java.util.logging.Logger;
021: import java.util.*;
022: import java.net.*;
023: import java.io.*;
024:
025: import com.iplanet.sso.SSOException;
026: import com.iplanet.sso.SSOToken;
027: import com.iplanet.sso.SSOTokenManager;
028: import com.sun.portal.log.common.PortalLogger;
029: import com.sun.portal.netlet.econnection.ESessionMsg;
030: import com.sun.portal.netlet.econnection.GWRunnable;
031: import com.sun.portal.netlet.proxy.NetletProxy;
032: import com.sun.portal.rproxy.configservlet.client.GatewayProfile;
033: import com.sun.portal.rproxy.configservlet.client.UserProfile;
034: import com.sun.portal.rproxy.connectionhandler.ErrorResponse;
035: import com.sun.portal.rproxy.monitoring.MonitoringSubsystem;
036: import com.sun.portal.rproxy.rewriterproxy.HTTPProxy;
037: import com.sun.portal.rproxy.server.RequestProcessor;
038: import com.sun.portal.rproxy.server.ServerSocketFactory;
039: import com.sun.portal.util.GWDebug;
040: import com.sun.portal.util.GWLocale;
041: import com.sun.portal.util.GWLogManager;
042: import com.sun.portal.util.GWThreadPool;
043: import com.sun.portal.util.LogInfoContainer;
044: import com.sun.portal.util.SRAEvent;
045: import com.sun.portal.util.ServiceIdentifier;
046: import com.sun.portal.util.SystemProperties;
047:
048: /*
049: *
050: * @author Mridul Muralidharan
051: */
052:
053: public class RProxyConnection extends ProxyConnection {
054:
055: private boolean secureConnection;
056:
057: private int port = 0;
058:
059: // private static Logger logger =
060: // Logger.getLogger("com.sun.portal.sra.netlet");
061: private static Logger logger = PortalLogger
062: .getLogger(RProxyConnection.class);
063:
064: private RequestProcessor requestProcessor;
065:
066: public static void startHttps(final int port) {
067: Runnable r = new Runnable() {
068: public void run() {
069: RProxyConnection rpconn = new RProxyConnection(true,
070: port);
071: try {
072: rpconn.start();
073: } catch (SocketException e) {
074: if (GWDebug.debug.errorEnabled())
075: GWDebug.debug
076: .error("RProxyConnection:startHttps(int) cannot start : "
077: + e);
078: }
079:
080: }
081: };
082: Thread thread = new Thread(r);
083: thread.start();
084: }
085:
086: public static void startHttps(final int exposedPort, final int port) {
087: Runnable r = new Runnable() {
088: public void run() {
089: RProxyConnection rpconn = new RProxyConnection(true,
090: exposedPort, port);
091: try {
092: rpconn.start();
093: } catch (SocketException e) {
094: if (GWDebug.debug.errorEnabled())
095: GWDebug.debug
096: .error("RProxyConnection:startHttps(int,int) cannot start : "
097: + e);
098: }
099:
100: }
101: };
102: Thread thread = new Thread(r);
103: thread.start();
104: }
105:
106: public static void startHttp(final int port) {
107: Runnable r = new Runnable() {
108: public void run() {
109: RProxyConnection rpconn = new RProxyConnection(false,
110: port);
111: try {
112: rpconn.start();
113: } catch (SocketException e) {
114: if (GWDebug.debug.errorEnabled())
115: GWDebug.debug
116: .error("RProxyConnection:startHttp(int) cannot start : "
117: + e);
118: }
119:
120: }
121: };
122: Thread thread = new Thread(r);
123: thread.start();
124:
125: }
126:
127: static boolean useAcceleratorSupport = false;
128: static {
129: String strUseAcceleratorSupport = SystemProperties.get(
130: "gateway.enable.accelerator", "false");
131: if (strUseAcceleratorSupport != null) {
132: useAcceleratorSupport = strUseAcceleratorSupport.trim()
133: .equalsIgnoreCase("true");
134: }
135: }
136:
137: private RProxyConnection(boolean secureConnection, int port) {
138: super ("RProxyHTTPSThread", "epc1");
139: this .secureConnection = secureConnection;
140: this .port = port;
141: /*
142: * if (useAcceleratorSupport && this.secureConnection){ requestProcessor =
143: * new RequestProcessor("https", port); } else{
144: */
145: requestProcessor = (this .secureConnection) ? new RequestProcessor(
146: "https", port)
147: : new RequestProcessor("http", port);
148: // }
149: }
150:
151: private RProxyConnection(boolean secureConnection, int exposedPort,
152: int port) {
153: super ("RProxyHTTPSThread", "epc1");
154: this .secureConnection = secureConnection;
155: this .port = port;
156:
157: /*
158: * if (useAcceleratorSupport && this.secureConnection){ requestProcessor =
159: * new RequestProcessor("https", exposedPort); } else{
160: */
161: requestProcessor = (this .secureConnection) ? new RequestProcessor(
162: "https", exposedPort)
163: : new RequestProcessor("http", exposedPort);
164: // }
165: }
166:
167: protected ServerSocket makeServerSocket() throws SocketException {
168: /*
169: * return (this.secureConnection) ?
170: * ServerSocketFactory.createSSLSocketServer(port) :
171: * ServerSocketFactory.createSRAPServerSocket(port); //:
172: * ServerSocketFactory.createNormalServerSocket(port);
173: */
174: if (this .secureConnection && useAcceleratorSupport
175: && ServiceIdentifier.isGateway()) {
176: return ServerSocketFactory.createSRAPServerSocket(port);
177: }
178: return (this .secureConnection) ? ServerSocketFactory
179: .createSSLSocketServer(port) : ServerSocketFactory
180: .createSRAPServerSocket(port);
181: // : ServerSocketFactory.createNormalServerSocket(port);
182: }
183:
184: /**
185: * Return true if its the Netlet Traffic, false otherwise.
186: */
187: private int isNetletTraffic(Socket inconnection) {
188:
189: InputStream in = null;
190: try {
191: in = inconnection.getInputStream();
192: } catch (IOException e) {
193: // logger.log(Level.SEVERE, "RProxyConnection cannot open input
194: // stream on " + inconnection, e);
195: Object[] params0 = { inconnection, e };
196: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX058", params0);
197:
198: try {
199: inconnection.close();
200: MonitoringSubsystem
201: .handleEvent(SRAEvent.PLAIN_SOCKET_DESTROYED);
202: } catch (Exception e1) {
203: }
204: return -1;
205: }
206:
207: ESessionMsg emsg = new ESessionMsg();
208: try {
209: in.mark(512);
210: } catch (Exception e) {
211: // logger.log(Level.SEVERE, "Cannot mark " + inconnection, e);
212: Object[] params1 = { inconnection, e };
213: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX059", params1);
214: try {
215: inconnection.close();
216: MonitoringSubsystem
217: .handleEvent(SRAEvent.PLAIN_SOCKET_DESTROYED);
218: } catch (Exception e1) {
219: }
220: emsg = null;
221: return -1;
222: }
223:
224: int result = emsg.readMsg(new DataInputStream(in));
225: if (result == 0 || result == 1) {
226: emsg = null;
227: return result;
228: }
229:
230: try {
231: in.reset();
232: } catch (Exception e) {
233: // logger.log(Level.SEVERE, "Cannot reset " + inconnection, e);
234: Object[] params2 = { inconnection, e };
235: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX060", params2);
236: }
237: emsg = null;
238: return -1;
239: }
240:
241: private boolean isConnectionFromValidGateway(Socket inconnection) {
242: boolean allowed = false;
243:
244: InetAddress addr = inconnection.getInetAddress();
245: // Is the remote end point a GW IP or not, if not reject the rquest.
246: String ip = addr.getHostAddress();
247: Object[] params = { ip };
248: logger.log(Level.FINEST, "PSSRNTLT_CSPNEPROX115", params);
249: if (HTTPProxy.isValidGateway(ip))
250: return true;
251: return allowed;
252: }
253:
254: protected void process(Socket connection, Integer logId) {
255:
256: try {
257: if (ServiceIdentifier.isRewriterProxy()) {
258: // Rewriter Proxy will accept connections only from a gateway. The list of valid gateways are specified
259: // in the RWP instances platform.conf file.
260: if (HTTPProxy.allowConnectionsFromAllClients()
261: || isConnectionFromValidGateway(connection))
262: GWThreadPool
263: .run(new RProxyThread(connection, logId));
264: else
265: closeSocket(connection);
266: } else
267: GWThreadPool.run(new RProxyThread(connection, logId));
268: } catch (Exception ex) {
269: ex.printStackTrace();
270: }
271: }
272:
273: private static final String TIMEOUT = "RProxyPortTimeout";
274:
275: private static final int DEFAULT_TIMEOUT = 1000 * 60;
276:
277: private static final int timeout = GatewayProfile.getInt(TIMEOUT,
278: DEFAULT_TIMEOUT) * 1000;
279:
280: class RProxyThread implements GWRunnable {
281:
282: private Socket connection;
283:
284: private Integer logId;
285:
286: public RProxyThread(Socket _connection, Integer _logId) {
287: connection = _connection;
288: logId = _logId;
289: }
290:
291: public void run() {
292:
293: boolean checkNetlet = false;
294: boolean checkProxylet = false;
295:
296: Socket nonsslsocket = null;
297:
298: // if (ServiceIdentifier.isRewriterProxy() ||
299: // (ServiceIdentifier.isGateway() && EProxy.isNetletEnabled)){
300: GWLogManager.logIdMap.put(
301: new Integer(connection.getPort()),
302: new LogInfoContainer(logId, connection));
303: // }
304:
305: // call setSoTimeout()
306: int initialTimeout = 0;
307: try {
308: initialTimeout = connection.getSoTimeout();
309: } catch (Exception ex) {
310: // logger.log(Level.SEVERE, "RProxy caught exception while
311: // setting getSoTimeout() : ", ex);
312: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX061");
313: }
314:
315: try {
316: connection.setSoTimeout(timeout);
317: } catch (Exception ex) {
318: // logger.log(Level.SEVERE, "RProxy caught exception while
319: // setting setSoTimeout() : ", ex);
320: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX062");
321: }
322:
323: if (ServiceIdentifier.isGateway()) {
324: checkNetlet = EProxy.isNetletEnabled;
325: } else if (ServiceIdentifier.isNetletProxy()) {
326: checkNetlet = true;
327: }
328:
329: checkProxylet = EProxy.isProxyletEnabled;
330:
331: int result = isNetletTraffic(connection);
332:
333: boolean isNetletTraffic = false, isEnd2EndSSLRequest = false;
334:
335: if (result == 0)
336: isNetletTraffic = true;
337: else if (result == 1)
338: isEnd2EndSSLRequest = true;
339:
340: if (checkProxylet == true) {
341: //
342: // Get the nonssl socket corresponding to this SSL socket
343: // connection
344: // The nonssl socket is needed to tunnel request to end server.
345: // Note: The nonssl socket is required because using the SSL
346: // socket for
347: // SSL Traffic will lead to double encryption. We want to avoid
348: // that.
349: //
350: String unqID = connection.getPort() + "_" + "A";
351: Object tmp_1 = GWLogManager.logIdMap.get(unqID);
352: if (tmp_1 != null) {
353:
354: LogInfoContainer info = (LogInfoContainer) tmp_1;
355: nonsslsocket = (Socket) info.getClientSocket();
356: }
357:
358: }
359:
360: if (checkNetlet && isNetletTraffic) {
361: // logger.info("RPRoxy received netlet request. Starting netlet
362: // session...");
363: logger.info("PSSRNTLT_CSPNEPROX063");
364: try {
365: connection.setSoTimeout(initialTimeout);
366: } catch (Exception ex) {
367: // logger.log(Level.SEVERE, "isNetletTraffic caught
368: // exception while setting setSoTimeout() : ", ex);
369: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX064");
370: }
371:
372: ESession es = new ESession(connection, logId);
373: try {
374: GWThreadPool.run(es);
375: } catch (InterruptedException e) {
376: // logger.log(Level.SEVERE, "Cannot run ESession", e);
377: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX065");
378: try {
379: connection.close();
380: MonitoringSubsystem
381: .handleEvent(SRAEvent.PLAIN_SOCKET_DESTROYED);
382: } catch (Exception e1) {
383: }
384: return;
385: }
386: } else if (checkProxylet && isEnd2EndSSLRequest) {
387: try {
388: connection.setSoTimeout(initialTimeout);
389: } catch (Exception ex) {
390: // logger.log(Level.SEVERE, "isNetletTraffic caught
391: // exception while setting setSoTimeout() : ", ex);
392: logger.log(Level.SEVERE, "PSSRNTLT_CSPNEPROX066");
393: }
394:
395: String req = null;
396: String host = null;
397: int port = 443;
398: try {
399: BufferedReader r = new BufferedReader(
400: new InputStreamReader(connection
401: .getInputStream()));
402:
403: req = r.readLine();
404: req = req.substring(req.indexOf(" "), req.length());
405: req = req.trim();
406:
407: host = req.substring(0, req.indexOf(":"));
408: port = Integer.parseInt(req.substring(req
409: .indexOf(":") + 1, req.length()));
410:
411: String cookie = r.readLine();
412:
413: SSOToken token = null;
414: try {
415: token = SSOTokenManager.getInstance()
416: .createSSOToken(cookie);
417: } catch (SSOException ssoe) {
418: try {
419: token = SSOTokenManager.getInstance()
420: .createSSOToken(
421: URLDecoder.decode(cookie));
422: } catch (SSOException ssoe2) {
423: // logger.log(Level.SEVERE, "Unable to create
424: // SSOToken ", ssoe2);
425: logger.log(Level.SEVERE,
426: "PSSRNTLT_CSPNEPROX067");
427: return;
428: }
429: }
430:
431: logger.log(Level.INFO, "PSSRNTLT_CSPNEPROX067"
432: + " check access deny list");
433: // check if the host is allowed to be accessed
434: UserProfile prof = new UserProfile(cookie);
435:
436: boolean matchFound = false;
437: boolean allowed = false;
438: String gwMinAuthLevel = (String) GatewayProfile
439: .getString("MinAuthLevel", "*");
440: String url = "https://" + host;
441: int minAuthLevel = 999;
442: String message = "Access Denied";
443: String userLocale = prof.getString(
444: "preferredlocale", "en_US");
445:
446: message = GWLocale.getPFString(
447: "AccessDeniedErrorMessage",
448: new Object[] { message }, userLocale);
449: ErrorResponse resp = null;
450:
451: if (!gwMinAuthLevel.equals("*")) {
452:
453: try {
454: minAuthLevel = Integer
455: .parseInt(gwMinAuthLevel);
456: } catch (NumberFormatException nfe) {
457: // logger.severe("Illegal Value for Gateway Min
458: // // Authentication Level");
459: logger.severe("PSSRRPROXY_CSPRCONHNDLR171");
460: resp = new ErrorResponse(message, token);
461: return;
462:
463: }
464: if (token.getAuthLevel() < minAuthLevel) {
465: resp = new ErrorResponse(message, token);
466: return;
467: }
468: }
469: // Check whether Access is allowed by auth level.
470: if (prof.getString(
471: "sunPortalGatewayAllowedAuthLevelResult",
472: "true").equalsIgnoreCase("false")) {
473: resp = new ErrorResponse(message, token);
474: return;
475: }
476:
477: logger.log(Level.INFO, "PSSRNTLT_CSPNEPROX067"
478: + " passed general tests ");
479: List list = prof
480: .getStringList("sunportalgatewayaccessdenylist");
481: Iterator iter = list.iterator();
482: String denyString;
483: String requrl = url;
484: while (iter.hasNext()) {
485: denyString = iter.next().toString();
486: logger.log(Level.INFO, "PSSRNTLT_CSPNEPROX067"
487: + " denystring " + denyString);
488: if (denyString.equals("*")) {
489: allowed = false;
490: matchFound = true;
491: break;
492: }
493:
494: logger.log(Level.INFO, "PSSRNTLT_CSPNEPROX067"
495: + " requrl " + requrl);
496: if (wildcardMatch(requrl, denyString)) {
497: logger
498: .log(Level.INFO,
499: "PSSRNTLT_CSPNEPROX067"
500: + " wildcarmatch "
501: + requrl);
502:
503: allowed = false;
504: matchFound = true;
505: break;
506: }
507: }
508:
509: if (!matchFound) {
510:
511: list = prof
512: .getStringList("sunportalgatewayaccessallowlist");
513: iter = list.iterator();
514: String allowString;
515: //System.out.println("Allow list - "+list);
516: while (iter.hasNext()) {
517: allowString = iter.next().toString();
518: /*
519: * if (requrl.startsWith(url)){ allowed = false; break; }
520: */
521: if (allowString.equals("*")) {
522: allowed = true;
523: matchFound = true;
524: break;
525: }
526:
527: if (wildcardMatch(requrl, allowString)) {
528: allowed = true;
529: matchFound = true;
530: break;
531: }
532: }
533: }
534:
535: if (!matchFound) {
536: // If not there in both lists - hence deny it.
537: allowed = false;
538: }
539:
540: if (!allowed) {
541: logger
542: .warning("Session: request is not allowed");
543: resp = new ErrorResponse(message, token);
544: sendResponseToClient(connection, resp);
545: return;
546: }
547:
548: } catch (IOException e) {
549: return;
550: } catch (Exception _e) {
551: return;
552: }
553:
554: ProxyletSession es = new ProxyletSession(nonsslsocket,
555: logId, host, port, connection);
556:
557: Thread _t = new Thread(es);
558: _t.start();
559:
560: /*
561: * try {
562: *
563: * GWThreadPool.run(es); } catch (InterruptedException e) { //
564: * logger.log(Level.SEVERE, "Cannot run ESession", e);
565: * logger.log(Level.SEVERE,"PSSRNTLT_CSPNEPROX068"); try {
566: * connection.close(); if
567: * (com.sun.portal.perf.rproxy.PerfContextObject.ENABLE_PERF) {
568: * com.sun.portal.perf.rproxy.SocketCount.decrementPlainSockets(); } }
569: * catch (Exception e1) { } return; }
570: */
571:
572: } else {
573: if (!ServiceIdentifier.isNetletProxy()) {
574: requestProcessor.processRequestInGWTheadPool(
575: connection, logId);
576: } else {
577: NetletProxy.processAmNotification(connection);
578: //closeSocket(connection);
579: }
580: }
581: }
582:
583: /*
584: * This method is taken from Profile.java of sp3 codebase and modified for
585: * use with Lihue - Mridul Does suffix or prefix or regular wildchar match
586: * depending on match value. If str1 matches str2 based on match type,
587: * return true, otherwise false. @param str1 string to be matched @param
588: * str2 string may contain one or more wildcard character '*' @return
589: * boolean value
590: */
591:
592: private boolean wildcardMatch(String str1, String str2) {
593: int beginIndex1 = 0;
594: int endIndex1 = 0;
595: int beginIndex2 = 0;
596: int endIndex2 = 0;
597: int strlen1 = str1.length();
598: int strlen2 = str2.length();
599: String substr = null;
600:
601: // if one of the string is null, consider it no match.
602: if ((str1.length() == 0) || (str2.length() == 0))
603: return (false);
604: if ((str1 == null) || (str2 == null))
605: return (false);
606:
607: if ((endIndex2 = str2.indexOf('*', beginIndex2)) != -1) {
608: // get the substring prior to the first '*'
609: substr = str2.substring(beginIndex2, endIndex2);
610:
611: // check if the first char in str2 is '*', i.e. the substring is
612: // null
613: if (endIndex2 > beginIndex2) {
614: // str1 contains the substring too? if not, no match
615: if ((beginIndex1 = str1
616: .indexOf(substr, beginIndex1)) == -1)
617: return (false);
618: // if it is not a SUFFIX match, then the prefixes should be
619: // equal
620: //if ((beginIndex1 != beginIndex2) && (match != SUFFIX))
621: if (beginIndex1 != beginIndex2)
622: return (false);
623: }
624: // move the pointer to next char after the substring already matched
625: beginIndex1 = beginIndex1 + (endIndex2 - beginIndex2);
626: if (endIndex2 >= strlen2 - 1)
627: return (true);
628: beginIndex2 = endIndex2 + 1;
629: } else // str2 doesn't contain wildcard '*'
630: {
631: if ((beginIndex1 = str1.indexOf(str2)) == -1)
632: return (false);
633: //if ((match == PREFIX) && (beginIndex1 == beginIndex2))
634: if (beginIndex1 == beginIndex2)
635: return (true);
636: //if ((match == REGULAR) && (strlen1 == strlen2))
637: //return(true);
638: //if ((match == SUFFIX) && ((strlen1 - beginIndex1) == strlen2))
639: //return(true);
640: return (false);
641: }
642:
643: // There are more than '*'s in str2, repeat what we have done
644: while ((endIndex2 = str2.indexOf('*', beginIndex2)) != -1) {
645: substr = str2.substring(beginIndex2, endIndex2);
646: if (endIndex2 > beginIndex2)
647: if ((beginIndex1 = str1
648: .indexOf(substr, beginIndex1)) == -1)
649: return (false);
650: beginIndex1 = beginIndex1 + (endIndex2 - beginIndex2);
651: if (endIndex2 >= strlen2 - 1)
652: return (true);
653: beginIndex2 = endIndex2 + 1;
654: }
655: // The substring after the last '*'
656: substr = str2.substring(beginIndex2, strlen2);
657:
658: if ((endIndex1 = str1.lastIndexOf(substr, strlen1 - 1)) == -1)
659: return (false);
660:
661: if (beginIndex1 > endIndex1)
662: return (false);
663:
664: //beginIndex1 = endIndex1;
665: // if ((match == PREFIX) || ((strlen1 - beginIndex1) == (strlen2 -
666: // beginIndex2)))
667: return (true);
668: //return(false);
669: }
670:
671: private void sendResponseToClient(Socket clientSocket,
672: ErrorResponse respObject) {
673: InputStream in = null;
674: try {
675: in = respObject.getContentStream();
676: respObject.setConnectionClose();
677: OutputStream out = clientSocket.getOutputStream();
678: byte headerBytes[] = respObject.getHeaderBytes();
679: logger.warning("Header bytes written "
680: + new String(headerBytes));
681: out.write(headerBytes);
682: out.write("Access Denied!".getBytes());
683: out.write("\n".getBytes());
684: out.flush();
685: out.close();
686: } catch (Exception e) {
687: }
688: }
689:
690: private String readRequest(InputStream in) throws IOException {
691: byte reply[] = new byte[100];
692: int replyLen = 0;
693: int newlinesSeen = 0;
694: boolean headerDone = false; /* Done on first newline */
695: boolean error = false;
696:
697: while (newlinesSeen < 2) {
698: int i = in.read();
699: if (i < 0) {
700: throw new IOException("Unexpected EOF from proxy");
701: }
702: if (i == '\n') {
703: headerDone = true;
704: ++newlinesSeen;
705: } else if (i != '\r') {
706: newlinesSeen = 0;
707: if (!headerDone && replyLen < reply.length) {
708: reply[replyLen++] = (byte) i;
709: }
710: }
711: }
712:
713: reply[replyLen++] = (byte) '\0';
714:
715: return new String(reply);
716: }
717:
718: // Methods of GWRunnable
719: public String getType() {
720: return RPROXY_THREAD;
721: }
722: // Methods of GWRunnable
723: }
724: }
|