Fri, 24 Sep 2010 22:42:14 -0700
6891766: Vulnerabilities in use of reflection in CORBA
Reviewed-by: hawtin
1 /*
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.corba.se.impl.transport;
28 import java.io.IOException;
29 import java.net.InetSocketAddress;
30 import java.net.ServerSocket;
31 import java.net.Socket;
32 import java.nio.channels.SelectableChannel;
33 import java.nio.channels.SelectionKey;
34 import java.nio.channels.ServerSocketChannel;
35 import java.nio.channels.SocketChannel;
36 import java.util.Iterator;
38 import com.sun.corba.se.pept.broker.Broker;
39 import com.sun.corba.se.pept.encoding.InputObject;
40 import com.sun.corba.se.pept.encoding.OutputObject;
41 import com.sun.corba.se.pept.protocol.MessageMediator;
42 import com.sun.corba.se.pept.transport.Acceptor;
43 import com.sun.corba.se.pept.transport.Connection;
44 import com.sun.corba.se.pept.transport.ContactInfo;
45 import com.sun.corba.se.pept.transport.EventHandler;
46 import com.sun.corba.se.pept.transport.InboundConnectionCache;
47 import com.sun.corba.se.pept.transport.Selector;
49 import com.sun.corba.se.spi.extension.RequestPartitioningPolicy;
50 import com.sun.corba.se.spi.ior.IORTemplate;
51 import com.sun.corba.se.spi.ior.TaggedProfileTemplate;
52 import com.sun.corba.se.spi.ior.iiop.IIOPAddress ;
53 import com.sun.corba.se.spi.ior.iiop.IIOPFactories;
54 import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate ;
55 import com.sun.corba.se.spi.ior.iiop.GIOPVersion ;
56 import com.sun.corba.se.spi.ior.iiop.AlternateIIOPAddressComponent;
57 import com.sun.corba.se.spi.logging.CORBALogDomains;
58 import com.sun.corba.se.spi.orb.ORB;
59 import com.sun.corba.se.spi.orbutil.threadpool.Work;
60 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
61 import com.sun.corba.se.spi.transport.CorbaAcceptor;
62 import com.sun.corba.se.spi.transport.CorbaConnection;
63 import com.sun.corba.se.spi.transport.SocketInfo;
64 import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor;
66 import com.sun.corba.se.impl.encoding.CDRInputObject;
67 import com.sun.corba.se.impl.encoding.CDROutputObject;
68 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
69 import com.sun.corba.se.impl.oa.poa.Policies; // REVISIT impl/poa specific
70 import com.sun.corba.se.impl.orbutil.ORBConstants;
71 import com.sun.corba.se.impl.orbutil.ORBUtility;
73 // BEGIN Legacy support.
74 import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketEndPointInfo;
75 // END Legacy support.
77 /**
78 * @author Harold Carr
79 */
80 public class SocketOrChannelAcceptorImpl
81 extends
82 EventHandlerBase
83 implements
84 CorbaAcceptor,
85 SocketOrChannelAcceptor,
86 Work,
87 // BEGIN Legacy
88 SocketInfo,
89 LegacyServerSocketEndPointInfo
90 // END Legacy
91 {
92 protected ServerSocketChannel serverSocketChannel;
93 protected ServerSocket serverSocket;
94 protected int port;
95 protected long enqueueTime;
96 protected boolean initialized;
97 protected ORBUtilSystemException wrapper ;
98 protected InboundConnectionCache connectionCache;
100 // BEGIN Legacy
101 protected String type = "";
102 protected String name = "";
103 protected String hostname;
104 protected int locatorPort;
105 // END Legacy
107 public SocketOrChannelAcceptorImpl(ORB orb)
108 {
109 this.orb = orb;
110 wrapper = ORBUtilSystemException.get( orb,
111 CORBALogDomains.RPC_TRANSPORT ) ;
113 setWork(this);
114 initialized = false;
116 // BEGIN Legacy support.
117 this.hostname = orb.getORBData().getORBServerHost();
118 this.name = LegacyServerSocketEndPointInfo.NO_NAME;
119 this.locatorPort = -1;
120 // END Legacy support.
121 }
123 public SocketOrChannelAcceptorImpl(ORB orb, int port)
124 {
125 this(orb);
126 this.port = port;
127 }
129 // BEGIN Legacy support.
130 public SocketOrChannelAcceptorImpl(ORB orb, int port,
131 String name, String type)
132 {
133 this(orb, port);
134 this.name = name;
135 this.type = type;
136 }
137 // END Legacy support.
139 ////////////////////////////////////////////////////
140 //
141 // pept.transport.Acceptor
142 //
144 public boolean initialize()
145 {
146 if (initialized) {
147 return false;
148 }
149 if (orb.transportDebugFlag) {
150 dprint(".initialize: " + this);
151 }
152 InetSocketAddress inetSocketAddress = null;
153 try {
154 if (orb.getORBData().getListenOnAllInterfaces().equals(ORBConstants.LISTEN_ON_ALL_INTERFACES)) {
155 inetSocketAddress = new InetSocketAddress(port);
156 } else {
157 String host = orb.getORBData().getORBServerHost();
158 inetSocketAddress = new InetSocketAddress(host, port);
159 }
160 serverSocket = orb.getORBData().getSocketFactory()
161 .createServerSocket(type, inetSocketAddress);
162 internalInitialize();
163 } catch (Throwable t) {
164 throw wrapper.createListenerFailed( t, Integer.toString(port) ) ;
165 }
166 initialized = true;
167 return true;
168 }
170 protected void internalInitialize()
171 throws Exception
172 {
173 // Determine the listening port (for the IOR).
174 // This is important when using emphemeral ports (i.e.,
175 // when the port value to the constructor is 0).
177 port = serverSocket.getLocalPort();
179 // Register with transport (also sets up monitoring).
181 orb.getCorbaTransportManager().getInboundConnectionCache(this);
183 // Finish configuation.
185 serverSocketChannel = serverSocket.getChannel();
187 if (serverSocketChannel != null) {
188 setUseSelectThreadToWait(
189 orb.getORBData().acceptorSocketUseSelectThreadToWait());
190 serverSocketChannel.configureBlocking(
191 ! orb.getORBData().acceptorSocketUseSelectThreadToWait());
192 } else {
193 // Configure to use listener and reader threads.
194 setUseSelectThreadToWait(false);
195 }
196 setUseWorkerThreadForEvent(
197 orb.getORBData().acceptorSocketUseWorkerThreadForEvent());
199 }
201 public boolean initialized()
202 {
203 return initialized;
204 }
206 public String getConnectionCacheType()
207 {
208 return this.getClass().toString();
209 }
211 public void setConnectionCache(InboundConnectionCache connectionCache)
212 {
213 this.connectionCache = connectionCache;
214 }
216 public InboundConnectionCache getConnectionCache()
217 {
218 return connectionCache;
219 }
221 public boolean shouldRegisterAcceptEvent()
222 {
223 return true;
224 }
226 public void accept()
227 {
228 try {
229 SocketChannel socketChannel = null;
230 Socket socket = null;
231 if (serverSocketChannel == null) {
232 socket = serverSocket.accept();
233 } else {
234 socketChannel = serverSocketChannel.accept();
235 socket = socketChannel.socket();
236 }
237 orb.getORBData().getSocketFactory()
238 .setAcceptedSocketOptions(this, serverSocket, socket);
239 if (orb.transportDebugFlag) {
240 dprint(".accept: " +
241 (serverSocketChannel == null
242 ? serverSocket.toString()
243 : serverSocketChannel.toString()));
244 }
246 CorbaConnection connection =
247 new SocketOrChannelConnectionImpl(orb, this, socket);
248 if (orb.transportDebugFlag) {
249 dprint(".accept: new: " + connection);
250 }
252 // NOTE: The connection MUST be put in the cache BEFORE being
253 // registered with the selector. Otherwise if the bytes
254 // are read on the connection it will attempt a time stamp
255 // but the cache will be null, resulting in NPE.
256 getConnectionCache().put(this, connection);
258 if (connection.shouldRegisterServerReadEvent()) {
259 Selector selector = orb.getTransportManager().getSelector(0);
260 selector.registerForEvent(connection.getEventHandler());
261 }
263 getConnectionCache().reclaim();
265 } catch (IOException e) {
266 if (orb.transportDebugFlag) {
267 dprint(".accept:", e);
268 }
269 orb.getTransportManager().getSelector(0).unregisterForEvent(this);
270 // REVISIT - need to close - recreate - then register new one.
271 orb.getTransportManager().getSelector(0).registerForEvent(this);
272 // NOTE: if register cycling we do not want to shut down ORB
273 // since local beans will still work. Instead one will see
274 // a growing log file to alert admin of problem.
275 }
276 }
278 public void close ()
279 {
280 try {
281 if (orb.transportDebugFlag) {
282 dprint(".close->:");
283 }
284 Selector selector = orb.getTransportManager().getSelector(0);
285 selector.unregisterForEvent(this);
286 if (serverSocketChannel != null) {
287 serverSocketChannel.close();
288 }
289 if (serverSocket != null) {
290 serverSocket.close();
291 }
292 } catch (IOException e) {
293 if (orb.transportDebugFlag) {
294 dprint(".close:", e);
295 }
296 } finally {
297 if (orb.transportDebugFlag) {
298 dprint(".close<-:");
299 }
300 }
301 }
303 public EventHandler getEventHandler()
304 {
305 return this;
306 }
308 ////////////////////////////////////////////////////
309 //
310 // CorbaAcceptor
311 //
313 public String getObjectAdapterId()
314 {
315 return null;
316 }
318 public String getObjectAdapterManagerId()
319 {
320 return null;
321 }
323 public void addToIORTemplate(IORTemplate iorTemplate,
324 Policies policies,
325 String codebase)
326 {
327 Iterator iterator = iorTemplate.iteratorById(
328 org.omg.IOP.TAG_INTERNET_IOP.value);
330 String hostname = orb.getORBData().getORBServerHost();
332 if (iterator.hasNext()) {
333 // REVISIT - how does this play with legacy ORBD port exchange?
334 IIOPAddress iiopAddress =
335 IIOPFactories.makeIIOPAddress(orb, hostname, port);
336 AlternateIIOPAddressComponent iiopAddressComponent =
337 IIOPFactories.makeAlternateIIOPAddressComponent(iiopAddress);
339 while (iterator.hasNext()) {
340 TaggedProfileTemplate taggedProfileTemplate =
341 (TaggedProfileTemplate) iterator.next();
342 taggedProfileTemplate.add(iiopAddressComponent);
343 }
344 } else {
345 GIOPVersion version = orb.getORBData().getGIOPVersion();
346 int templatePort;
347 if (policies.forceZeroPort()) {
348 templatePort = 0;
349 } else if (policies.isTransient()) {
350 templatePort = port;
351 } else {
352 templatePort = orb.getLegacyServerSocketManager()
353 .legacyGetPersistentServerPort(SocketInfo.IIOP_CLEAR_TEXT);
354 }
355 IIOPAddress addr =
356 IIOPFactories.makeIIOPAddress(orb, hostname, templatePort);
357 IIOPProfileTemplate iiopProfile =
358 IIOPFactories.makeIIOPProfileTemplate(orb, version, addr);
359 if (version.supportsIORIIOPProfileComponents()) {
360 iiopProfile.add(IIOPFactories.makeCodeSetsComponent(orb));
361 iiopProfile.add(IIOPFactories.makeMaxStreamFormatVersionComponent());
362 RequestPartitioningPolicy rpPolicy = (RequestPartitioningPolicy)
363 policies.get_effective_policy(
364 ORBConstants.REQUEST_PARTITIONING_POLICY);
365 if (rpPolicy != null) {
366 iiopProfile.add(
367 IIOPFactories.makeRequestPartitioningComponent(
368 rpPolicy.getValue()));
369 }
370 if (codebase != null && codebase != "") {
371 iiopProfile.add(IIOPFactories. makeJavaCodebaseComponent(codebase));
372 }
373 if (orb.getORBData().isJavaSerializationEnabled()) {
374 iiopProfile.add(
375 IIOPFactories.makeJavaSerializationComponent());
376 }
377 }
378 iorTemplate.add(iiopProfile);
379 }
380 }
382 public String getMonitoringName()
383 {
384 return "AcceptedConnections";
385 }
387 ////////////////////////////////////////////////////
388 //
389 // EventHandler methods
390 //
392 public SelectableChannel getChannel()
393 {
394 return serverSocketChannel;
395 }
397 public int getInterestOps()
398 {
399 return SelectionKey.OP_ACCEPT;
400 }
402 public Acceptor getAcceptor()
403 {
404 return this;
405 }
407 public Connection getConnection()
408 {
409 throw new RuntimeException("Should not happen.");
410 }
412 ////////////////////////////////////////////////////
413 //
414 // Work methods.
415 //
417 /* CONFLICT: with legacy below.
418 public String getName()
419 {
420 return this.toString();
421 }
422 */
424 public void doWork()
425 {
426 try {
427 if (orb.transportDebugFlag) {
428 dprint(".doWork->: " + this);
429 }
430 if (selectionKey.isAcceptable()) {
431 accept();
432 } else {
433 if (orb.transportDebugFlag) {
434 dprint(".doWork: ! selectionKey.isAcceptable: " + this);
435 }
436 }
437 } catch (SecurityException se) {
438 if (orb.transportDebugFlag) {
439 dprint(".doWork: ignoring SecurityException: "
440 + se
441 + " " + this);
442 }
443 String permissionStr = ORBUtility.getClassSecurityInfo(getClass());
444 wrapper.securityExceptionInAccept(se, permissionStr);
445 } catch (Exception ex) {
446 if (orb.transportDebugFlag) {
447 dprint(".doWork: ignoring Exception: "
448 + ex
449 + " " + this);
450 }
451 wrapper.exceptionInAccept(ex);
452 } catch (Throwable t) {
453 if (orb.transportDebugFlag) {
454 dprint(".doWork: ignoring Throwable: "
455 + t
456 + " " + this);
457 }
458 } finally {
460 // IMPORTANT: To avoid bug (4953599), we force the
461 // Thread that does the NIO select to also do the
462 // enable/disable of Ops using SelectionKey.interestOps().
463 // Otherwise, the SelectionKey.interestOps() may block
464 // indefinitely.
465 // NOTE: If "acceptorSocketUseWorkerThreadForEvent" is
466 // set to to false in ParserTable.java, then this method,
467 // doWork(), will get executed by the same thread
468 // (SelectorThread) that does the NIO select.
469 // If "acceptorSocketUseWorkerThreadForEvent" is set
470 // to true, a WorkerThread will execute this method,
471 // doWork(). Hence, the registering of the enabling of
472 // the SelectionKey's interestOps is done here instead
473 // of calling SelectionKey.interestOps(<interest op>).
475 Selector selector = orb.getTransportManager().getSelector(0);
476 selector.registerInterestOps(this);
478 if (orb.transportDebugFlag) {
479 dprint(".doWork<-:" + this);
480 }
481 }
482 }
484 public void setEnqueueTime(long timeInMillis)
485 {
486 enqueueTime = timeInMillis;
487 }
489 public long getEnqueueTime()
490 {
491 return enqueueTime;
492 }
495 //
496 // Factory methods.
497 //
499 // REVISIT: refactor into common base or delegate.
500 public MessageMediator createMessageMediator(Broker broker,
501 Connection connection)
502 {
503 // REVISIT - no factoring so cheat to avoid code dup right now.
504 // REVISIT **** COUPLING !!!!
505 ContactInfo contactInfo = new SocketOrChannelContactInfoImpl();
506 return contactInfo.createMessageMediator(broker, connection);
507 }
509 // REVISIT: refactor into common base or delegate.
510 public MessageMediator finishCreatingMessageMediator(Broker broker,
511 Connection connection,
512 MessageMediator messageMediator)
513 {
514 // REVISIT - no factoring so cheat to avoid code dup right now.
515 // REVISIT **** COUPLING !!!!
516 ContactInfo contactInfo = new SocketOrChannelContactInfoImpl();
517 return contactInfo.finishCreatingMessageMediator(broker,
518 connection, messageMediator);
519 }
521 public InputObject createInputObject(Broker broker,
522 MessageMediator messageMediator)
523 {
524 CorbaMessageMediator corbaMessageMediator = (CorbaMessageMediator)
525 messageMediator;
526 return new CDRInputObject((ORB)broker,
527 (CorbaConnection)messageMediator.getConnection(),
528 corbaMessageMediator.getDispatchBuffer(),
529 corbaMessageMediator.getDispatchHeader());
530 }
532 public OutputObject createOutputObject(Broker broker,
533 MessageMediator messageMediator)
534 {
535 CorbaMessageMediator corbaMessageMediator = (CorbaMessageMediator)
536 messageMediator;
537 return new CDROutputObject((ORB) broker, corbaMessageMediator,
538 corbaMessageMediator.getReplyHeader(),
539 corbaMessageMediator.getStreamFormatVersion());
540 }
542 ////////////////////////////////////////////////////
543 //
544 // SocketOrChannelAcceptor
545 //
547 public ServerSocket getServerSocket()
548 {
549 return serverSocket;
550 }
552 ////////////////////////////////////////////////////
553 //
554 // Implementation.
555 //
557 public String toString()
558 {
559 String sock;
560 if (serverSocketChannel == null) {
561 if (serverSocket == null) {
562 sock = "(not initialized)";
563 } else {
564 sock = serverSocket.toString();
565 }
566 } else {
567 sock = serverSocketChannel.toString();
568 }
570 return
571 toStringName() +
572 "["
573 + sock + " "
574 + type + " "
575 + shouldUseSelectThreadToWait() + " "
576 + shouldUseWorkerThreadForEvent()
577 + "]" ;
578 }
580 protected String toStringName()
581 {
582 return "SocketOrChannelAcceptorImpl";
583 }
585 protected void dprint(String msg)
586 {
587 ORBUtility.dprint(toStringName(), msg);
588 }
590 protected void dprint(String msg, Throwable t)
591 {
592 dprint(msg);
593 t.printStackTrace(System.out);
594 }
596 // BEGIN Legacy support
597 ////////////////////////////////////////////////////
598 //
599 // LegacyServerSocketEndPointInfo and EndPointInfo
600 //
602 public String getType()
603 {
604 return type;
605 }
607 public String getHostName()
608 {
609 return hostname;
610 }
612 public String getHost()
613 {
614 return hostname;
615 }
617 public int getPort()
618 {
619 return port;
620 }
622 public int getLocatorPort()
623 {
624 return locatorPort;
625 }
627 public void setLocatorPort (int port)
628 {
629 locatorPort = port;
630 }
632 public String getName()
633 {
634 // Kluge alert:
635 // Work and Legacy both define getName.
636 // Try to make this behave best for most cases.
637 String result =
638 name.equals(LegacyServerSocketEndPointInfo.NO_NAME) ?
639 this.toString() : name;
640 return result;
641 }
642 // END Legacy support
643 }
645 // End of file.