Internet Engineering Task Force ftw. INTERNET-DRAFT K. Peterbauer draft-peterbauer-sip-servlet-ext-00.txt (Kapsch AG) February 14, 2001 J. Stadler, I. Miladinovic, T. Pudil Expires: August, 2001 (IKN, Vienna University of Technology) SIP Servlet API Extensions Status of this Memo This document is an Internet-Draft and is in full conformance with all provisions of Section 10 of RFC2026 [1]. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet- Drafts. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet- Drafts as reference material or to cite them other than as "work in progress." The list of current Internet-Drafts can be accessed at http://www.ietf.org/ietf/1id-abstracts.txt The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html. Copyright Notice Copyright (C) The Internet Society (2001). All Rights Reserved. Abstract This document improves and extends the SIP Servlet API defined in [2]. The SIP Servlet API defines a mechanism, which enables the encapsulation of service logic in so called SIP Servlets on the top of the protocol stack of a SIP Server. A very important point, which is not treated by [2] is the interoperability of services. [3] proposes a first approach to overcome this problem with a so called root servlet. In this Internet draft we define a more generic model to perform a combination or interaction of SIP Servlets. This makes the servlet approach to a very powerful alternative also in UMTS to connect SIP Proxy and Service Logic. Table of Contents 1 Introduction..........................................2 1.1 Background..........................................2 1.2 Overview............................................3 2 Filtering.............................................7 3 Servlet Lifetime Policies.............................8 Peterbauer, Stadler, Miladinovic, Pudil [Page 1] Internet Draft SIP Servlet API Extensions February 2001 4 Servlet Descriptors...................................9 5 Contact Database......................................9 6 SIP Services.........................................10 6.1 Dispatching Services...............................10 6.2 Service Descriptor.................................10 6.3 Service Deployment.................................10 7 API Reference........................................11 7.1 SipConfiguration...................................11 7.2 SipFilter..........................................11 7.3 SipFilterChain.....................................12 7.4 SipFilterConfig....................................12 7.5 SipMessageDispatcher...............................12 7.6 SipServiceDispatcher...............................13 7.7 SipServletContext..................................14 7.8 SipRequestWrapper..................................14 7.9 SipResponseWrapper.................................14 8 Security Considerations..............................14 9 Acknowledgement......................................14 10 References...........................................15 11 Authors Addresses....................................15 12 Appendix: The SIP Servlet API........................16 13 Full Copyright Statement.............................31 1 Introduction 1.1 Background The SIP Servlet API [2], which is very similar to the concept for HTTP servlets [4], is a very good approach to define a modular mechanism to encapsulate service logic on top of the SIP Stack in a SIP Server, for instance a SIP Proxy in the UMTS core. By this a wide range of services could be implemented inside of such a servlet. The API sufficiently defines the programming interface between the SIP Server (called Servlet Container in the following) and a single SIP Servlet. However, several key features to support the development, deployment and maintainance of complex enterprise- level SIP Services in a portable, vendor-neutral way are left as open issues: - Servlet Interaction, Servlet Communication: It is essential that the API allows multiple servlets to process an incoming SIP message. - Filtering: Customization of the request and response objects defined by the API. - Serlvet Lifetime Policies: The SIP Servlet API leaves the decision when to destroy a servlet entirely to the container. This standard policy causes problems for servlets, which communicate with the outside world with other means than the SIP Servlet API. - Servlet Descriptors: While the programmatic configuration of a Peterbauer, Stadler, Miladinovic, Pudil [Page 2] Internet Draft SIP Servlet API Extensions February 2001 servlet is specified, it is not defined how this configuration is loaded into the container. - Servlet Mapping: The SIP Servlet API does not define the mechanism used for triggering servlets from SIP Messages. - The API does not support the abstraction of a SIP Service as a collection of interacting servlets and the deployment and maintainance of such a service. - Contact Database: The Contact Database defined by the API is implemented by the container vendor, prohibiting to plug-in custom implementations. This draft attempts to define extensions to the existing API with respect to these open issues. 1.2 Overview Before we go more in detail, we need to define the term service for our context. A service is a collection of interacting SIP Servlets, necessary helper classes, filters, other resources, and their configuration data that can be bundled and run on any standard- compliant SIP Server (container) from any vendor. Services have to be deployed to SIP Servers not only in the way that all necessary servlets are deployed, but a definition of the service has to be deployed too. A possibility to do this is shown in chapter 6, where a so called Service Descriptor is used. This Descriptor provides the option for the Servlet Container or the administrator of the SIP Server to check the service according to some rules. The rules depend on the policies for the SIP Server and the process of checking is out of scope for this document. Another term which has to be explained is filter. We are the opinion that some functionalities are not easy to implement in a servlet. A good example is the simple case of logging. Sure, it would be possible to call a log servlet every time it could be necessary. A more easy way would be do apply a filter to a SIP Message, which wraps the original Request or Response in the way that a log command is executed for instance in every case the request.send(SipURL url) or response.send() method is invoked. By this it would be furthermore very easy to restrict the possibilities of single, maybe not self written, servlets. A more detailed description of the filter concept we want to give in chapter 2. Figure 1 gives an overview to our architecture. The SIP Stack of the SIP Server receives a SIP Message, for instance a request. After processing, it gives it to the Servlet Container. Now it has to be checked, which service is required. For this the function getServiceName(SipRequest request) of the Service Dispatcher is called. The Service Dispatcher checks the Require Header or, if no service is specified there, it could check some Peterbauer, Stadler, Miladinovic, Pudil [Page 3] Internet Draft SIP Servlet API Extensions February 2001 conditions on the other headers. If no service could be found a default service could be used. So the Service Dispatcher can return a symbolic name of the service. Now the, for the first servlet necessary filters could be applied to the Message, calling doFilter(SipMessage message, FilterChain chain). The Filter Chain parameter is an Interface of the Container, by which further filters or other ressources, e.g. the servlet, could be invoked. By this, the now wrapped message is given to the first servlet (called Primary Servlet in the following) by calling gotRequest(SipRequest requ) or gotResponse (SipResponse resp). The Primary Servlet processes the request and, if necessary, forwards it to further servlets. +------------+ | Service | | Dispatcher | +------------+ | API | +----------+-----+------------+-----+ SIP | | | Message | SIP | Servlet | ---------->| Stack | Container | | | | +----------+-----+------------+-----+ | API | | API | +-----+ +-----+ +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ Filters Servlets Figure 1 [3] proposes an interaction pattern which allows a servlet to return a sequence of other servlet instances to the container. The container forwards the SIP Message to those target servlets. The draft does not explicitly define how this sequence of servlets looks like. Possible strategies are to return a sequence of servlet instances or a sequence of symbolic names. We believe that this pattern has the drawback that the Primary Servlet does not regain control over the message processing cycle after the invocation of the target servlets. Basically the pattern invents a strict servlet chaining mechanism, but does not support servlet nesting: The initiating servlet may wish to perform some kind of post-processing after the invocation of one or more target servlets. Maybe the initiating servlet wishes only to log the invocation, or it may wish to invoke yet another servlet depending on the results of the target servlets. To overcome this drawback, we suggest that the container provides a standardized Message Dispatcher interface similarly as provided by the HTTP Servlet API [4], which allows one servlet to pass the Peterbauer, Stadler, Miladinovic, Pudil [Page 4] Internet Draft SIP Servlet API Extensions February 2001 control over the message processing cycle to another servlet identified by a symbolic name, and to regain control after invocation. The coupling between the servlets can be kept low by adding a mechanism for the configurable resolution of those symbolic names to servlet classes. The Servlets Descriptor (described in detail below) may provide a list of all symbolic names used by the servlet code, together with a description of the expected functionality of the specified servlet. In the deployment phase those names are mapped to actual servlet classes. As a consequence of low coupling, no direct servlet-to-servlet communication is allowed, e.g. by directly invoking methods of the SipServlet interface or additionally defined methods. The well-known patterns of indirect communication using (not necessarily local) shared objects can be applied. The complete course of action can be described as follows: - The initial servlet inspects the SIP message and detects that the message shall be forwarded to another servlet. - The servlet accesses the Message Dispatcher interface and forwards the message to the servlet identified by a (hard-coded) symbolic name as well as the necessary filters. - Filters are applied either to the original message or to the message forwarded by the former servlet. - The Message Dispatcher resolves the appropriate servlet instance by using the mapping of symbolic names to servlets provided by the configuration data. - The Message Dispatcher might have to instantiate and initialize the target servlet. - The Message Dispatcher invokes the target servlet. - The target servlets processes the message. Afterwards it either forwards it again or it returns. - The Message Dispatcher passes the result of the invocation back to the initial servlet as result of the forward method. - The initiating servlet may perform any postprocessing, or may forward the call to other servlets. Figure 2 gives an overview to this process. For a better survay, the return path is not drawn here. Every arrow is a function call. A very important point in our design is, that conditional services are possible, which means, that depending on the result of the processing of the message by a servlet the further path in the service is chosen. Here it is important to underline, that the Peterbauer, Stadler, Miladinovic, Pudil [Page 5] Internet Draft SIP Servlet API Extensions February 2001 servlet does not know the next servlet. It only generates a symbolic name, which identifies the out coming of the service proceeding and which is given back to the container by the forward(SipRequest requ, sring servletName) call. +------------------------------------+ | Servlet Container | +-----------+------------+-----------+ | API | | API | +-----------+ +-----------+ || /\ || /\ || /\ || 1\/ ||2 5\/ ||6 3\/ ||4 \/7 +--+ +--+ +--+ +--+ | | | | | | | | +--+ +--+ +--+ +--+ Filters Servlets Figure 2 The approach has the advantage of a very loose servlet coupling, high flexibility, and even support for interaction between distributed servlets: - No hard-coding of target servlet classes necessary. - No unique naming scheme of servlets necessary. - Reconfiguration of a deployed service possible without changing code, but simply by changing the name mapping. - Since the message dispatcher intercepts all servlet invocations, it is possible to forward the call to a servlet running in another virtual machine, potentially on another host. SIP may be used as distribution protocol, but also any other distribution protocol can be implemented by the container (e.g., Java RMI or CORBA IIOP with fast binary encodings). Please note that this distribution mechanism is opaque to the interacting servlets, as long as they do not rely on local shared objects. Therefore servlets should be explicitly declared as distributable. As an example we consider the following scenario: Incoming SIP Messages shall be processed differently for different groups of users (e.g., according to the customers service contract). Several servlets have been developed or bought off-the-shelf, tailored for the needs of a certain user group. A specialized servlet shall implement the necessary dispatching logic, depending e.g. on the "From" header of a SIP Message. The implementation of this Primary Servlet inspects the SIP Message and detects the callers user- group in an application-specific way (e.g., by querying some data storage). The Primary Servlet forwards the message by calling the Message Dispatcher with one the symbolic names "gold-customer- servlet", "silver-customer-servlet" or "bronze-customer-servlet". Peterbauer, Stadler, Miladinovic, Pudil [Page 6] Internet Draft SIP Servlet API Extensions February 2001 The configuration data might map the name "gold-customer-servlet" to a servlet of class my.org.GoldCustServlet. 2 Filtering Filtering is a simple concept found in the HTTP Servlet API. With slight adaptions it is a valuable mechanism for SIP Servlets. The SIP Servlet API models SIP messages as Java interfaces, which are implemented by the Servlet Container in a vendor-specific way. It might be desirable to adapt the behavior of those objects in a custom way. For example, some form of application-specific logging shall be applied whenever a request is sent to another SIP Server. Typically this kind of logging will be implemented by the servlet itself. However, this is not possible if the servlet class has been bought off-the-shelf. Another example is that the desired functionality is implemented by a set of collaborating servlets, but it is not desirable that each and every servlet has to take care for logging. Filters are objects which intercept invocations of a servlet and receive the SIP Message object which shall be passed to the servlet. They can inspect and modify the message, or they can even replace or wrap the message object with a custom implementation as can be seen in Figure 3 for a simple log filter. +------------------+ | SipRequest | +------------------+ | send(SipURL) | | createResponse() | | ... | +------------------+ || Log || Filter \/ +-------------------------------------------------+ | SipRequestWrapper | +-------------------------------------------------+ | +------------------+ | | | SIP Request | send(SipURL) | | +------------------+ {log() | | | send(SipURL) | <--- old.send(SipURL)} | | | createResponse() | createResponse() | | | ... | <---{old.createResponse()} | | +------------------+ | +-------------------------------------------------+ Figure 3 Peterbauer, Stadler, Miladinovic, Pudil [Page 7] Internet Draft SIP Servlet API Extensions February 2001 Filters can preprocess SIP Messages for an arbitrary number of servlets. A single servlet can be configured to be filtered by an arbitrary number of Filter objects. Possible use-cases are: - Authentication, authorization and autiting filters. - Logging filters. - Filters firing certain events on general event channels with decoupled listeners. Filter configuration, filter chaining and associating filters with servlets can be defined in alignment with the HTTP Servlet API. Though there are major differences to the HTTP version: HTTP is a simple request-response protocol, but in SIP there is no one-to-one relationship between a request and the response, and a SIP Servlet may fork the request etc. Therefore filtering is not applied to a request/response pair, but to a single SIP Message. To make it possible that every Servlet Container can use same filters, it is necessary to define the org.ietf.sip.Filter interface in the SIP Servlet API. The filter developer creates a filter by implementing this interface. The whole description of this interface will be given in chapter 7. Before a servlet is called, the necessary filters are applied, calling doFilter(SipMessage msg, FilterChain chain). This is done for all filters, which are specified by the service for that servlet and than calls the servlet method gotRequest(SipRequest requ) or gotResponse(SipResponse resp). The Servlet Container keeps the copy of the original (non-wrapped) message and after the Servlet has finished, does the same action with the next Servlet (if any). For the next Servlet, different filter(s) (or no one filter) could be defined and therefore the original message must be stored. 3 Servlet Lifetime Policies The SIP Servlet API leaves the decision when to destroy a servlet entirely to the container implementation. While this standard policy of container-controlled lifetime will be sufficient in many cases, it may be desirable to support different kinds of lifetime policies. For example, a servlet may contact some remote server using some other distribution protocol like Java RMI or CORBA IIOP and may wish to receive callbacks from this remote server, prohibiting container-controlled destruction of the servlet. Thus following policies are candidates for a more sophisticated lifetime management: Peterbauer, Stadler, Miladinovic, Pudil [Page 8] Internet Draft SIP Servlet API Extensions February 2001 - Container-controlled: This is the standard policy, leaving all lifetime decisions to the container. - Servlet-controlled: The container must not destroy the servlet as long the the container is not shutdown itself. The servlet itself may request destruction, using a new method of the SipServletContext interface. This solution has the disadvantage that now a separate context instance is necessary for every servlet and context instances cannot be shared. Therefore this method is not defined in the API reference. For further study. - Load-on-startup options for both policies. Other policies are possible, e.g. lifetime per transaction or even per invocation. 4 Servlet Descriptors A similar descriptor mechanism as defined by the HTTP Servlet API can be applied, using XML as descriptor format, including some additional features: - The definition of all symbolic names expected by the servlet is included. - The servlets desired lifetime policy and options for loading on startup. - Description of the expected initialization parameters: type (e.g. string, boolean, integer, file, URL, ..), default values, flag if mandatory or optional, .. 5 Contact Database The Contact Database defined by the API is implemented by the container vendor, prohibiting to plug-in custom implementations. It is desirable to provide a simple plug-in mechanism. By requiring that a Contact Database implementation provides a public no-arg constructor the container can easily be configured to instantiate and use a custom implementation instead of its own default implementation. Key benefits are that a custom implementation can be integrated in any existing environment, using existing databases (LDAP, relational, file, à), the database can be filled with registration information other than SIP REGISTER [5] requests, and the contained data can be evaluated with any existing too. The SIP Servlet API has to be changed as far as the interface SipServletContext shall not extend the ContactDatabase interface, but provides access to the database with a new method. Additional methods for intitialization and destruction lead to a clean design. Peterbauer, Stadler, Miladinovic, Pudil [Page 9] Internet Draft SIP Servlet API Extensions February 2001 6 SIP Services A definition of the term service has been given in chapter 1. 6.1 Dispatching Services The main purpose of the Service Dispatching is to find the right service for a SIP Message and to give this service back to the Servlet Container. After receiving a SIP Request, the container calls the getServiceName(SipRequest request) method of the Service Dispatcher with the SIP Request as parameter. The return value of this method is a String containing the symbolic servlet name of the chosen service. The "Require" header field [5] of the request can be used to indicate which service should be used for this request. If the "Require" header is not specified or the Service Dispatcher cannot find the service specified in "Require" header, it must return a service according to other rules. This draft does not define these rules, but several parts of the SIP Message could be used to find a service, for example: Request URI, Method, From header, Timestamp header etc. It is also possible to define a default Service that implements usually proxy functionality. This service is than used, if the request does not match any of the dispatching rules. 6.2 Service Descriptor The configuration of a SIP Service can be done in a standardized way, again using XML descriptors commonly known from the HTTP Servlet API. A service descriptor contains: - the descriptors of the servlets of the service, - the descriptors of the custom filters of the service, - the filters to be applied for every servlet, - the mapping of the symbolic names used by the servlets to dispatch messages to other servlets, - the Primary Servlet which is always invoked when the Service Dispatcher decides to dispatch to this service, - a flag if the service is distributable, - optional initialization parameters global to the service and exposed to the servlets and filters, - optional declaration of a custom contact database implementation, - additional miscellaneous information such as a Service Description, version information, dependencies such as constraints concerning the Java runtime environment (JDK version) etc. 6.3 Service Deployment Again we can align the SIP Servlet API with the HTTP Servlet API by defining a similar mechanism for packaging a SIP Service as a single compressed file using Javas standard archive format (JAR), Peterbauer, Stadler, Miladinovic, Pudil [Page 10] Internet Draft SIP Servlet API Extensions February 2001 together with the service descriptor. Key benefit is that a service can be assembled and deployed in a way which is independent of the vendor of the servlet container on which the service shall be deployed. A potential problem of this approach is that it does not support sharing of binaries used by more than one service. This problem could be solved by using global unique names for the servlets. By this, it is possible at deployment time to find eventually existing servlets. So the mapping could be done including not only the servlets from the deployed jar package. servlets. 7 API Reference This draft proposes a few additional interfaces and methods to the existing SIP Servlet API. All interfaces are placed in package org.ietf.sip. As a further extension it is proposed that all relevant methods defined so far may throw an additional exception of class java.io.IOException, so that a servlet can react properly on e.g. broken communication links. 7.1 SipConfiguration public interface SipConfiguration Generic interface used by the servlet container used to pass information to a configurable entity during initialization. Additional convenience methods should be added, e.g. for getting parameters of primitives types other than strings. public String getInitParameter(String name) Returns a string containing the value of the named initialization parameter, or null if the parameter does not exist. public java.util.Iterator getInitParametersNames() Returns an iterator for all string containing the string names of all initialization parameters of this configuration objects. The iterator is read-only does not allow removal of entries. 7.2 SipFilter public interface SipFilter The interface which can be implemented and plugged in into the container for custom filtering. public void destroy() Peterbauer, Stadler, Miladinovic, Pudil [Page 11] Internet Draft SIP Servlet API Extensions February 2001 Filter destruction. The filter has to release all acqired resources and perform any necessary cleanup. public boolean doFilter(SipMessage message, FilterChain chain) throws ServletException, java.io.IOException The doFilter method of the filter is called by the container each time a request is passed through the chain due to a client message for the servlet at the end of the chain. The filter chain passed in to this method allows the filter to pass on the message to the next entity in the chain. The filter may modify the message, or wrap it with a custom implementation. The return value has the same semantics as the corresponding gotRequest/ gotResponse methods of the SipServlet interface. public void init(FilterConfig config) throws ServletException Filter initialization. The filter may react on an incomplete or malformed configuration by throwing an excpeption. 7.3 SipFilterChain public interface SipFilterChain Interface provided by the servlet container to invoke the next filter in the chain, or the target servlet if the filter is the last one in the chain. public boolean doFilter(SipMessage message) throws ServletException, java.io.IOException Causes the next filter in the chain to be invoked, or if the calling filter is the last filter in the chain, causes the resource at the end of the chain to be invoked. The return value is the return value of the next entity. 7.4 SipFilterConfig public interface FilterConfig extends SipConfiguration Used by the servlet container used to pass information to a filter during initialization. public String getFilterName() Returns the filter-name of this filter as defined in the deployment descriptor. public SipServletContext getServletContext() Returns a reference to the callers servlet context. 7.5 SipMessageDispatcher Peterbauer, Stadler, Miladinovic, Pudil [Page 12] Internet Draft SIP Servlet API Extensions February 2001 public interface SipMessageDispatcher New interface provided by the servlet container for dispatching SIP Messages to other servlets. public boolean forward(SipServletRequest requ, String servletName) throws ServletException, java.io.IOException Forwards the given request to the servlet identified by a symbolic servlet name. The result is the result of the invocation of the target servlet. public boolean forward(SipServletResponse resp, String servletName) throws ServletException, java.io.IOException Forwards the given response to the servlet identified by a symbolic servlet name. The result is the result of the invocation of the target servlet. 7.6 SipServiceDispatcher public interface SipServiceDispatcher Every Servlet Container uses a single instance of the interface for dispatching incoming message with a new SIP transaction demarcation. This interface allows to plug-in custom implementations. Custom dispatchers must provide a public no-arg constructor. public void destroy() Dispatcher destruction. public void init(SipConfiguration config, java.util.Iterator services)throws ServletException Dispatcher initialization. The service parameter is an iterator which could be used to support the Service Dispatcher with a list of installed services. The dispatcher may react on an incomplete or malformed configuration by throwing an exception. public String getServiceName(SipServletRequest request) throws ServletException Gets the symbolic name of the service for processing the given request. How the dispatcher finds out the name is completely unspecified. public String getServiceName(SipServletResponse response) throws ServletException Gets the symbolic name of the service for processing the given response. How the dispatcher finds out the name is completely Peterbauer, Stadler, Miladinovic, Pudil [Page 13] Internet Draft SIP Servlet API Extensions February 2001 unspecified. 7.7 SipServletContext public interface SipServletContext Already defined by the API. However, it is proposed that this interface does not extend the ContactDatabase interface, but allows to access the database with the following new method: ContactDatabase getContactDatabase() Accesses the services Contact Database. 7.8 SipRequestWrapper public class SipRequestWrapper implements SipRequest Convenience class for wrapping a SIP request with a custom implementation. This support class simply forwards all method calls to the wrapped request object. Subclasses only need to override the methods they are interested in, without having to completely implement the interface. public SipRequestWrapper(SipRequest wrapped) Construction with the request object to be wrapped. 7.9 SipResponseWrapper public class SipResponseWrapper implements SipResponse Convenience class for wrapping a SIP response with a custom implementation. This support class simply forwards all method calls to the wrapped response object. Subclasses only need to override the methods they are interested in, without having to completely implement the interface. public SipResponseWrapper(SipResponse wrapped) Construction with the response object to be wrapped. 8 Security Considerations By this architecture it is possible already at time of deployment to check the service according to some rules applied for the server. Out of them, this memo adds no security considerations beyond those applicable to the referenced documents. 9 Acknowledgement We would like to thank all members of the project A1 of the ftw. for their ideas and the helpful dicussions. Peterbauer, Stadler, Miladinovic, Pudil [Page 14] Internet Draft SIP Servlet API Extensions February 2001 Furthermore we have to mention that this draft has been benefitted from the work done by the authors of the "SIP Servlet API" as well as the "Java Servlet Specification Version 2.3" for http servlets. 10 References [1] Bradner, S., "The Internet Standards Process -- Revision 3", BCP 9, RFC 2026, October 1996. [2] Kristensen A., Byttner A., "The SIP Servlet API", Internet Draft, Internet Engineering Task Force, Septermber 1999, expired (see Appendix of this document) [3] ODoherty M., "Root SIP Servlet", Internet Draft, Internet Engineering Task Force, August 2000, Work in progress. [4] Davidson J., Coward D., "Java Servlet Specification Version 2.3", Sun Microsystems, October 2000, Work in progress. [5] Schulzrinne H., Rosenberg J., Handley M., Schooler E., "SIP: Session Initiation Protocol", RFC 2543, Internet Engineering Task Force, March 1999. 11 Authors Addresses Karl Peterbauer Kapsch AG Pottendorferstr. 19 A-1121 Vienna Phone: +43 (1) 811 11 1839 Fax: +43 (1) 811 11 8675 EMail: peterbau@kapsch.net Johannes Stadler Institute for Communication Networks Vienna University of Technology Favoritenstr. 9/388 A-1040 Vienna Phone: +43 (1) 58801 38845 Fax: +43 (1) 58801 38898 EMail: johannes.stadler@tuwien.ac.at Igor Miladinovic Institute for Communication Networks Vienna University of Technology Favoritenstr. 9/388 A-1040 Vienna Phone: +43 (1) 58801 38844 Fax: +43 (1) 58801 38898 EMail: igor.miladinovic@tuwien.ac.at Thomas Pudil Institute for Communication Networks Vienna University of Technology Favoritenstr. 9/388 A-1040 Vienna Peterbauer, Stadler, Miladinovic, Pudil [Page 15] Internet Draft SIP Servlet API Extensions February 2001 Phone: +43 (1) 58801 38843 Fax: +43 (1) 58801 38898 EMail: thomas.pudil@tuwien.ac.at 12 Appendix - "The SIP Servlet API" Because our draft references the "SIP Servlet API" draft, which has been expired in March 2000, we would like to show the most important chapters 4, 5, 6 and 9 here in this appendix in full agreement with the author Anders Kristensen. This is necessary for a understanding of our concept. To avoid confusions, the chapter numbers of this other draft are written between brackets. (4) Overview of the SIP Servlet API All classes and interfaces of the SIP Servlet API are located within the org.ietf.sip package. The key interfaces are SipServlet and SipServletContext which represents servlets and their view of the servlet engine respectively. The servlet context implements the factory and contact database interfaces in addition to providing varios other facilities. The dynamic aspects of the API consists mainly of the SipRequest, SipResponse, and Transaction interfaces which provide information and control to servlets. (4.1) Interfaces ContactDatabase Access to the servlet engines contact database. This interface provides servlets with access to contact information for users. Contact Represents SIP Contact addresses, ServletConfig Represents servlet configuration information. The mechanism used for associating configuration with servlet instances is outside the scope of the SIP Servlet API itself, but the information is made available to servlets via this class. SingleThreadModel The SingleThreadModel empty interface is implemented by servlets that does not wish to handle more than one event at a time. It is the servlet engines responsibility to ensure that it only ever invokes one callback method in the servlet at a time. SipAddress Represents value of SIP From and To headers and serves as the base class for the representation of Contact header values. SipConstants This interface defines a number of constants used Peterbauer, Stadler, Miladinovic, Pudil [Page 16] Internet Draft SIP Servlet API Extensions February 2001 throughout the SIP API. It defines constants corresponding to SIP methods and status codes. For convenience this interface is extended by several other interfaces. SipFactory Factory methods for SipURLs, Contacts, SipAddresses, and Transactions. SipMessage Base interface for SipRequest and SipResponse. As SIP entities can receive and send requests as well as responses, there is a need for SIP servlets to be able to set and get headers, content, and other information in both requests and response. This interface reflects the commonality between all SIP messages. SipRequest Represents SIP requests. This class provides access to all parts of SIP requests, both for incoming and outgoing messages. SipResponse Represents SIP responses. SipServlet The interface implemented by SIP servlets in order to extend SIP servlet engines. SipServletContext The SipServletContext represents the servlet engine, that is the SIP stack, to SipServlets. It provides access to a variety of functionality: logging, server attributes, server software information, factory methods for SIP messages, URLs, etc, as well as access to the servers contact database. SipTransaction Represents SIP transactions. SipURL Represents SIP URLs, i.e. addresses of SIP endpoints SIP URLs are used in the request-URI of SIP requests as well as in To, From, and Contact header fields. (4.2) Classes SipUtils Miscellaneous static utility methods. SipServletAdapter An abstract implementation of the SipServlet interface. This provides default implementations for all methods and is a convenient base class for servlets. (4.3) Exceptions ParseException A ParseException is thrown when an error occurs while attempting to parse some entity. Peterbauer, Stadler, Miladinovic, Pudil [Page 17] Internet Draft SIP Servlet API Extensions February 2001 ServletException ServletExceptions can be thrown by servlets to indicate to the server that an error occurred during processing of a SIP message. (5) Overview of SIP Servlet API Usage The API is primarily intended for use in SIP servers, in particular proxies, but can also be supported by user agents. When a SIP request belonging to a new transaction is received, the server decides which servlet, if any, should receive it. As discussed in section 2.2 the mechanism for associating initial requests with servlets is not specified by this document. The server passes an object representing the request to the servlet, which then decides whether to proxy it, respond to it, or whether to let the server perform its default processing on the message. (5.1) Registering for Callbacks Servlets can register themselves as listeners on a transaction via the SipTransaction interface: public void addListener(SipServlet servlet) public void removeListener(SipServlet servlet) SipTransaction listeners receive all messages related to the corresponding transaction that a server receives. Servlets are automatically registered as listeners for the initial transactions but not for transactions it itself initiates. Hence, in order to receive responses to locally initiated request, a servlet will have to first register itself as a listener for that transaction. If the number of listeners on a transaction drops to zero and no more than one outstanding proxied request exists, the servlet engine MAY free up any resources it has associated with the transaction and become stateless with regard to that transaction. In this case the implementation of the SipTransaction interface should contain all information needed for the engine to go stateful at a later time, in case a servlet keeps a reference to the SipTransaction and later adds itself as a listener. The ability of servlets to unsubscribe themselves as listeners for a transaction is useful because it allows proxies to go stateless but it may also have performance benefits, at least for distributed servlet engines. Are finer grained registrations desirable, e.g. on final responses only as in SIP CGI? (5.2) Message Processing Servlets control how messages it receives are handled. It can proxy and initiate requests and consume responses or forward them upstream. This is done using the following methods: Peterbauer, Stadler, Miladinovic, Pudil [Page 18] Internet Draft SIP Servlet API Extensions February 2001 public Object SipRequest.send(SipURL nextHop) public void SipResponse.send() SipRequest.send is used both for initiating and forwarding requests. The SipURL argument identifies the next hop and basically represents the request URI as it will appear in the request line of the message. SipResponse.send is used to forward responses received in a proxy and to send locally generated responses upstream. The receiever is determined by the Via headers of the response. Servlets are free to inspect all parts of SIP messages, both headers and content, and to set the value of non-system header fields. (5.3) System Headers We use the term "system" headers to refer to those headers that are managed by the SIP stack and which servlets MUST NOT attempt to set epxlicitly via SipMessage.setHeader or similar "generic" methods. This includes the following headers: Call-ID, From, To, CSeq, Via, Record-Route, and Content-Length. These headers should not need to be manipulated directly by servlets. This makes it easier for a SIP stack to enforce correct protocol behaviour. (5.4) Creating Messages A servlet can respond to a request by first creating a corresponding response, and then send it. For example: public boolean doInvite(SipRequest req) { SipResponse res = req.createResponse(); res.setStatus(486); res.send(); return true; } The value of system headers of the response object is derived from the corresponding values in the request object, as are all other headers which a UAS is required to copy from requests to responses. In order to initiate an outgoing request in a new transaction it is necessary to first create a transaction object and then a request: from = context.createSipAddress("Bell ... req.send(to.getSipURL()); In this case the value of system headers is taken from the Peterbauer, Stadler, Miladinovic, Pudil [Page 19] Internet Draft SIP Servlet API Extensions February 2001 transaction object which was initialized with the spceified From and To headers and Call-ID and CSeq number chosen by the implementation. Servers MAY modify messages sent by servlets in other ways, e.g. by adding other headers. The last example shows how factory methods in SipServletContext are used instead of constructors in order to insulate servlet code from any specific implementation. (5.5) The default action SIP servlets respond to message callbacks with a boolean indicating whether or not the server should apply its default processing to the message (if the return value is false) or not (true). All methods in the SipServletAdapter class returns false, meaning that default message handling will take place for all callback methods that are not overridden. Using return values to control whether or not to perform default actions means a servlet cannot possibly instruct the server to perform it more than once, although it may be unfortunate that the default action can only be performed upon returning from a callback. (5.6) Request Tokens The SipRequest.send(SipURL) method returns a "request token" which can be used by servlets to match against similar tokens obtained from SipResponse.getRequestToken(), in order to match up responses with requests. Request tokens should be treated as opaque objects which are only good for comparing reference equality. Request tokens are used for the same purpose as in SIP CGI. They are needed in the SIP Servlet API because a forking proxy may invoke send() on a request object more than once, meaning that the request object itself cannot play the role of the request token. (5.7) Access to Message Content Access to the body of messages is via the following methods in the SipMessage interface: public byte[] getContent() public Object getParsedContent() throws ParseException public Object getMediaDescription() throws ParseException public void setContent(byte[] buf) getContent and setContent works in terms of the raw bytes constituting the content, whereas getParsedContent() and getMediaDescription() attempts to parse the content according to the MIME type of the message. The type of object returned will thus Peterbauer, Stadler, Miladinovic, Pudil [Page 20] Internet Draft SIP Servlet API Extensions February 2001 depend on the Content-Type of the message. A server is required at a minimum to be able to parse SDP. We should define or refer to a Java API for SDP that conformant implementations must adhere to. The difference between getParsedContent() and getMediaDescription() is that is that for messages with a MIME multipart Content-Type, getParsedContent() will return an object representing the entire multipart body while getMediaDescription() will recurse into the multipart body to find, parse and return a body part with a recognized media description. Should we integrate with the Java Activation Framework, e.g. define SipMessage to extend javax.activation.DataSource? Implementations of the present API may delegate parsing to JAF without changing the SIP Servlet API. For multipart messages getParsedContent() SHOULD return an instance of javax.mail.MultiPart, which represents MIME multipart messages in the JavaMail API. "A SIP-CGI/1.1 server MAY choose to process some methods directly rather than passing them to scripts". (5.8) The Contact Database Servlets have access to the servers contact database via the ContactDatabase interface (extended by SipServletContext). There is no assumption about how the contact database is implemented - it could be a database, local flat files, a directory server, or something else. Servlets can look up and modify contact information, subject to whatever security constraints the server might want to impose. (5.9) Optional Behaviour SIP servlet engines MAY choose to process incoming messages itself rather than handing them to a listening servlet. This can happen, for example, if the server doesnt satisfy a Requires header, if the message fails authentication or the caller doesnt have the required privileges. Likewise engines may attempt to detect protocol violations made by servlets and take appropriate actions. Conformant SIP servers would typically want to impose various security checks on servlets, see section 9. (6) API Reference We list here the interface and class signatures of the SIP Servlet API. The annotated API reference is browsable and the code downloadable. Peterbauer, Stadler, Miladinovic, Pudil [Page 21] Internet Draft SIP Servlet API Extensions February 2001 (6.1) Interfaces (6.1.1) ContactDatabase public interface ContactDatabase Access to the servlet engines contact database. This interface allows servlets to obtain information about which "physical" contact addresses are currently registered for different "logical" addresses, and also to change it, for example, in response to incoming REGISTER requests. The server may lookup contact addresses based on the SipURL or display-name or other attributes of the argument. These operations are highly security sensitive and should be protected appropriately. public java.util.List getContacts(SipAddress sipAddr) public void setContacts(SipAddress sipAddr, java.util.List contacts) public void addContact(SipAddress sipAddr, Contact contact) public void removeContact(SipAddress sipAddr, Contact contact) (6.1.2) Contact public interface Contact extends SipAddress Represents SIP Contact addresses. A Contact extends a SipAddress with three well-defined parameters: the q-value, and action, and an expires indication. This interfaces provides getters and setters for each of these. getWildcard() returns a static Contact instance representing the special "wildcard" Contact representing the "*" wildcard which can be used as the value of the Contact header in REGISTER requests. public Contact getWildcard() public float getQ() public void setQ(float q) public String getAction() public void setAction(String action) public String getExpires() public void setExpires(String expires) public interface ServletConfig public String getInitParameter(String name) public SipServletContext getServletContext() (6.1.3) SingleThreadModel public interface SingleThreadModel Peterbauer, Stadler, Miladinovic, Pudil [Page 22] Internet Draft SIP Servlet API Extensions February 2001 The SingleThreadModel empty interface is implemented by servlets that does not wish to handle more than one event at a time. It is the servlet engines responsibility to ensure that it only ever invokes one callback method in the servlet at a time. (6.1.4) SipAddress public interface SipAddress Represents value of SIP From and To headers and serves as the base class for the representation of Contact header values. A SipAddress can be thought of as representing something that conforms to the following grammar: SipAddress = (name-addr | addr-spec) *(";" addr-params) name-addr = [display-name] "<" addr-spec ">" addr-spec = SIP-URL | URI display-name = *token | quoted-string Note that a SipAddress can encapsulate either a SIP URL or an arbitrary non-SIP URI. These are represented in this class by SipURL and String attributes respectively, exactly one of which must (normally) be non-null. public String getDisplayName() public SipURL getSipURL() public String getURI() public String getParameter(String name) public java.util.Iterator getParameterNames() (6.1.5) SipConstants public interface SipConstants This interface defines a number of constants used throughout the SIP API. It defines constants corresponding to SIP methods and status codes. For convenience this interface is extended by several other interfaces. public static final String INVITE = "INVITE"; public static final String ACK = "ACK"; public static final String OPTIONS = "OPTIONS"; public static final String BYE = "BYE"; public static final String CANCEL = "CANCEL"; public static final String REGISTER = "REGISTER"; public static final int SC_TRYING = 100; public static final int SC_RINGING = 180; public static final int SC_CALL_FORWARDING = 181; public static final int SC_QUEUED = 182; public static final int SC_OK = 200; public static final int SC_MULTIPLE_CHOICES = 300; public static final int SC_MOVED_PERMANENTLY = 301; Peterbauer, Stadler, Miladinovic, Pudil [Page 23] Internet Draft SIP Servlet API Extensions February 2001 public static final int SC_MOVED_TEMPORARILY = 302; public static final int SC_SEE_OTHER = 303; public static final int SC_USE_PROXY = 305; public static final int SC_ALTERNATIVE_SERVICE = 380; public static final int SC_BAD_REQUEST = 400; public static final int SC_UNAUTHORIZED = 401; public static final int SC_PAYMENT_REQUIRED = 402; public static final int SC_FORBIDDEN = 403; public static final int SC_NOT_FOUND = 404; public static final int SC_METHOD_NOT_ALLOWED = 405; public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407; public static final int SC_REQUEST_TIMEOUT = 408; public static final int SC_CONFLICT = 409; public static final int SC_GONE = 410; public static final int SC_LENGTH_REQUIRED = 411; public static final int SC_PRECONDITION_FAILED = 412; public static final int SC_REQUEST_BODY_TOO_LARGE = 413; public static final int SC_REQUEST_URI_TOO_LARGE = 414; public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415; public static final int SC_BAD_EXTENSION = 420; public static final int SC_TEMPORARILY_NOT_AVAILABLE = 480; public static final int SC_INVALID_CALL_ID = 481; public static final int SC_LOOP_DETECTED = 482; public static final int SC_TOO_MANY_HOPS = 483; public static final int SC_INTERNAL_SERVER_ERROR = 500; public static final int SC_NOT_IMPLEMENTED = 501; public static final int SC_BAD_GATEWAY = 502; public static final int SC_SERVICE_UNAVAILABLE = 503; public static final int SC_GATEWAY_TIMEOUT = 504; public static final int SC_VERSION_NOT_SUPPORTED = 505; public static final int SC_BUSY = 600; public static final int SC_DECLINE = 603; public static final int SC_DOES_NOT_EXIST = 604; public static final int SC_NOT_ACCEPTABLE = 606; (6.1.6) SipFactory public interface SipFactory Factory methods for SipURLs, Contacts, SipAddresses, and Transactions. The createSipTransaction() method returns a new SIP transaction object with the specified parameters. This can be used to crate a new SipRequest object which is used to initiate new transactions. The servlet engine generates a new Call-ID and CSeq number for the transaction. Note that in order to receive responses to requests made within the returned transaction the caller must register itself as a listener with the transaction. public SipTransaction createSipTransaction(SipAddress from, SipAddress to) public SipURL createSipURL(String sipURL) throws ParseException public SipURL createSipURL(String user, String host) Peterbauer, Stadler, Miladinovic, Pudil [Page 24] Internet Draft SIP Servlet API Extensions February 2001 public SipURL createSipURL(String user, String host, int port) public SipAddress createSipAddress(String sipAddress) throws ParseException public SipAddress createSipAddress(SipURL sipURL) public SipAddress createSipAddress(SipURL sipURL, String displayName) public Contact createContact(String contact) throws ParseException public Contact createContact(SipURL url, String displayName) public Contact createContact(String uri, String displayName) public Contact createContact(SipAddress addr) (6.1.7) SipMessage public interface SipMessage extends SipConstants Base interface for SipRequest and SipResponse. As SIP entities can receive and send requests as well as responses, there is a need for SIP servlets to be able to set and get headers, content, and other information in both requests and response. This interface reflects the commonality between all SIP messages. public String getMethod() public String getProtocol() public String getRemoteAddr() public String getRemoteHost() public String getServerName() public int getServerPort() public String getServerProtocol() public SipTransaction getTransaction() public String getHeader(String name) public java.util.Iterator getHeaderNames() public java.util.Iterator getHeaders(String name) public void setHeader(String name, String value) public void addHeader(String name, String value) public SipAddress getFrom() public SipAddress getTo() public java.util.List getContacts() public void setContacts(java.util.List contacts) public int getContentLength() public String getContentType() public void setContentType(String type) public byte[] getContent() public Object getParsedContent() throws ParseException public Object getMediaDescription() throws ParseException public void setContent(byte[] buf) (6.1.8) SipRequest public interface SipRequest extends SipMessage public SipURL getRequestURI() public String getAuthType() public String getRemoteUser() Peterbauer, Stadler, Miladinovic, Pudil [Page 25] Internet Draft SIP Servlet API Extensions February 2001 public boolean recordRoute(boolean recordIt) public SipResponse createResponse() public Object send(SipURL url) (6.1.9) SipResponse public interface SipResponse extends SipMessage Represents SIP responses. public int getStatus() public String getReasonPhrase() public Object getRequestToken() public void setStatus(int code, String reason) public void setStatus(int code) public void send() (6.1.10) SipServlet public interface SipServlet extends SipConstants The interface which must be implemented by SIP servlets in order to extend SIP servlet engines. This is implemented by the abstract class SipServletAdapter. public void init(ServletConfig config) public boolean gotRequest(SipRequest req) throws ServletException public boolean gotResponse(SipResponse res) throws ServletException public void destroy() public ServletConfig getServletConfig() public String getServletInfo() public void log(String msg) public void log(String msg, Throwable t) (6.1.11) SipServletContext public interface SipServletContext extends SipFactory, ContactDatabase The SipServletContext represents the servlet engine, that is, the SIP stack, to SipServlets. It provides access to a variety of functionality: logging, server attributes, server software information, factory methods for SIP messages, URLs, etc, as well as access to the servers contact database. public int getMajorVersion() public int getMinorVersion() public String getServerInfo() public Object getAttribute(String name) public java.util.Iterator getAttributeNames() public void setAttribute(String name, Object value) public void removeAttribute(String name) public void log(String msg) public void log(String msg, Throwable t) Peterbauer, Stadler, Miladinovic, Pudil [Page 26] Internet Draft SIP Servlet API Extensions February 2001 (6.1.12) SipTransaction public interface SipTransaction Represents SIP transactions. A transaction is identified by its CSeq number within a call leg. As calls and call legs are not represented explicitly in the API, transactions encapsulate Call-ID, From and To headers as well as the CSeq number. These transaction parameters doesnt change during the lifetime of a transaction, and hence are read-only attributes oif this class. SipTransactions created locally, e.g. by a servlet, are initialized with values for the From and To headers and the request method, whereas the value of the Call-ID, CSeq number and possibly tags associated with the From or To headers cannot be set by applications. Messages belonging to the same transaction will share the same SipTransaction instance. This is useful because transaction objects can hold uninterpreted client state, via its attribute methods. This requirement implies that distributed SIP servlet engines must route messages belonging to the same transaction to the same actual JVM. public String getCallID() public SipAddress getFrom() public SipAddress getTo() public String getCSeq() public SipRequest createRequest(String method) public Object getAttribute(String name) public java.util.Iterator getAttributeNames() public void setAttribute(String name, Object value) public void removeAttribute(String name) public void addListener(SipServlet servlet) public void removeListener(SipServlet servlet) (6.1.13) SipURL public interface SipURL Class SipURL represents addresses of SIP endpoints. SIP URLs are used in the request-URI of SIP requests as well as in To, From, and Contact header fields. public String getUser() public void setUser(String user) public String getPassword() public void setPassword(String password) public String getHost() public void setHost(String host) public int getPort() public void setPort(int port) Peterbauer, Stadler, Miladinovic, Pudil [Page 27] Internet Draft SIP Servlet API Extensions February 2001 public String getParameter(String name) public void setParameter(String name) public void setParameter(String name, String value) public void removeParameter(String name) public java.util.Iterator getParameterNames() public String toString() (6.2) Classes (6.2.1) SipUtils public abstract class SipUtils Miscellaneous static utility methods. public static long getJavaTime(String time) Given a time specification in the form of be delta-seconds (an integer) or an RFC 1123 date specification returns Java time (absolute time in milliseconds since Jan 1 1970 - same unit as returned by System.currentTimeMillis()) corresponding to the specified SIP time. public static long getSipDeltaTime(String time) Returns the SIP delta time corresponding to a string which matches t = (SIP-date | delta-seconds) See RFC 2543, sections 6.20 and 6.13. (6.2.2) SipServletAdapter public abstract class SipServletAdapter implements SipServlet, ServletConfig A simple abstract adapter class for SIP servlets. In addition to providing default implementations for all methods, also dispatches incoming request to other methods based on the SIP request method. The default implementation of callbacks (gotRequest, gotResponse, do*) all return false to indicate to the servlet engine that it should perform the default action for the message. public void init(ServletConfig config) public boolean gotRequest(SipRequest req) throws ServletException public boolean doInvite(SipRequest req) throws ServletException public boolean doAck(SipRequest req) throws ServletException public boolean doOptions(SipRequest req) throws ServletException public boolean doBye(SipRequest req) throws ServletException public boolean doCancel(SipRequest req) throws ServletException public boolean doRegister(SipRequest req) throws ServletException public boolean gotResponse(SipResponse res) throws ServletException public void destroy() Peterbauer, Stadler, Miladinovic, Pudil [Page 28] Internet Draft SIP Servlet API Extensions February 2001 public ServletConfig getServletConfig() public String getInitParameter(String name) public java.util.Iterator getInitParameterNames() public SipServletContext getServletContext() public String getServletInfo() (6.3) Exceptions (6.3.1) ParseException public class ParseException extends java.lang.Exception A ParseException is thrown when an error occurs while attempting to parse some entity. public ParseException() public ParseException(java.lang.String msg) (6.3.2) ServletException public class ServletException extends java.lang.Exception ServletExceptions can be thrown by servlets to indicate to the server that an error occurred during processing of a SIP message. public ServletException () public ServletException (java.lang.String msg) (9) Security Considerations The biggest security concern raised by the introduction of SIP servlets is the havoc wreaking potential of this sometimes untrusted code. (9.1) Sensitive Operations Other than access to resources such as as file systems, network, windowing system, etc., the SIP Servlet API introduces a couple of sensitive operations of its own: o Access to a registrars contact database (the ContactDatabase interface) is highly sensitive. The whereabouts of people should usually be considered private data belonging to those individuals and should be protected against unauthorized access. Apart from just being private information, the ability to modify registration data can be used to gain control over calls and thus o The ability to initiate arbitrary SIP requests. o The ability to generate responses to requests. A server may execute untrusted code in a "servlet sandbox" - an environment that restricts the set of operations that can be performed. In addition to the original sandbox model used in browsers Peterbauer, Stadler, Miladinovic, Pudil [Page 29] Internet Draft SIP Servlet API Extensions February 2001 to execute untrusted applet code the JDK1.2 security model allows fine-grained access-rights to be associated with code from different sources. Using this, servlets can, for example, be allowed to look up and/or modify contact information for a specific subset of people. Servlet engines are free to control access to any of the methods defined in this document. A failed permission check causes a runtime exception (e.g. java.security.AccessControlException) to be thrown. As runtime exceptions does not have to be declared in throws clauses of method signatures any method can potentially be disallowed for specific servlets. The most obvious candidates for access control are: o all methods in the ContactDatabase interface (extended by SipServletContext) o SipServletContext.createSipTransaction - as this is needed to initiate requests. o SipRequest.createResponse - if a servlet is allowed to forward responses but not to create responses of its own Additionally, a server MAY limit and monitor the number of requests and responses initiated by a servlet. (9.2) Buggy or Malicious Servlet Code Buggy or malicious servlet code shouldnt be able to core dump a servlet engine. The lack of pointers and the presence of exception handling allows servers to protect themselves against this type of badly written extension code. (9.3) Protocol Violations As the very point of SIP servlets is that responsibility for message processing can be delegated to code that can be developed and distributed independently of servlet engines, these extensions almost necessarily have the potential to violate the SIP protocol in various ways. A SIP servlet engine MAY attempt to detect various types of protocol violations and destroy or otherwise curb misbehaving in addition to informing the administrator. Such violations include: o Illegal message formats, e.g. badly formatted header fields, attempts to set the Class-ID or From fields of proxied requests, say. o Illegal state changes, for example generating a BYE request for an already disconnected call leg, a response to an ACK, or multiple final non-2xx responses. Having servlet engines manage most of the headers directly involved in message routing - Call-IDs, CSeq numbers, From and To headers and Via header processing - makes it easier to detect protocol violations as servlets should never set these headers explicitly. (9.4) Denial of Service Attacks Peterbauer, Stadler, Miladinovic, Pudil [Page 30] Internet Draft SIP Servlet API Extensions February 2001 The access control security checks that can be performed with JDK1.2 and the older sandbox model cannot protect a server against denial- of-service attacks based on excessive use of memory or CPU cycles. It may well be feasible to analyze Java bytecode in order to enforce restrictions on SIP servlets such as they contain no loops and allocate only a bounded amount of memory. Such a check could be performed at the time the code is uploaded or otherwise installed on a server. A less ambitious approach is for a server administrator to manually inspect the servlet code or to rely on code signing techniques to achieve an appropriate level of trust in servlet code. This chapters 4, 5, 6 and 9 should help to give the reader an understanding of how our design is based on this draft. 13 Full Copyright Statement "Copyright (C) The Internet Society (1997). All Rights Reserved. This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implmentation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English. The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns. This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE." This draft expires in August 2001. Peterbauer, Stadler, Miladinovic, Pudil [Page 31]