Introduction  This document covers unusual findings concerning
installing Webserver  application Server 2.0/2.1.1/3.0.

Problem
2.0     2.1.1     3.0

You cant set a physical location for a
virtual directory in the listener, to the same
physical location as an entry in the web
request broker.   The listener virtual
directory will
override.                                                   X
X         X

You cant display images, documents,
etc from a liveHTML directory (SSI).
 Only html documents can be displayed from there.         X
X         X

You cant have your initial document contain
live HTML(ie  server:port/ ).
You must redirect your initial document to  an
ssi directory specified in the web request broker.             X
X         X

Any directories supported by the web request
broker, do not support an "initial file", and do not
support "directory
indexing".                                             X
X         X

UNIX   Listeners on port 80 can only
             be started by
root.
X
UNIX - Only root can start a listener as
nobody/nobody                           X
NT   - You must shut the listener down when
           changing the
configuration                                       X        X
X

            You can not execute cgi.  Ie (execute ssi tag)         X

Other Gotchas

1. always set your browser to 0 memory cache and 0 disk cache for web
administrator configuration.
2. Web server 3.0 should be in its own oracle home on UNIX.
3. On NT, never enter   server:port/ssi if ssi is identified as an SSI
directory.  This will cause a Dr. Watson error, and hang the listener
uppon restarting.





Problem Repository

1. Prob# 1033814.6  OWS-05732 OWS-05723 OWS-08802 STARTING NEW WEB
LISTENER
2. Soln# 2081026.6  CHANGE CONFIG AND LOG DIRECTORIES TO OWNER/GROUP
NOBODY


1. Prob# 1033814.6  OWS-05732 OWS-05723 OWS-08802 STARTING NEW WEB
LISTENER

Problem ID          : 1033814.6
Affected Platforms  : Sun Solaris V2 Sparc
Affected Products   : Oracle Web Application Server
Affected Components : OIS V03.00.XX
Affected Oracle Vsn : V07.03.03.XX

Summary:
OWS-05732 OWS-05723 OWS-08802 STARTING NEW WEB LISTENER

+=+

Problem Description:
====================

You are starting up a Web Listener V3.0 with a userid and groupid other
than
oracle and dba.  The following errors may be returned:

        OWS-05723,00000:  Cannot change ownership of Listener
Directories

        OWS-05730,00000:  Given Group ID  is invalid.

        OWS-05732

The most common userid and groupid used is nobody.


Search words:
Web Application Server webserver ows startup
ows-5732 ows-5723 ows-5730

+==+

Diagnostics and References:



2. Soln# 2081026.6  CHANGE CONFIG AND LOG DIRECTORIES TO OWNER/GROUP
NOBODY

Solution ID         : 2081026.6
For Problem         : 1033814.6
Affected Platforms  : Sun Solaris V2 Sparc
Affected Products   : Oracle Web Application Server
Affected Components : OIS V03.00.XX
Affected Oracle Vsn : V07.03.03.XX

Summary:
CHANGE CONFIG AND LOG DIRECTORIES TO OWNER/GROUP NOBODY/NOBODY

+=+

Solution Description:
=====================

Follow the steps below:

1. Create the listener using Oracle/DBA.
2. Go to:
$Oracle_Home/ows/admin/ows//httpd_/.
Find the directory that contains file:  sv.cfg file.
3. Change the Config and Log directories to owner/group nobody/nobody.
4. Open the Config directory.
5. Change the owner/group of the sv.cfg file to
nobody/nobody.
6. Open the sv.cfg file.
7. Check the field that says UserID/GroupID, and change it to
nobody/nobody.
8. Login as root with the proper Oracle environment set 

When you want to start/stop the listener, start by using this command
line.
The listener cannot be started in the admin page.

If you do not log in as the root userid and password to start the Web
Listener, you must ensure that the following environment variable are
set:

        ORAWEB_HOME
        ORAWEB_SITE
        ORAWEB_ADMIN
        ORACLE_HOME
        ORACLE_BASE
        ORACLE_SID (optional)




+==+

References:




***********************************
Configuring WebServer For Stability
***********************************

In this bulletin, "WebServer" refers both to Web Server V2.x and
to Web Application Server 3.0 unless noted otherwise.

-------------------
Errors you may see:
-------------------

* System or WebServer extremely slow
* System utilization extremely high, maybe processing, maybe I/O.
* UNIX System swap space or NT available memory severely reduced.
* System crash and re-boot because of fatal memory shortage.
* WebServer processes vanish.  May dump core, or may not.
* WebServer fails every few hours, or even every few minutes.

------------------------------
How to avoid such instability:
------------------------------

Sites plagued by such instability have often found relief by
configuring with the guideines below in mind.  The guidelines
coordinate the specification of:

(1) Cartridge Min and Max in the WRB ".app" file
(2) MTS (Multi Threaded Server, for UNIX platforms only)
(3) RDBMS processes and sessions parameters.

Also covered:

(4) Configuring a SQL*Net V2 listener to use MTS
(5) Monitoring MTS servers
(6) Configuring a second SQL*Net V2 listener to use MTS
(7) Configuring multiple "WebServer homes" for fewer agent connections.
(8) Virtual hosting in a single WebServer.


=========
Overview:
=========

The Min value for Cartridges, specified in the WebServer ".app" files,
controls how many of those cartridges should be kept loaded and ready
to run even if not currently in use.

If Cartridge Min is set too low, demands on the system to launch
cartridges in response to requests from Web Clients may bog the system
down or overwhelm it.  Processes may disappear.  The system may slow to
a crawl.  The system may even spontaneously reboot!

The default Cartridge Min "0" is too low for sites with a high volume of
accesses.

Similarly, setting Cartridge Max too far above Min can lead to excessive
demands on the system as a whole, as well as on the individual WebServer
components running on a system.  The default max "100" for Web Server V2

and default "30" for Web Application Server V3 are often too far above
the Cartridge Min.

When a V2 OWA cartridge or V3 PLSQL cartridge starts, its agent connects

to Oracle databases.  Depending on Cartridge Min and Max, on on Site
activity, the number of database connections may be surprisingly large.

For UNIX platforms, the MTS feature (Multi Threaded Server) dramatically
reduces the impact on the system of making a large number of database
connections

MTS uses SQL*Net V2 listeners to connect clients such as WebServer
agents to MTS dispatchers.  So, at least one SQL*Net V2 listener is
needed.

One SQL*Net V2 listener can only handle a finite number of connection
requests per second.  When the rate of connection requests too
frequently exceeds that number, more SQL*Net V2 listeners can be
configured and can use MTS (|The RDBMS must be 7.3.3 or above.)

As each WebServer agent starts up, it makes connections to all databases
for which Web Server V2 DCDs and Web Application Server 3.0 virtual
paths have been defined.   This is for efficiency, to allow logins to
proceed as quickly as possible when needed.

Note that, for WebServer agents, connecting to a database is not tied to
logging into that database.  In contrast, sqlplus combines the two.
When you "connect" in sqlplus, you connect and log in.  When you exit
from your session or log out, your connection is dropped, too.  But
WebServer agents can connect once, then log in and out many times while
maintaining the connection across those separate sessions.  Staying
connected can boost performance of Web Sites.

On the other hand, many customers have several "pools" of agents and of
databases, intending that agents in one pool will only connect to the
databases associated with that pool, but never to any databases
associated with other pools.  To do this, Separate V2 Web Server homes
or separate V3 Web Sites can be configured.  Otherwise, all agents will
establish connections to all databases, even though they will never log
in to some of them.

These unexpected connections must be accounted for in the specification
of Cartridge Min and Max, and of MTS dispatchers.

Conversely, a single WebServer can be configured to accept Web Client
requests for more than one "host" or "domain".  That is, one WebServer
can serve as a Web Site not only for "www.a.com" but also for
"www.b.com".
This is called "virtual hosting".

Not only can a single WebServer serve as the Web Site for more than one
domain, it can also return a different home page for each domain.

===============
End of Overview
===============



++++++++++++++++++++++++++++
If these tips don't help ...
++++++++++++++++++++++++++++

The configuration tips that follow may not resolve an instability
problem completely!

In addition to product bugs, sometimes system overload and instability
are caused by applications that take a lot of time or a lot of some
other resource.  If cartridges take more time, memory or other resource
than expected, be sure to check the WebServer's log directories for
signs of application error.

Even if cartridges seem "well behaved", if your system is unstable,
check ".log" and ".err" files in the log directories for error messages.

For Web Server V2, check in the $ORACLE_HOME/ows2/log directory or the
$ORACLE_HOME/ows21/log directory, depending on your WebServer version.

For Web Application Server 3.0 on a UNIX server, Issue the command

find $ORACLE_BASE -name '*.log' -print

to find them all.  Windows NT Explorer will let you do a similar search
of the file system on the NT platform.

If you expect your application routinely to take a long time to respond
to Client Browser requests, you may want to warn users about the delay
they'll experience.  And you may need to adjust Cartridge Min, Max and
other configuration parameters to allow for each cartridge's reduced
capacity to handle user requests.



+++++++++++++++++++++++++
Components of a WebServer
+++++++++++++++++++++++++

There are four components to keep in mind when working with the Oracle
WebServer.  One is the Client Browser.  The other three components are
combined under the umbrella term "Oracle WebServer":

--CLIENT---        -----------ORACLE WEBSERVER-------------

+---------+        +----------+  +---------+  +-----------+
|         |  HTTP  |          |  |  Web    |  |           |
| Browser | <----> | Listener |--| Request |--| Cartridge |
|         |        |          |  |  Broker |  |           |
+---------+        +----------+  +---------+  +-----------+

The Client Browser is totally independent of the WebServer.  Any Client
Browser that's HTTP-compliant can work with the WebServer.

Within the WebServer, the Listener component (named oraweb, oraweb2 or
oraweb21 depending on the version) interfaces with the Client Browser.
The Listener can deliver files (HTML, images, etc) directly back to the
Client Browser without involving the Web Request Broker.  The Listener
can also perform CGI for the Client Browser, without involving the Web
Request Broker.

If Client's URL doesn't look like a request for a file or for CGI, the
Listener hands the URL to the Web Request Broker component.

Oracle WebServer products include a Listener component.  Oracle's
Listener can be replaced with Netscape or Microsoft IIS "server"
products.  The Web Request Broker can work with them, too.  See
Installation Instructions and on-line doc for details.

The Web Request Broker component determines which cartridge needs to
run in response to a URL from the Client Browser that the Listener
component did not handle by returning a file or running a CGI app.

The cartridges are programs that run to provide the resource requested
by the Client URL.  A URL can call for a page that's generated
dynamically
by a procedure stored in an Oracle database, for example.  As part of a
V2 OWA cartridge or V3 PLSQL cartridge, an agent logs into the
appropriate database, runs the specified procedure, and returns the
dynamically generated results to the Listener where they are passed back
to the Client.

When a change is made to the configuration of a WebServer Listener, then
that change is made in the listener's ".cfg" file.  When a change is
made to the configuration of the Web Request Broker, that change is made
in a ".app" file.

For Web Server V2, if either a ".cfg" file or ".app" file is changed,
both the Listener and the Web Request Broker that are controlled by
those files must be stopped and started in order to see and respond to
the change.  The commands "wclctl2" for V2.0 amd "wlctl21" for V2.1 do
that.  For example, if a change is made either to the listener
parameters or to the WRB specifications of a listener named websvr, the
V2.1 commands

wlctl21 stop listener_name
wlctl21 start listener_name

will stop and start both the listener and its associated WRB.


For Web Application Server V3, if any ".cfg" file is changed, only
the associated listener needs to be stopped and started.  For example,
if V3 listener websvr is modified, then

owsctl stop websvr
owsctl start websvr

will stop the old listener, then start a new one that will see and
respond to the modified ".cfg" file.  Or the single command:

owsctl reload websvr

will have the same effect.

For Web Application Server V3, there is a single Web Request Broker
component for all listeners in one Web Site.  This Web Request Broker
component is not affected by changes to any of the Listeners.

But all of those listeners require that the Web Request Broker component
be running.  When any modification of the single V3 wrb.app is made,
then the Web Request Broker component must be stopped and started in
order for the change to take effect.  There is no "reload" option for
the Web Request Broker.

And because all of the Listener components require that the V3 Web
Request Broker be running, it's important before you stop the Web
Request Broker that you first stop all Listeners configured under the
same Web Site.

Stopping the Web Request Broker component ordinarily will stop all of
the cartridges it launched.  However, the cartridges may continue to
run, since they are by design indepedent of the Web Request Broker and
Listener.


+++++++++++++++++++++++++++++++++++
To Configure to Resolve Instability
+++++++++++++++++++++++++++++++++++


=====================
Cartridge Min and Max
=====================

Cartridge min and max are specified in the ".app" file.  For WebServer
2.x, there is one ".app" file per listener.  For V2.0, it is in:

$ORACLE_HOME/ows2/admin

For V2.1, it is in

$ORACLE_HOME/ows21/admin

directory.  Web App Server 3.0 has only one wrb.app file per Web Site.

You can edit the files directly, but to avoid introducing errors that
will keep the listener and WRB processes from starting, it's best to use
the administrative pages on the Web to input Min and Max numbers.

For V2, from the administrative home page, go to the "WebServer Manager"
page.  Follow the link to the "Web Request Broker  Administration" page.

Modify the WRB of the listener you want.  In the "Applications and
Objects" section, scroll to the right to find the Min and Max columns
for the cartridges you use.  If you use the V2 OWA application, or V3
PLSQL
cartridge, plus one or more written in-house, for example, set Min and
Max for each of those cartridges.

For V3, from the Administrative home page, follow the link to the Web
Application Server Manager", then to the "Oracle Web Application Server"

then to "Cartridge Administration".  There, the link to "Cartridge
Summary (Web Request Broker)" takes you to a page where you can scroll
down to the "Application and Objects" section or use the link to
"Objects" to take you there.  Set the Min and Max for the application(s)
you use.

What numbers to set?  If experience proves you routinely have "n"
cartridges running, pad that number a bit, and use that for the minimum.
For example, if you usually have 5 cartridges running, set the Min to 7.
And set the Max only a little above it:  10.

If you routinely have 15 agents running, set Min 20, Max 25.  If 50
agents usually are running, set Min 60, Max 70.  If routinely 100 run,
set Min 115, max 125.

The minimum is the number of cartridges that launch when you start the
WebServer.  If they're the V2 OWA or V3 PLSQL cartridges, they connect
to databases, but not log in at that time.  When a Client URL requires
it, they log in, run the specified procedure, then log out.  But they
maintain their connection to the MTS dispatcher (or to the dedicated
server, if that is how you choose to connect).

With Min set to 0, as soon as the agent logs out of the database, it
also breaks its connection to the database, and exits from the system.
When the next browser request is received, the agent must be started, a
connection established to a server process (and if that's a dedicated
server, it will also be started up at the same time), then proceed with
logging in to the database and so on.  Specifying a non-zero minimum, to
maintain connections between log-ins, boosts performance and can avoid
WebServer instability.

As for the Max, set it only a little over the Min, to give some cushion.
But there's no point in setting Max 50 or 100 over Min.  If you need 50
or 100 more than your minimum at some times, often enough to introduce
an instability problem, then increase your minimum by that 50 or 100.
And set the Max just a little above that.

If your system can't  handle a minimum that high, then it can't handle a
maximum that high either, to state the obvious.

Why is MaxConnectCount 338?  That's the limit on most UNIX platforms
simply because of a system limit on "file handles".  When a UNIX program
opens a file, the program specifies the file by name.  The system sends
a "file handle" back to the program, and  and the program uses that file
handle for all subsequent reading, writing and closing of the file.
There is a limit of 1024 file handles per program.  So there's a limit
of 1024 file handles for the Web Server program, too.  Each Web
connection uses three file handles.  The MaxRequestCount of 338 comes
from allowing 10 file handles
for other purposes, and dividing the 1014 that remain by 3: 1014 / 3 =
338.

On other platforms, like NT, this limit is more arbitrary.  Still, there
will be some number of connections that is the most any particular
system can maintain, due to some resource or other.  So, defaulting the
maximum allowable connections to 338 in general is a useful guideline,
even if it's not exactly correct on some platforms..

How will you know if the configured Max is reached?  You will see
messages:

NDWLL_NOPROCS

in the WebServer ".err" file.  Client browser will likely see "Document
contains no data" in place of the page or the frame in a page that got
no HTML, because a new cartridge was not allowed to run to provide it.
Or the browser may see a "gray screen".


========================================
The need for MTS (Multi Threaded Server)
========================================

MTS is FOR UNIX SYSTEMS ONLY.

You'll want to use MTS as opposed to dedicated server processes, because
the WebServer may involve a surprisingly large number of processes.
Each such process uses up a significant amount of swap space.  Depending
on Cartridge Min and Max, and the number of V2 DCDs or V3 virtual paths
defined, there may be dozens or even hundreds of connections, and as
many dedicated server processes if you don't use MTS.  The effect on
swap space is significant. And could be the cause of system crashes,
"spontaneous" system reboot, or the mysterious vanishing of processes.

When you launch an agent, it establishes a connection to each database -
not a login, but a connection -  defined in the V2 owa.cfg and each V3
virtual path that's derived from the "Applications and Directories"
section of the single V3 wrb.app file.

For ISPs, this may be a surprise.  An ISP will likely define one or more

V2 DCDs or V3 virtual paths for Customer A, with the intent that some
agents use them to connect and log in to Customer A's databases.  The
same ISP may define one or more additional DCDs or virtual paths for
Customer B,
intending to have other agents use them to connect and log in to
Customer B's databases.   In fact, when each agent starts up,  it makes
a connection (without logging in) using all the DCDs defined in the V2
owa.cfg file or all the virtual paths defined in the V3.0 wrb.app file
for PLSQL applications.  The reason this is done is to expedite logging
in to any database when requested.   There is no way for an agent to
know which V2 DCDs or V3.0 virtual paths it may need to use, so it
establishes a connection using each.

Suppose that the intent is to have 10 agents connected to database A and

10 agents connected to database B.  The intent is to have 20 connections

total.  However, each of the 20 agents makes a connection not only to
the intended database but the other one was well - two connections per
agent.  That's a total of 40 connections, twice the number expected.

If the intent was to have 20 agents for each of five V2 DCDs, so a Min
of 100 agents were configured and 100 connections were expected, the
result would be 500 connections to database servers -a fivefold
increase.

The effect of this unexpected increase in connections on swap and
other system resources may be catastrophic.

If you are familiar with the sqlplus program, you may not realize (as I
did not) that it combines the connecting step and the logging in step
into what seems one step.   Furthermore, logging out from a database
also disconnects you from it.  But the two functions can be separated,
and in the WebServer, they are.  The agents establish connection to a
server process, then may log in and out repeatedly through that same
server process.  And may never log in through some connections.  The
reason for making all these connections is to speed up logging in if
needed.

In contrast, if you have set (or allowed to default) a min to zero, then
as soon as the agent cartridge is started, it makes connections to all
databases, logs in to one, runs the requested stored procedure, and
logs out from that one database.   Then all connections are dropped and
the agent process stops.  This is exceedingly inefficient.  It puts
demand
on several time-and-resource-consuming functions of the operating system

to do all that work each time a client request comes in by way of a URL.

That's why specifying a suitable Min value can make such a difference.
Each agent will be started and make connections to server processes
only once, then handle many, many requests.  Each request is handled
much faster.

There is another parameter - MaxRequests - that can also be defined in
the the .app file.   If experience shows there's some flaw in the agent
that causes it to "get into trouble" over time, you'll want to set this
parameter to a number (of logins) that will be reached before the
trouble gets out of hand.  When the number is reached, the agent process
ends its connections, and exits.  Then a new agent is started, with a
clean slate.

The default V2 MaxRequests is 50 and for V3 is 50000 according to some
sources, but none of them official.

MaxRequests must be entered into the V2 .app file, by following links
from Web Server Home Page thru the Web Request Broker icon, choosing to
modify the appropriate .app file, and in the "Cartridges" section
choosing to modify OWA.  You need to enter "MaxRequests" and the value
you want for it in the respective empty boxes that are displayed.  For
example:

Protect_OWA_Pkg   = TRUE
MaxRequests       = 5000

For V3, the link to the appropriate page is missing.  You can enter the
URL
http://host:port/ows-abin/ctadmin?FORM_CODE=CARTRIDGE_MAIN_FORM&Cartridge=PLSQL

and follow the link to PLSQL Cartridge spcific parameters.  Again you'll
need to enter "MaxRequests" and the value you want for it in the empty
boxes:

MaxRequests       = 10000

If  the agent shows no sign of trouble after many, many connections,
there's nothing to be gained by stopping it and starting a new one.  In
that case, set MaxRequests high, like to 5000 or even 10000 as in the
examples above.


=======================================
Configure MTS and a SQL*Net V2 listener
=======================================

To configure MTS, add lines like the following to your "initSID.ora"
file
in the $ORACLE_HOME/dbs directory, where "SID" is replaced with the name

of the ORACLE_SID.  For SID V733, for instance, the file is
initV733.ora:

mts_dispatchers="ipc,2"
mts_dispatchers="tcp,2"
mts_max_dispatchers=10
mts_servers=2
mts_max_servers=10
mts_service=A733
mts_listener_address="(ADDRESS=(PROTOCOL=ipc)(KEY=A733))"
mts_listener_address="(ADDRESS=(PROTOCOL=tcp)(host=netsol3)(port=3888))"

You'll need to configure a SQL*Net V2 listener, by creating a file
called listener.ora that by default is found in the
$ORACLE_HOME/network/admin directory.

Be forewarned in what you're about to see that the word "listener" is
more than just an arbitrarily chosen work.  It is indeed the name that's
being given to one particular listener.  The word "listener" is the
default name
for a SQL*Net V2 listener.    Here's a sample listener.ora:

LISTENER=
(ADDRESS_LIST=
(ADDRESS=
(PROTOCOL=IPC)
(KEY=A733)
)
(ADDRESS=(PROTOCOL=TCP)(HOST=netsol3)(PORT=3888))
)

STARTUP_WAIT_TIME_LISTENER = 0
CONNECT_TIMEOUT_LISTENER = 10

SID_LIST_LISTENER=
(SID_LIST=
(SID_DESC=
(SID_NAME=A733)
(ORACLE_HOME=/web/webav/base/product/7.3.3.0.2)
(GLOBAL_DBNAME=A733.netsol3.us.oracle.com)
(SDU=32767)
)
)

TRACE_LEVEL_LISTENER =  off
USE_CKPFILE_LISTENER = false
USE_PLUG_AND_PLAY_LISTENER = false


When the command "lsnrctl start" or "lsnrctl start listener" is issued,
the listener.ora file is read.  That file guides the start-up of the
SQL*Net V2 listener named "listener". .

++++
TIP:
++++

The order that the lsnrctl program searches in directories in order to
find listener.ora is:  First, if environment variable TNS_ADMIN is set,
go find the file there, or give up.  Second, if TNS_ADMIN is not set,
look in /etc or in /var/opt/oracle directories for it, depending on your
operating system.  If not there, look in the $ORACLE_HOME/network/admin
directory. Whether or not one is found from the above, also look in the
$HOME directory for a "hidden" file named ".listener.ora.  If found, it
takes precedence over the other.  They are not merged.  The hidden file
is the only one used.


=================================
Address Blocks, Listeners and MTS
=================================

Looking closer at the listener.ora, and the MTS parameters in
initSID.ora:

First, the listener process must know which protocols it is to listen
on. For each protocol, there is a way to register with the operating
system routines for that service.  For instance, the address block in
listener.ora:

(ADDRESS=
(PROTOCOL=IPC)
(KEY=A733)
)

tells the listener process to register with the operating system's IPC
services, using the key A733.  Incidentally, the executable "tnslsnr" is
what is started by the "lsnrctl start " command. It is
"tnslsnr" that is the actual listener.

IPC is a protocol that processes running on the same machine can use to
communicate with one another.  Computers usually keep all the processes
that are running concurrently on them completely unaware of all other
processes.  When two of those processes want to communicate with one
another, they can use the IPC or "Inter Process Communication" protocol
to do it.

The process that wants to receive messages by IPC must register with IPC
services on that machine.  The registering process specifies a key that
no other process on the same machine will use to register.  That is, the
key is unique.   Then, any processes that want to send messages to the
registered process use the same IPC service and the same key, saying in
effect, "Send this message to the process that registered with you using
this unique key," key A733 in the example.

Besides tell the tnslsrn process to regiseter with IPC services using
key A733, the address block:

(ADDRESS=(PROTOCOL=TCP)(HOST=netsol3)(PORT=3888))

tells the tnslsnr process to register as well with TCP services, on the
host that is the one the tnslsnr process is running on.  (Someday, it
won't have to be.)  In place of an IPC key, a process that wants to
register with TCP services uses a "port" number, 38888 in this example.

For any one IP address, TCP services allow only one process at a time to
register using any given port number.  Processes that want to
communicate
via TCP services to this host (actually, to its primary IP address)
specify the destination port number, 38888 in this case, in order to
communicate with the process they want.

Looking in the initSID.ora example, you can see that

mts_listener_address="(ADDRESS=(PROTOCOL=ipc)(KEY=A733))"
mts_listener_address="(ADDRESS=(PROTOCOL=tcp)(host=netsol3)(port=3888))"

tells the MTS dispatchers, "Go let the SQL*Net V2 listener that has
registered with IPC services using key A733 that you are available to
accept MTS connections.  Also let the listener that's registered with
TCP services on the primary IP address associated with the hostname
"netsol3" using port number 38888 that you are available to accept MTS
connections."


=========================
Monitor Listeners and MTS
=========================

Use the "lsnrctl services" command to monitor the listener.  You can
enter the command and one of its subcommands together, "lsnrctl start
listener" for example.  Or enter "lsnrctl" by itself, and be prompted
for subcommands:

lsncrctl
 start listener

Here's what the "services" subcommand shows about MTS dispatchers :

LSNRCTL> services
Connecting to (ADDRESS=(PROTOCOL=IPC)(KEY=A733))
Services Summary...
A733          has 5 service handler(s)
DEDICATED SERVER established:0 refused:0
DISPATCHER established:0 refused:0 current:0 max:60 state:ready
D001 (machine: netsol3, pid: 12716)
(ADDRESS=(PROTOCOL=ipc)(DEV=22)(KEY=#12716.1))
DISPATCHER established:0 refused:0 current:0 max:60 state:ready
D002 (machine: netsol3, pid: 12718)
(ADDRESS=(PROTOCOL=tcp)(DEV=22)(HOST=144.25.219.246)(PORT=34662))
DISPATCHER established:0 refused:0 current:0 max:60 state:ready
D003 (machine: netsol3, pid: 12720)
(ADDRESS=(PROTOCOL=tcp)(DEV=22)(HOST=144.25.219.246)(PORT=34659))
DISPATCHER established:0 refused:0 current:0 max:60 state:ready
D000 (machine: netsol3, pid: 12714)
(ADDRESS=(PROTOCOL=ipc)(DEV=22)(KEY=#12714.1))
The command completed successfully
LSNRCTL>

You can see that the listener is set up to handle dedicated connections.

It also knows about four MTS dispatchers.  D000 and D001 are ready to
accept IPC connections.  That is, if a client program like sqlplus or
like a WebServer agent sends a connection request to the SQL*Net V2
listener using IPC, then the listener will pass the connection request
along to either D000 or D001.  The SQL*Net V2 listener routes
connections to the MTS dispatchers alternating, so after 10 total
connections, you should see each MTS dispatcher has gotten five of them.

The same logic applies for any processes that use the TCP protocol to
send a connection request to the SQL*Net V2 listener.  Such processes
may be on other hosts, possibly around the world.  Or the sending
process may be on the same host as the tnslsnr process.  This is called
a "TCP loopback" connection.  It still uses TCP services to connect,
even though both sending and receiving processes are on the same host.
You'll probably find IPC services are faster than TCP services.  So when
you configure WebServer agents to connect to databases on the same host
using SQL*Net V2, you'll probably want to use IPC to make the
connection.

For instance, if the SQL*Net V2 service name specified in the V2 DCD or
V3 agent definition is: test

Then an entry in tnsnames.ora like this:

test.us.company.com =
(description =
(address =
(protocol = ipc)
(key = listener_key)
)
(connect_data =
(sid = TheSID)
)
)

will probably perform slightly better than:

test.us.company.com =
(description =
(address =
(protocol = tcp)
(host = MyHost)
(port = 1521)
)
(connect_data =
(sid = TheSID)
)
)

Notice in the two examples, one uses an IPC address block, the other a
TCP address block.

The tnsnames.ora file is usually in the same directory as listener.ora
and is found by the same directory search order as listener.ora)

The extension ".us.company.com" in the example is defined in the
tnsnames.ora entry but is not part of the service name or SQL*Net alias
specified in the WebServer.   That's okay, as long as the file
sqlnet.ora (in the same directory as tnsnames.ora and listener.ora,
located by the same search) has an entry in it like this (indented here
for clarity, but starting in the flush-left column of the file in
practice):

names.default_domain = us.company.com

If there's no such entry in sqlnet.ora, then you can either remove
".us.company.com" from the entry in tnsnames.ora, or add
".us.company.com" to the service name specified in the WebServer DCD or
PLSQL agent definition..

While you're working with the sqlnet.ora file, you'll probably want to
add the following lines as well (remember, starting flush left, not
indented):

automatic_IPC = off
trace_level_client = off
trace_file_client  = cli
trace_unique_clint = on
trace_level_server = off
trace_file_serfver = srv

The first parameter will bypass attempting a connection that ordinarily
will fail.  Even though the connection process will recover, bypassing
this attempt will speed up the connection process.

The other parameters are what you specify to enable SQL*Net tracing.
These parameters turn both client-side and server-side tracing off (by
the "trace_level_" paramater).  But if you ever need to trace (by
setting the levels to some number between 1 and 16 inclusive), you'll
have a head-start.


===========================================
Queuesize, and a Second SQL*Net V2 listener
===========================================

One SQL*Net V2 listener can only accept connection requests at a certain
maximum rate.  The rate depends on processor speed and what else the
processor is doing.  But whatever the rate, if a sustained volume of
connection requests bombard the SQL*Net V2 listener at a faster rate,
the listener won't be able to handle all requests.

To handle a burst of connection requests, the parameter "queuesize" in
listener.ora may help.  Here's how it's specified:

LISTENER =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = TCP)
(HOST = prodserv)
(PORT = 1521)
(QUEUESIZE = 200)
)
)

In the one address block in the address list above (a TCP address
block), the queuesize of 200 has been specified.  The default is O/S
specific, according to the manual "Understanding SQL*Net", but likely
well under 200.  By setting it to 200, the listener will be able to take
on more connection requests at one time. But it still cannot satisfy the
requests any faster.

If connection requests keep arriving faster than the listener can handle
them on a sustained basis, increased queuesize won't help.  You'll need
to configure a second SQL*Net V2 listeners, and configure MTS to work
with both the old and the new listeners.  Note that the RDBMS must be at
release 7.3.3 or above in order to configuremultiple SQL*Net V2
listeners to use MTS.

Browser requests that are not satisfied because the connection could not
be handled by the SQL*Net listener may lead to browsers seeing:

-- "Document contains no data"
-- "Unable to complete request at this time.  Try again later."
-- Gray screen.

If sustained connection rates above 10 - 15 per second must be
maintained, the load will probably need to be spread across more than
one listener. Let's say you need to accommodate 20 connections per
second.  The following can be specified in listener.ora to define the
parameters for two listeners, one named "listener" and the other named
"test".

In listener.ora, remember that the word "listener" is really the name of
a listener.  You can configure several listeners in one listener.ora
file, using a different name for each:

LISTENER=         ### The first half of the file is the same as before.
(ADDRESS_LIST=
(ADDRESS=
(PROTOCOL=IPC)
(KEY=A733)
)
(ADDRESS=(PROTOCOL=TCP)(HOST=netsol3)(PORT=3888)
)
)

STARTUP_WAIT_TIME_LISTENER = 0
CONNECT_TIMEOUT_LISTENER = 10

SID_LIST_LISTENER=
(SID_LIST=
(SID_DESC=
(SID_NAME=A733)
(ORACLE_HOME=/web/webav/base/product/7.3.3.0.2)
(GLOBAL_DBNAME=A733.netsol3.us.oracle.com)
(SDU=32767)
)
)

TRACE_LEVEL_LISTENER =  off
USE_CKPFILE_LISTENER = false
USE_PLUG_AND_PLAY_LISTENER = false

TEST=                             ###  Here's the new part of the file.
(ADDRESS_LIST=
(ADDRESS=
(PROTOCOL=IPC)
(KEY=A733t)               ### note the "t" added to "A733"
)                        ### and the unique port 3889
(ADDRESS=(PROTOCOL=TCP)(HOST=netsol3)(PORT=3889)
)
)

STARTUP_WAIT_TIME_test = 0
CONNECT_TIMEOUT_test = 10

SID_LIST_test=
(SID_LIST=
(SID_DESC=
(SID_NAME=A733)
(ORACLE_HOME=/web/webav/base/product/7.3.3.0.2)
(GLOBAL_DBNAME=A733.netsol3.us.oracle.com)
(SDU=32767)
)
)

TRACE_LEVEL_test =  off
USE_CKPFILE_test = false
USE_PLUG_AND_PLAY_test = false

You start the listener named "test" by entering "lsnrctl start test".
You can check its status by entering "lsnrctl status test" or its
services by entering "lsnrctl services test".  Or enter

lsnrctl
 start test
 status test
 services test
 exit

To start both the listener named "listener" and the listener named,
"test":

lsnrctl
 start        ###   or "start listener"
 start test
 exit

will start both.

Here are the changes to initSID.ora to tell the MTS dispatchers to work
with with more than one SQL*Net V2 listener.  The RDBMS must be 7.3.3 or
above:

mts_dispatchers="ipc,2"           ### The first 6 lines are like before
mts_dispatchers="tcp,2"
mts_max_dispatchers=10
mts_servers=2
mts_max_servers=10
mts_service=A733
mts_multiple_listeners = true     ### This and the next 2 parms are new
mts_listener_address="(ADDRESS_LIST=(ADDRESS=(PROTOCOL=ipc)(KEY=A733t))\
(ADDRESS=(PROTOCOL=IPC)(KEY=A733)))"
mts_listener_address="(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(host=netsol3)\
(port=3888))(ADDRESS=(PROTOCOL=tcp)(host=netsol3)(port=3889)))"

++++
TIP:
++++
You'll find that the two SQL*Net V2 listeners work with the same pool of
MTS dispatchers.  However, each listener will keep separate track of the
connections made through it.


==============
More about MTS
==============

Keep in mind that MTS involves two parts, dispatchers and servers.

The MTS dispatchers are what the clients connect to.  A client
connection will not move between dispatchers.  What the MTS dispatchers
do is, put client work on a queue.  The pool of shared servers come
along and take work
off the queue, do the work, and put the results on another queue, where
the MTS dispatchers find it and send results to the appropriate client.

Each server process does one client's work at a time.  The server
doesn't care which client.  The work of five clients will be done by
five servers. Or, in the extreme case that there's only one shared
server, that server will do one client's work, then the next, and so on.

That is to say, the MTS dispatchers do "multi-thread" the client
connections, but any one shared server only "single-thread" client work.

If all active MTS dispatchers are handling the maximum connections they
can handle, and another connection request arrives, the SQL*Net V2
listener will set that connection request up with a dedicated server
processes, even if the "mts_max_dispatchers" limit has not yet been
reached.

If the "mts_max_dispatchers" limit has not been reached, the "alter
system" command can be used to increase the number of dispatchers (or
decrease it, if you want).  For example:

alter system set mts_dispatcher="tcp,3"

will start an additional MTS dispatcher using the TCP protocol, assuming

that the initSID.ora example above was used originally to start up only
two of them.

See the SQL Reference, under Alter System for more about that command.

On the other hand, with shared servers, if your initSID.ora calls for an
initial 2 servers, max 10, but then too much work for the two servers
starts to pile up, additional servers will be spawned dynamically, up to
the maximum of ten.  When  the need for servers decreases, the
dynamically spawned servers will be stopped.

To monitor how busy the shared dispatchers are, enter the following SQL:

select name, network, status, (busy /(busy + idle)) * 100 "% of time
busy" from v$dispatchers;

To monitor how busy the shared servers are, enter the following SQL:

select name, paddr, requests,
(busy/(busy + idle)) * 100 "%TIME BUSY", status
from v$shared_server;

You may find that some servers go largely unused.  In that case, you
might reduce your "mts_servers" value in initSID.ora if holding the
total number of processes to a minimum is critical.

Conversely, you might find even the servers that are only spawned when
needed are active and very busy.  If so, consider increasing the
"mts_servers" specification to equal the current "mts_max_servers"
value, plus a few.  Then set "mts_max_servers" even higher.



==========================
Startup Procedures for MTS
==========================

MTS is basically an RDBMS service.  That is, when the RDBMS is started
up, it starts up "mts_dispatchers" worth of dispatcher processes, and
"mts_servers" worth of server processes.

The dispatchers immediately try to let the SQL*Net V2 listener(s) that
are identified in initSID.ora know that they are ready to handle
requests for MTS connections using their respective protocols.

What if the SQL*Net V2 listeners aren't running yet?  Then the RDBMS
alert logs will show a potentially serious error:  ORA-12541.  The
meaning of this error is, "No listener".  In this case, since the
listener indeed isn't running, the ORA-12541 is expected, and only means
that the listener needs to be started.

To avoid generating ORA-12541 errors in the alert logs, it's recommended
that you start the SQL*Net V2 listeners first, then start the RDBMS.
That way, the listeners will be ready when the MTS dispatchers want to
report they are ready.

What if the SQL*Net V2 listeners stop and are then started again?  Then
the MTS dispatchers will discover that the listener they checked in with

previously is no longer running, and will at intervals try to connect to

a listener again, using the information in initSID.ora again.  Within a
couple of minutes after starting the listener again, the MTS dispatchers
will have checked in with the new listener.


========================================
To Minimize Connections Each Agent Makes
========================================

To hold to a minimum the number of connections a V2 WebServer agent
makes as it starts, you can configure several V2 WebServers each in its
own ORACLE_HOME.

To conserve disk space, most directories in each configuration will be
soft links to just one set of files.

Basically, only the admin and log directories need to be unique for each
such WebServer.  Here's a script to run in the new ORACLE_HOME to create

the file system for a new V2.1 WebServer.  After running it, each
WebServer will see only its own owa.cfg and so will not make unwanted
connections to databases in other owa.cfg files.  But it will share the
directories of another WebServer where possible.  (Thanks to TJ
Goldstein for developing this script, and to Claudio Margenat for
refining it.)

#!/bin/csh
#
# Setup script for new web listener
#
# Set the "original ORACLE_HOME environment variable to
# ORIGINAL_ORACLE_HOME.  The "new ORACLE_HOME" is the
# new directory you're in when you run this script.
#
# In the new $ORACLE_HOME, create link to original $O_H/bin
#
echo 'Creating bin link...'
ln -s $ORIGINAL_ORACLE_HOME/bin bin
#
# Create a new ows21 directory in the new $O_H
#
echo 'Creating real ows21...'
mkdir ows21
#
# Create new admin and log directories in it.
#
cd ows21
mkdir admin
mkdir log
#
# Create links for other new directories to the old ones.
#
echo 'Creating links...'
ln -s $ORIGINAL_ORACLE_HOME/ows21/admdoc admdoc
ln -s $ORIGINAL_ORACLE_HOME/ows21/admbin admbin
ln -s $ORIGINAL_ORACLE_HOME/ows21/bin bin
ln -s $ORIGINAL_ORACLE_HOME/ows21/demo demo
ln -s $ORIGINAL_ORACLE_HOME/ows21/doc doc
ln -s $ORIGINAL_ORACLE_HOME/ows21/img img
ln -s $ORIGINAL_ORACLE_HOME/ows21/install install
ln -s $ORIGINAL_ORACLE_HOME/ows21/java java
ln -s $ORIGINAL_ORACLE_HOME/ows21/lib lib
ln -s $ORIGINAL_ORACLE_HOME/ows21/mesg mesg
ln -s $ORIGINAL_ORACLE_HOME/ows21/nlsdata nlsdata
ln -s $ORIGINAL_ORACLE_HOME/ows21/wrbsdk wrbsdk
ln -s $ORIGINAL_ORACLE_HOME/ows21/sample sample
#
# Copy files from the original "admin" directory into the new
# one and edit the .cfg and .app files as needed to reduce
# the numbers of DCDs and activate the number of WRBs needed
# to handle the usual demand.
#
echo 'Copying admin files'
cd admin
cp $ORIGINAL_ORACLE_HOME/ows21/admin/* .
#
#
echo ''
echo 'Directories are created.  Please edit the svadmin.cfg and'
echo 'svadmin.app in the ows21/admin directory to show '
echo 'new ORACLE_HOME and new port.'
echo 'For example, if admin port was 12345, change it to 12346'
echo 'to have it use port 12346.  Two servers cannot use '
echo 'the same port at the sametime.  Also change old paths'
echo 'to new.  For example if the old ORACLE_HOME were:'
echo ''
echo '/u1/app/oracle/product/7.3.3.0.0'
echo ''
echo 'and the new one were:'
echo ''
echo '/u1/new/WebServer2.1.1'
echo ''
echo 'then entries in the .cfg and .app files like this one for document
root:'
echo '/u1/app/oracle/product/7.3.3.0.0/ows21/doc/'
echo 'can be changed globally by entering ":" and the following string:'

echo ''
echo '%s&app/oracle/product/7.3.3.0.0&new/WebServer2.1.1&'


To avoid unwanted connections using WAS 3.0, you'll need to install into

separate WebSites   Given the complexity of the V3 directory structure,
it may not be practical to use soft links to conserve disk space.


===============
Virtual Hosting
===============

Going in the other direction, it's possible for a single WebServer or
WebAppServer to handle more than one "host" or HTTP domain, and provide
each with its own home page.  That is, one WebServer or WebAppServer can
handle requests both for www.a.com as well as for www.b.com.  This is
called "virtual hosting".  Each domain name or "host.domain" is
converted by DNS
(Domain Naming Services) to an IP address.  That is, words are converted

to the "dotted decimal" numeric address associated with the words.

Let's say  "www.a.com" is converted to 123.45.6.7 while www.b.com" is
converted to 123.45.6.8 and "www.c.com" is resolved to  123.45.6.9 for
an
IP address.    All three can be hosted by the same Web Site.

To configure one listener to accept connections to all these IPs, and
to return a different home page for each, here are steps to follow for
V2.1:

In the listener admin page, choose to configure the listener.

In the multiport section, specify all domain names, and the directory
for the home page for each on a separate line.

Address      Port  Security  Host Name  Base Directory  Log Info File
123.45.6.7    80     none    this.host  /homepage1/     /opt/weblog1/
123.45.6.8    81     none    this.host  /homepage2/     /opt/weblog2/
123.45.6.9    82     none    this.host  / homepage3/    /opt/weblog3/

The administration page requires you to specify a different port number
for each hostname.  For example, port 80 for the first, 81 for the
second, 82 for the third.

After modifying the listener with this configuration change, go into the
file system, into the $ORACLE_HOME/ows21/admin directory.  Edit the
svNAME.cfg file where NAME is the name you've specified for the
listener, like svDFLT.cfg for the listener you've named DFLT. Manually
change all the port numbers to the same.  In this example,setting all
three to 80 will cause this listener to receive all HTTP requests from
browsers to any of the domains configured.  A different home page is
returned to each.

For Web App Server 3.0, the steps are the same, except that all can be
done inside the admin screen, since the admin screens now allow you to
set the same port for more than one entry.


++++
TIP:
++++
If you leave the port numbers different, then the WebServer will indeed
listen using the specified Port and Host Name combinations, if that's
what you want it to do. One WebServer can listen using multiple ports.


++++
TIP:
++++
Notice the entries under the "Base Directory" heading.  These give the
path to a unique home page for each of the virtual hosts.  Each
directory specified here is relative to "document root" specified in the
DirMap section of the ".cfg" file.

For example, if the initial file is

index.html

and the document root is

/u1/app/oracle/product/7.3.3/ows21/doc

then browsing the URL

http://www.a.com

will return

/u1/app/oracle/product/7.3.3/ows21/doc/homepage1/index.html

while browsing the URL

http://www.b.com"

will return

/u1/app/oracle/product/7.3.3/ows21/doc/homepage2/index.html


++++
TIP:
++++
The entry in the "Host Name" column is compared with the name specified
in the browser's URL.  For example, if the entry under "Host Name" were:

production.us.company.com

but the URL used to reach the WebServer listening at port 80 on that
system were:

http://production

the server will return to the browser the error:

The request did not specify a valid virtual host

The name in the URL must match the entry in the "Host Name" field:

http://production.us.company.com


============================
RDBMS Processes and Sessions
============================

The last part in coordinating the values for Cartridge Min and Max, and
the MTS dispatcher and server values is to set "processes" in
initSID.ora to an appropriate value.

Remember that there may be ten or more "background" services that must
be included in the process count:  DBWR (database writer), LGWR (log
writer),  RECO (two-phase commit recovery), SMON (system monitor), PMON
(process
monitor), possibly archive and possibly snapshot processes, too, to
start to list them.

Also, if 20 - 30 individuals may be logged in to the database at any
given time, they must be allowed for in the specfication of the
"processes" parameter.

Finally, allow for the maximum number of agents to be running and logged

in concurrently.  And allow for any log-ins that other cartridges may
make.
(One Pro*C cartridge may open multiple "cursors", each of them a
separate log-in that's counted as yet another process.)

If you figured, "This database wlll never have more than 50 people
logged in at one time," chances are, your setting for processes is too
low. To handle the demand from a busy Web Site, a setting of "processes
= 250" or even "processes = 500" might not be excessive.

As for the "sessions" parameter, it need not be specified at all.  It
defaults to 1.1 times processes.  However, if you specify both:

process = 750
sessions = 25

You'll find the "sessions" limit will block log-ins after only 25
sessions  have been established.  That's far below the 750 you thought
you would allow.


============================
When an Agent Cannot Connect
============================

When the process limit is so low that a PL/SQL agent cannot log in to
the
database in order to run the procedure specified in the URL, the user
back at the browser will be prompted to authenticate, to provide a
username and password.  The prompting occurs even when the path is not
protected, so authentication is never needed ordinarily!

You can supply a name and password, or just chose to cancel the
authentication.  Either way, the agent will try to connect again.

If the agent still can't connect, the client is prompted for username
and password again.  If the agent can connect, then the procedure is
run and the response is sent to the client, as usual.

This behaviour, admittedly, is a "bug".  But fixing it, so browsers
aren't asked to authenticate, won't correct the base problem:  The
process limit is too low, so agents sometimes cannot connect.  At least
knowing what this behaviour means can simplify correcting the
bottom-line issue:  Increase the process limit.


===========================================
Web Application Server 3.0 Advanced Edition
===========================================


WAS 3.0 makes possible having the HTTP listener on host A, the Web
Request Broker processes on host B, and  cartridges running on host C.
See install instructions for details.

There needs to be an administrative listener/server installed on each
host, to configure the listeners, the WRB and cartridges on that host.

This configuration spreads the work of the WebServer across several
hosts, reducing the impact of each WebServer component on each system.

***
end
***





Web Application Server 3.0 Walk-Through to Resolve Common Problems
------------------------------------------------------------------

Often just after installing Oracle Web Application Server 3.0 (OWAS), or
after trying to modify it, browsing the site may display messages like:

+ Document contains no data.

+ The requested URL was not found.

+ Request Failed
We were unable to process your request at this time.
Please try again later.

+ Content-type: text/html

+ The request did not specify a valid virtual host

This walk-through can help you find the cause for these messages, and
may help you put more complex issues into perspective later on.

First, let's look at the components involved in browsing an OWAS-powered
website.  I'll call the components processes, although they are
sometimes called threads, or tasks.

A process is a series of instructions being executed in a computer.
While you could call any series of instructions a program, software as
complex as OWAS is actually a collection of many programs, each
developed separately, each doing some small part of the total work.

It's often useful to represent a process as a box:

___
|   |
| P |
|___|

Most commercial computers actually allow many processes to be running
concurrently.  The operating system or O/S allows the instructions of
one process to run for a small fraction of a second.  Then the O/S
interrupts it, lets another process's instructions execute, and so on.

It's important that each process is completely independent of all the
others in the system.  For example, if two processes are each writing to
a file -- each writing to its own file -- the two processes must not
interfere with one another.  Each of the two files they create must
contain only what the appropriate process put in it.  If a file included
bits and pieces thrown in by another process, the file would lack data
integrity. A report that your process was writing might have part of a
shopping list that another process was writing, and part of the bank
deposit transaction that still another concurrently running process was
writing.

On the other hand, sometimes two processes want to interact with one
another. One example of this is the "client-server" model, where a
client program like sqlplus is running in one process, working closely
with the oracle executable that's running in another process to provide
RDBMS services.  (Note that the executable named oracle -- all lowercase
letters -- was written by Oracle to provide ORACLE RDBMS services.)

Back in the days of Oracle V5 and into V6, both sqlplus and oracle
programs could run in a single process.  This was called "single task".

Partly for improved security, and partly to start in the direction of
networked computing, the two programs were set up so each would run in
its own process.  The sqlplus programs would run in a client process,
the oracle program in a server  process:

___       ___
|   |     |   |
| C |<--->| S |
|___|     |___|


When both processes run on one computer -- one host -- they can can take
advantage of O/S services to communicate with one another.  Generically,
these services are called IPC or "Inter Process Communications".  As the
name suggests, these are services the O/S provides to allow two
processes that are otherwise independent of one another to communicate.

When client and server processes are running on separate hosts, they
need a
networking protocol like TCP/IP to provide a way for the two to talk:
___       ________       ___
|   |     |        |     |   |
| C |<--->| TCP/IP |<--->| S |
|___|     |________|     |___|

More accurately, the client process C talks to TCP/IP services on its
host. The TCP/IP services there talk through the TCP/IP network to
TCP/IP services on the other host.  And server process S talks to those
TCP/IP services:
___       ___       _________       ___       ___
|   |     |   |     |         |     |   |     |   |
| C |<--->| T |<--->| NETWORK |<--->| T |<--->| S |
|___|     |___|     |_________|     |___|     |___|

|--- Host A ---|                   |--- Host B ---|

When the program running in client process C is sqlplus, it talks to its
TCP/IP-services process T by running another Oracle program in process
C, a program called the Oracle SQL*Net V2 TCP/IP adapter.  And on the
other side, the oracle program running in server process S runs its own
copy of the same SQL*Net V2 adapter program to communicate with the
TCP/IP-services process T on its host.

Processes that communicate over the Web are less tightly coupled than
the client-server model using TCP/IP.  In client-server, each
client-server pair of processes is dedicated to its own communications.
Each is completely unaware of communications between other client-server
pairs, even those running on the same host or hosts.  Over the Web,
several web browser processes routinely work with a single web listener
process.

What I'm calling a "web listener process" is the "web server process"
that listens for requests from browsers.  Oracle's Web Application
Server products include such a web listener and other components as well
-- called collectively the Web Request Broker and Cartridges.  So, while
you might call the process that a web browser communicates with a "web
server" since it serves the browser, I'll call it a "web listener" to
distinguish it from the Web Request Broker processes and Cartridge
processes that are also part of an Oracle "web server".

A web browser process usually communicates with a web listener process
as a "one shot" event.  That is, browser B sends a request for some
resource to web listener WL.  As soon as WL sends the resource back to
B, the communication between the two processes is considered all done.
The next request to WL may come from any other browser currently on the
Web, anywhere in the world (or anywhere in your organization, for an
Intranet Web), not necessarily from same browser B as before.

Still, we can represent one interaction between a browser and web
listener this way:

___          ____
|   |  HTTP  |    |
| B |<------>| WL |
|___|  or    |____|
SSL

HTTP (HyperText Transport Protocol) and SSL (Secure Sockets Layer) are
built on the TCP/IP networking protocol referred to already.  It would
be more accurate to represent the processes this way:

___       ___       _________       ___       ____
|   |     |   |     |         |     |   |     |    |
| B |<--->| T |<--->| NETWORK |<--->| T |<--->| WL |
|___|     |___|     |_________|     |___|     |____|

|--- Host A ---|                   |--- Host B ----|

That is, browser B communicates with TCP/IP services T on its host.
Those services communicate over the network with TCP/IP services T on
the web listener's host.  And web listener WL communicates with TCP/IP
services T on its host.

Note that Oracle SQL*Net V2 TCP/IP adapters are not involved.  Both
process B and process WL have their own routines to talk to the TCP/IP
services process T on their respective hosts.

A browser talks to TCP/IP services to request a "URL" -- a Uniform
Resource Locator.  What the browser wants is a resource that it will
display.  If that resource is a file in the file system that the web
listener has access to, the web listener can find and return the file to
complete the communications. Likewise, when the URL requests a CGI
program be run, the web listener can find and run the CGI program.

If the file that the web listener returns to the browser is not
displayable, or if the CGI script runs but fails to return anything for
the browser to display, the browser may display

Document contains no data.

That is, the requested resource was located, but no stream of data was
returned to the browser for it to display.

Diagnosing why no stream of data was returned can be very difficult.
Obvious causes include:  Files that are empty.  CGI programs that return
nothing for the browser to display.  Communication errors that keep data
streams from reaching their destination.  And, of course, bugs.  While
this error can be hard to resolve, the other errors discussed here will
be much easier to deal with.

CGI programs run "under" the web listener process.  That is, regardless
of what the CGI program does, it runs as a "child" of the web listener.
And it runs on the same host as the web listener.  Oracle introduced the
Web Request Broker to allow browsers to request programs to run, but not
with the web listener as parent, not necessarily on the same machine,
and with more capabilities.

When the web listener receives a URL (or, more accurately, when it
receives the URI or Uniform Resource Indicator part of the URL, the part
after "http://host.domain<:port_number/"), the Web Request Broker first
takes a look at it to see if the "virtual path" is one it recognizes.
For example, if the full URL were:

http://webdemo.oracle.support.com:1234/agent1/plsql/main_procedure

then the URI would be:

agent1/plsql/main_procedure

and the "virtual path" would be

agent1/plsql/

This virtual path ordinarily would be mapped by the web listener to some
physical path in its file system, showing the web listener where to find
the requested resource.

When the virtual path is mapped by twhat kind of program the browser
wants the WRB to run.  And in the case of wanting to run an agent in
order to run a PL/SQL procedure stored in an Oracle database, the
virtual path tells which agent is wanted.  In this case, agent1 is
wanted.

When the agent runs, it will run in a cartridge created by the WRB.
More accurately, it will run in a cartridge created by the "factory"
process wrbfac.  But if we lump all the WRB processes together for the
sake of simplicity, the processes look like this:

___          ____       _____       ______
|   |  HTTP  |    |     |     |     |      |
| B |<------>| WL |<--->| WRB |<--->| CART |
|___|  or    |____|     |_____|     |______|
SSL  |                               |
| Oracle Web Application Server |

The three boxes in the Oracle Web Application Server talk to one another
by UDP protocol in version 3.0.  So do the several processes I've lumped
in "WRB" to talk among themselves.  UDP is a lot like TCP/IP, but with
reduced overhead and reduced capability.  Still, UDP is enough to handle
the communication needs of these processes.  And it's faster.

In version 3.1, the protocol used is IIOP, a new and open standard
that's defined as part of CORBA, the Common Object Request Broker
Architecture. Another bulletin, "Overview of CORBA and IIIOP", is needed
to discuss them in more detail.

The agent that's running in the CART process is none other than the
client in the client-server diagrams discussed earlier!

That is, instead of running the sqlplus program in client process C,
another set of programs are running.  These agent programs determine
which database to connect to, as which user ID, using which password.
And once connected, they tell the server process which procedure to
run.  While sqlplus prompts a user for connect information, the agent
cartridge has to find this information in its configuration ... unless
"Basic Oracle" or "database" authentication is being used.

If it is, then the browser's user is prompted to provide user ID and
password. Still, the DAD configuration that's associated with the agent
configuration
tells which database the login is made to.

While there is only one WRB -- one set of WRB processes -- in any given
Oracle Web Application Server installation, there can be many web
listeners communicating with it, running on the same host as the WRB and
on other hosts as well.  Likewise, the one WRB can and routinely does
work with a large number of CARTs, running on the same host and/or other
hosts.

To summarize:

(1) Browser B sends a request for a resource to web listener WL.

(2) WL asks the Web Request Broker WRB to see if the resource is one it
can provide.

(3) The WRB recognizes the request is one it can provide through one of
the cartridges is has been configured to use.

(4) The WRB starts a cartridge, for example, an agent cartridge.  Or if
one is already running and is available, the WRB passes the request to
it. Configuring a cartridge's minimum above the default 0 keeps
cartridges going, to handle more than one request.  See the bulletin
"Configuring for Stability" for more details.

(5) The agent connects to every database it might be asked to log in
to.  That is, it connects to a server process for each database that any
agent might be asked to log in to.  If the agent process is used to do
more than one browser's request, it may be asked to act as any one of
the agents that are configured for this Web App Server.  At this point,
though, the agent programs don't know which agent they are to be.

If the databases that the agent connects to use MTS, that will reduce
the number of processes in the system -- sometimes a definite
advantage.  MTS allows a small number of dispatcher processes to accept
connections from a large number of clients, including agents.  Within
each dispatcher process, a particular client is dedicated to a
particular thread.  That preserves the integrity of client-server
communications.  But with a smaller "footprint" as far as the O/S is
concerned.

The communication between agent and server is no different from the
communication between a sqlplus client and its server.  IPC can be
used.  Or, if TCP/IP is used instead, the agent uses the same SQL*Net V2
TCP/IP adapter that sqlplus uses.  The agent uses tnsnames.ora and
sqlnet.ora files the same as sqlplus does.

If SQL*Net errors occur, keep in mind that the agent is acting very much
like sqlplus at this point.  Whatever resolves these errors from sqlplus
will resolve them for the agent.

(6) The agent requests the server to find and run the stored procedure
specified in the URI.

(7) The server runs the procedure.  If the procedure generates a data
stream to return to the browser, that data stream goes to the agent, on
to the web listener, and finally back to the browser.

And the communication is complete.

If the procedure doesn't return any data stream to the browser, instead
of the message "Document contains no data", the browser will display:

Content-type: text/html

That's because a data stream did actually start in anticipation of what
the procedure would provide, but nothing was added to this initial data
stream. Modify the procedure to produce output and this error will go
away.

When the URI is specified that's intended for the WRB, but the WRB does
not recognize the virtual path, then neither it nor the web listener
will be able to deliver the requested resource.  The browser will
display:

URL not found.

The most likely causes for this error include an incorrectly entered
URI, so the virtual path that's specified doesn't match any virtual path
that's configured, or using the DAD name in the virtual path, rather
than the agent name.

Note that, if the procedure name is entered incorrectly in the URI, the
browser does not display "URL not found" but rather displays:

Request Failed
We were unable to process your request at this time.
Please try again later.

But there are many more reasons for getting that same error.

Basically, the URI has been processed to the point that the WRB has
determined an agent is needed, and has passed the request on to an agent
(running in a "CART" process).  But the agent is not able to complete
its work.

Possible reasons for that include:  The database is down.  The userID,
password or connect string that it's using are incorrect.  SQL*Net
errors are interfering with agent-server communications.  The procedure
has been changed and is malfunctioning.  The request is passing the
wrong number of parameters or the wrong type of parameter. This
procedure depends on another procedure that currently is invalid and
can't be re-compiled successfully.

The following steps can help narrow the search for the cause of the
error:

(1) Using the svrmgrl executable in the $ORACLE_HOME/bin where OWAS3 is
installed, enter:  svrmgrl

(2) Enter:  connect uid/pwd@netv2_alias

where "uid/pwd@netv2_alias" are values from the V2 DCD or V3 DAD/Agent
configuration or match the username and password you supplied when
prompted by a browser.

If connection problems arise here, resolve them as you would any other
client-server connection problem.  If, for example, changing an
environment variable resolves svrmgrl's problem, then changing the same
environment variable that the CART process sees should resolve the
agent's problems making a connection.

(3) If connected successfully, enter:

create or replace procedure confirm1 is
begin
htp.print('hi from '||user||' confirm1');
end;
/

Type "user" as shown.  Don't substitute the login ID.  PL/SQL will
substitute the ID at runtime.  By using the variable "user" here, you
can see just who is running the procedure.  And that may be a surprise
in some cases.  See the bulletin "Tookit and Procedure Ownership Issues"
for more details.

(4) There should be no errors. If there are, enter:

show errors

If there's an error "PLS-00201: identifier 'HTP.PRINT' must be declared"
then the Web Developer's Toolkit isn't available to this user ID.

How to deal with this situation is discussed in "Toolkit and Procedure
Ownership Issues".

The most expedient option is to install the toolkit by running
owains.sql script in the same schema where the confirm1 procedure is
being created.

If the error is simply a typo, the error message tells which line and
which column in the line it had trouble with.  That can help find the
error.  When the command is entered correctly, those errors will
disappear.

(5) Enter:  set serveroutput on

(6) Enter:  execute confirm1

The procedure should complete successfully but the message that the
procedure "htp.print"ed does not appear at this time.

(7) Enter:  execute owa_util.showpage

Expect to see the message from procedure confirm1 now.  This is the same
output the browser would see by issuing a URL that runs the same
procedure. For example:

http://host.domain:port/agent_name/plsql/confirm1

If you try the URL from the browser, and the browser displays:

The request did not specify a valid virtual host

then the most likely cause is that the host name specified for the web
listener that listens at the specified port number does not match thee
"host.domain" in the URL.

That is, in the administrative web pages, when choosing to configure
that listener, the "Host Name" specified in the "Addresses and Ports"
section does not match what was specified in the URL.  (It is called the
"Host Name" regardless of whether only the host's name is specified, or
the host's name fully qualified by the domain name.)

If you look in the ".cfg" file for the listener, the speicified Host
Name is shown in the "MultiPort" section.

If the web listener is sitting behind a firewall, and browsers outside
the firewall see the message

The request did not specify a valid virtual host

then the firewall is not only intercepting the browser's message, and
forwarding them on the web listener, but also supplying a different
value for "host.domain".  On Solaris systems, the snoop utility allows
you to monitor what is actually coming to the web listener process from
the firewall.  Enter "man snoop" for more detail.

Whether you use snoop or some other network diagnostic tool, it most
likely will show there is a discrepancy between what the web listener
sees as its "Host Name", versus the host value that the firewall is
passing to it.

If the firewall cannot be configured to supply the right name, it is
possible to configure a web listener to accept multiple hostnames.  It's
only necessary that each hostname be recognized by the O/S when the web
listener asks the O/S for the IP address associated with that hostname.
For example, one listener can be configured to recognize both:

http://webdemo:1234/agent1/plsql/main_procedure

and

http://webdemo.oracle.support.com:1234/agent1/plsql/main_procedure

In conclusion, this bulletin has walked you through the Oracle Web
Application Server in a way that may help you resolve several common
error messages, and may help you deal with more complex errors as well.

##



UNIX User-ID, Permissions and Web Application Server V3
-------------------------------------------------------

Starting with Oracle Web Application Server V3.0 (OWAS3), the command
to start the server (owsctl) and the OWAS3 executable (oraweb) are no
longer owned by the root user-ID as a default.  And they also no longer
have set-user-ID and set-group-ID permissions.  As a result,

(1) You may have problems starting Web Application Servers that listen
at HTTP-default port 80, SSL-default port 443, or any other port number
under 1024.

(2) OWAS3 listeners may run under the ownership of the oracle user-ID
when you didn't expect it.  And you may consider that a security risk.

(3) OWAS3 listeners that run as low-privileged users may fail to start,
and may fail to tell why in the error logs, even though you installed
the product under the oracle ID and into the Oracle RDBMS ORACLE_HOME
directory structure as the install documentation suggested you could.

(4) After sorting out permissions and file-ownership issues in order
to get a OWAS3 listener to run as a low-privileged user, each time you
make a change to that listener's configuration, you may find you need
to sort out the issues all over again.

(5) You may wonder which ORACLE_HOME to specify in the configuration of
your DADs.  Must it be an RDMBS's ORACLE_HOME?  What if the database
that the DAD is accessing is remote? (The online help is easy to
understand incorrectly!)

(6) You now have an opportunity to simplify not only installation but
also runtime security, by installing OWAS3 under a low-privileged
user-ID, into a directory structure independent of any Oracle database,
and by running OWAS3 under that low-privileged user-ID.

Most customers chose between the following alternatives for installing
and running OWAS3:

Alternative 1, The low-privileged user approach.

To implement this option, install Oracle Web Application Server into a
file system owned by a low-privileged user.  Let's use "owas30" in
group "owas30" as an example.

User-ID owas30 will be "low-privileged" if this user-ID owns no files
other than OWAS3 files.  And if group-ID owas30 also is not the group-ID

for any other files.  That means, except for OWAS3 files, processes
running with the owas30 owning user-ID and group-ID are limited to the
access allowed for "others".  And typically, that's the most
restrictive, most secure file-access permission. (Appendix A reviews
basics of permissions and owning user-ID in more detail.)

To follow through with this option, you issue nearly all "owsctl"
commands when you are logged in as the owas30 user-ID, either by "login"

or by "su".   As a result, the WRB processes, the cartridges, and the
the HTTP listeners all run with an owning user-ID of owas30, the
low-privileged ID.

Once the administrative listener starts, it may be configured to set the

owning user-ID to some other ID, like before.  But there's really no
reason to change the owning user-ID, not only for the administrative
listener, but for all others.  Letting them all run under the owas30 ID
makes life simpler, as well as most secure.  It's also very simple to
implement, and to maintain.  I'll explain more about that in a minute.

The only issue to resolve is, when an HTTP listener wants to use a port
number under 1024, that listener must started and stopped by root. That
is, you must first log in as root or su to root before issuing the
"owsctl
start " for that listener.  The same applies to
stopping that listener.

The simplest way to accomplish this is to create "run control" files
that start up the WRB and listeners automatically during system start-up
and that stop the listener and then the WRB (note the reverse order!) at

shutdown.  The WRB and all listeners using ports above 1024 can be
started and stopped by the low-privileged user owas30.  Only the
listeners using ports below 1024 need to be started and stopped by
superuser root.  Even then, these listeners can be configured to run as
user-ID owas30, as soon as the privileged port number has been acquired.
(See Appendix B for an example "rc" script.)

A facility called "sudo" is widely and freely available that can let
adminstrators grant specified user-IDs the right to issue specified
commands as root.  That way, a non-administrator without root access can

issue "sudo owsctl start " where the named listener
acquires a port under 1024, and the listener will start successfully.
Once it starts, it can set-user-ID to owas30, reducing its security
risk.

Alternative 2, Install as oracle, run as a low-privileged user.

Many sites default to this alternative, because they install into a file
system owned by the oracle user-ID.  They run listeners that use port
numbers both above and below 1024.  And they run those listeners under
the nobody user-ID for security's sake.  This alternative is possibly
the most common, because people are used to installing Oracle products
into RDBMS "ORACLE_HOMEs" owned by the oracle user-ID.  Unfortunately,
it's not nearly as easy to maintain as the previous option. It can
create headaches not only when starting listeners at ports under 1024,
but also if the administrative listener's web pages are used to modify
configurations.  I'll elaborate further on.

Alternative 3, Install as oracle, run as oracle.

Obviously close to the previous option, in this case, you install into a

file system owned by oracle and run listeners as oracle.  This is an
easy alternative, but not very secure.  If a hacker gains control of a
process owned by the oracle user-ID, the opportunity to do harm is
greater than if the owning user-ID were owas30 or similar low-privileged

user-ID.  And this option still can't start listeners at ports under
1024 directly.  You still have to find a way to do it as root.

Alternative 4, Run owsctl and oraweb as root.

Install into a file system owned by any user-ID but usually it's oracle.
And run listener's under the root user-ID, at least at startup.  This is
essentially doing with Web Application Server V3 what was done with Web
Server 2.1.1 and before.  It can be the most hassle-free alternative,
but also the least secure.

Let me explain more about each one, in reverse order.  The last
alternative is the one you're likely most familiar with if you ran
earlier Oracle Web Server products.  But the first alternative is the
one I very definitely recomment over all the others, and I want to end
on that option.

Option 4 can be accomplished by logging in or "su"ing to root, changing
the owning user-ID of owsctl and oraweb to root and changing their
owning group to root's group, too. Then give both files set-user-ID and
set-group-ID permissions. (Script fmods.sh in $ORAWEB_HOME/install is
provided to automate this process.  But I hope you don't do it.)

After that, anyone who can execute the owsctl command can start and stop

any listener, whether it uses ports above or below 1024.  As with
earlier products, you can configure each listener to run as any user-ID
you choose, including root, oracle or nobody.  File ownership and
permissions are the least trouble.

One risk is, if some remote user figures out a way to bypass the oraweb
executable and start talking directly to the shell or process it is
running in, that remote user might be able to play with your system with
the permissions and privileges of the superuser.  And that "play" could
have disasterous consequences for your site.

Another risk:  When "su"ing to root under some versions of Solaris 2.4,
the PATH and LD_LIBRARY_PATH environment variables would not be adopted
from the session, but default to a limited set of libraries.  There are
workarounds for this problem spelled out in Oracle "bug report" 519239.

Option 3 seems convenient to implement.  Since most of us install
Oracle products under the oracle user-ID and file system, and run the
Oracle products as oracle, this alternative seems an obvious choice.
Unfortunately, it's nearly as insecure as the option 4.  After all, if
running under the root user-ID is a risk because it might allow a hacker

to gain root access to your system, the oracle user-ID is also not one
you want a hacker to have access to, in most installations.  And you
still have to deal with the problem that the oracle user-ID doesn't have

sufficient clout to use ports under 1024.  You still have to find a way
to get listeners at those lower ports started by root.

Option 2 is obviously a lot like option 3.  But a new problem often
arises here:  The oracle user-ID (group dba) owns files and directories.

The user-IDs that listeners run under may not have permission to write,
or possibly even to read, in the oracle user-ID's file structure.

Even if you get ownerships and permissions sorted out once, you may have

to revisit the issue each time you modify the configuration files.  The
administrative listener will re-write the modified configuration files
under its owning user-ID, and that may make the files inaccessible to
the listener that was modified!

And still, you have to deal with starting listeners at ports under 1024.

That leaves option 1.  It's the least familiar, but the most secure.

Using this option, you install the Web Application Server product in an
ORACLE_HOME that is NOT the ORACLE_HOME of any RDBMS.  How do that?
It's actually very simple:

(1) Create a user-ID like owas30, a low-privileged ID.
(2) Create "the top" of a file structure:  /home/owas30  or /u1/owas30
for example.
(3) Set environment variable ORACLE_BASE to this directory.
(4) Figure out ORACLE_HOME and all other environment variables from this
base.
(5) Install into this environment.
(6) In the configuration of DADs (Database Access Descriptors), where
the form asks for the ORACLE_HOME value, that will be the owas30 user's
ORACLE_HOME, not an Oracle RDBMS ORACLE_HOME. (This point is really not
new, and not directly tied to permissions.  Despite what the online doc
might lead you to believe, you should always specify here the
ORACLE_HOME where the Web Server product is installed.  The ORACLE_HOME
where a database is installed is never needed at this point.)

Won't it matter that there's no RDBMS in this file structure?  Most
likely, it actually makes  a difference in a positive direction.  It
avoids version conflicts between Web Application Server components like
svrmgrl that may not run properly out of an RDBMS ORACLE_HOME.  And it
forces you to use SQL*Net V2 to connect to any RDBMS, even it they are
running on the same host as the Web Application Server.

You use SQL*Net V2 by specifying a V2 service names in your DADs, to
access all databases, even databases that are running on the same host.
Using SQL*Net V2 allows you to use MTS for your V7 database -- see the
"Stabilitiy Bulletin" for more about why MTS can be beneficial.  And
SQL*NET V2 allows the OWAS3 agents to connect to Oracle8 databases.

To review SQL*Net V2 issues briefly and incompletely:

+ A listener.ora file tells a SQL*Net V2 listener where to listen (at
which TCP/IP port, and which IPC key, for example) as well as which SIDs

it will recognize and what is the ORACLE_HOME for each RDBMS SID.
+ On the Web Application Server's side -- the agent's side -- there are
two files, tnsnames.ora and sqlnet.ora, that give the agent the
information it needs in order to contact the listener.
+ Basically, the agent needs to know which protocol, which port or key,
and which SID to use in order to contact the listener referred to above.

+ You specify a SQL*Net V2 service name in the DAD, which the agent
looks up in the tnsnames.ora file.  There, the agent finds the detailed
information it needs in order to contact the listener, and through that
listener, establish a connection to the appropriate database.
+ The sqlnet.ora file tells the agent whether to try  making an IPC
connection regardless of what protocol the tnsnames.ora files says to
use -- usually simply a waste of time, and usually best disabled -- as
well as at what level to generate a SQL*Net trace, and whether a
default domain needs to be appended to the service name specified in the
DAD, before looking up the service name in the tnsnames.ora file.
+ There's lots more to say about each of these files and about SQL*Net
V2.  Keep in mind, this was just a start.

To return to discussing UNIX permissions and user-IDs, the security risk

associated with them has already been mentioned briefly.  In general,
the risk is that some user sitting at a remote browser can somehow
bypass talking to the running HTTP listener executable, and start
talking directly to the process or "shell" that the executable is
running in.  In the early days of the Web, a CGI program that didn't
check user-supplied information for special characters might allow a
remote user to trick the server's shell into opening a session on the
remote user's machine, and allow the remote user to input commands
through that window to the shell.  If the shell had root user-ID
privilege, the remote user could read any file, change any file, shut
down the system -- anything.   It's getting harder and harder for
hackers to bypass the executables and talk to the shells they run in.
But better to play it safe and have the shell's owning user-ID be that
of a low-privileged user-ID, just in case.

What about the WRB processes?  Do they care if they don't run as root?
Not as long as the UDP port number used by the WRB processes is above
1024.  The default is 2649.  The processes communicate among
themselves,  and communicate with cartridges and with the HTTP listeners

using the UDP protocol.  UDP is a variation of the TCP/IP protocol
that's simplified and quicker.  As long as the port they use is above
1024, any user who can issue "owsctl start wrb" can start the WRB
processes.  Even a low-privileged user like the suggested owas30 ID.
The "ps" command will show that the several WRB processes all continue
to run with the owning ID of the session that started them.  Running
under a low-privileged user-ID will have no effect on them.


In summary, user-ID, group-ID and file permissions are more an issue for

Web Application Server V3 installed on UNIX systems than they were for
Web Server V2.1.1 and earlier.  That's because the owsctl command and
oraweb executable are no longer owned by root, nor do they have
set-user-ID and set-group-ID permissions.  That means they continue to
run  with the owning user-ID and group-ID of the process that started
them.

While this change may require new procedures in order to start HTTP
listeners that use port numbers under 1024, it also can increase the
security of the entire system, by reducing the opportunity for
outsiders to gain control of shell processes owned by root or by oracle.



APPENDIX A
----------

How user-ID and permissions work
--------------------------------

When you login to a UNIX system, typically a process or "shell" begins
running in the computer that provides you with a session.   This session

lets you can enter input at the keyboard, see what you typed on a
screen, enter commands, and see results of entering those commands.

Your login process has several identifiers.  For example, it has an
owning user-ID -- your login ID.  It also has a group-ID that system
adminstrators have assigned you to.

Another important identifier is the Process ID or "PID" (rhymes with
"kid").  The PID is a unique number that the system assigns to each
process running in the system.  This PID helps keep each process
completely separate from any others that's are running concurrently in
the system.

While the PID of each process is unique, more than one concurrently
running process may share the same owning user-ID and group-ID.

When you enter any command -- for example, "ps" or "vi some.file" or
"owsctl start wrb" -- your login process "forks".  Forking is actually
a system function.  Forking makes a new process that's identical to the
original in every way -- same owning user-ID and group-ID, same programs
and environment variables -- identical in every way except for the PID.

It's standard practice after a program successfully forks, for the
program to check its PID immediately.  If its PID is unchanged, the
program knows it is the original process, called the parent process.
And the parent process continues as before.  In this case, the parent
continues to provide you with a login session.

If its PID is changed, the program knows it is a "child" process.  While

it is, at this moment, exactly like the parent, executing the same
instructions, working in the same environment, the child knows it's
supposed to do something else.   In this case, it is supposed to find
the executable that you specified -- ps, or vi, or owsctl for example --
load it into its process space or "shell", and start running that new
program.

When the command that starts running accesses files -- like vi will to
edit the file, and owsctl will to read configurations -- then the issue
of permissions on those files comes into play.

The owner of each file can determine whether the file can be read, can
bewritten (that is, can be re-written, or changed) or can be executed.
Each of these permissions can be assigned separately to:

1. The file's owner.
2. Other users in the same group as the owner.
3. All other users, not the owner, and not in the owner's group.

For a file you own, could you deny yourself permission to write your own
file?  That is, not allow yourself to re-write, or change the file, even
though you own it?  Sure.   You could even set permissions so you can't
even read your own file!  That's not a very useful setting in most
cases.  But it shows the power of the permissions.

The more usual issues about a file are:

+ Does the owner allow others in the owner's group to write it?
+ Are others not in the group allowed to write the file?
+ Are others not in the group even allowed to read it?

Say you have a confidential file.  You can set permissions to allow the
owner to read and write it (and to execute it, if it's an executable
file), but allow only read access to other users in the same group,and
neither read access nor write access to all others.  The confidentiality

of your file is fairly safe.  It won't be read by any process owned by
any user outside your group.  And it won't be changed by a process with
any user-ID than your own (although root still could, of course).

While it's reassuring to talk about protecting a confidential file with
permissions, the same rules apply when your Web Server configuration and

log files are owned by user-ID oracle, group-ID dba, but the listener
that needs to read the configuration file and write files in the log
directory has a different owning user-ID and group-ID.  If the listener
cannot read what it needs to read, or cannot write what it
needs to write, it will fail to start!  And it may not be able to write
an error message to tell you why!

Before Web Application Server 3.0, user-ID, group-ID and permissions
were less of a issue because of two more permissions that can be
assigned to executable files.  These are the set-user-ID and Setgroup-ID

permissions. For more information about permissions and ownership, see
the "man page" for "ls".  At the UNIX prompt, enter "man ls" to see the
man pages for the ls command.

The command "ls -l" lists files, their owning user-ID and group-ID, and
permissions.  You may also want to read the man pages for "chmod"
(changes mode, or permissions) and for "chown" (changes owner).

Here's how set-user-ID and set-group-ID work:

As an example, let's look at the "wlctl21" command used to start up the
Web Server V2.1 listener.  A script run at the end of installation --
root.sh -- set the file's owning user-ID to root, and gave the file the
set-user-ID permission.  (The same applies for group-ID, remember, but
I'll just talk about user-ID from now on.)

What happens when you enter "wlctl21 start admin" is, your login session
responds by forking as usual.  The child has your login ID as its owning

user-ID, as usual.  And the child finds the "wlctl21" executable, as
usual.  But because the wlctl21 file has set-user-ID permission, the
child process now changes its owning user-ID to be the same as the
user-ID that owns the file. That is, to the superuser, root.

A process running under an owning user-ID of root is much more powerful.

In general, it can read and write any file it wants to.  And it can
start any HTTP listener that wants to use a port number under 1024.

On the other hand, don't lose track of the child process's "ancestry".
It still has the same environment variable settings as its parent, your
login session.

What happens in the child process that's running wlctl21?  It forks
again, and starts running the HTTP listener executable, oraweb21.  This
executable also has the set-user-ID permission and is owned by root.  So

it can use any port it wants, even under 1024.

Once the oraweb21 executable is running, you can configure that listener

to run as any UNIX ID you want.  Like oracle.  Or nobody.  That is, the
process that's running oraweb21 as root can yet again change its owning
user-ID.   That's how you get a listener at HTTP-default port 80, or
SSL-default port 443, or any other port under 1024 that runs with a
low-privileged user-ID like the nobody ID.

You can accomplish the same when you run OWAS3 too, but now permissions
come into play as they didn't with wlctl21 and oraweb21.

That's because neither the owsctl command file nor oraweb executable are

owned by root.  Nor do they have set-user-ID permission.  That means
they run with the owning user-ID of their parent process.  If the parent

is your login process, then the owning user-ID they run with is your
login ID.  The file access permissions your login ID has are the access
permissions that owsctl has.  Those permissions also apply to the oraweb
process, up to the point it sets its owning user-ID to another user, if
that's what its configuration file directs it to do.

If you configure your administrative listener either to continue to run
with your login ID as its owning user-ID, or to change to a user-ID like
nobody, then when you use that adminstrative listener to start other Web

Application Server listeners, the new listener processes will inherit
the current owning user-ID -- your login ID, let's say.   That's when
the permissions to access configuration and log files can cause troubles
you never had before.  That's when a listener that wants to use a port
number under 1024 doesn't have the necessary authority or privilege.


APPENDIX B
----------

An example file from a Solaris system to automate startup and shutdown
of the wrb and some listeners by a low-privileged user, and to start two
listeners as user root so they can acquire ports under 1024:

#!/bin/sh
#
# Script to handle automatic shutdown, startup of Web App Servers
#

case "$1" in
'start')
echo "Web App Servers starting."
#
# The next entry "su"s to an ID and runs its initialization script
# The initialization script sets environment variables needed to
# start the wrb and low-privileged OWAS3 listeners admin and AV01.
#
/bin/su - webav -c '$ORAWEB_HOME/bin/owsctl start wrb'
/bin/su - webav -c '$ORAWEB_HOME/bin/owsctl start admin'
/bin/su - webav -c '$ORAWEB_HOME/bin/owsctl start AV01'
#
# Below are the same environment variables, now being set for root
#
ORACLE_BASE=/web/app/oracle
ORACLE_HOME=/web/app/oracle/product/7.3.3.0.2
ORACLE_SID=A733
export ORACLE_BASE ORACLE_HOME ORACLE_SID
ORAWEB_HOME=$ORACLE_HOME/ows/3.0
ORAWEB_SITE=WAS30A
ORAWEB_BASE=$ORACLE_HOME/ows
ORAWEB_ADMIN=$ORACLE_BASE/admin
ORAWEB_CARTX=$ORACLE_BASE/admin  # see note, inst gde 2-11
LD_LIBRARY_PATH=$ORACLE_HOME/lib
PATH=$ORAWEB_HOME/bin:$ORACLE_HOME/bin:/usr/ccs/bin:$PATH
TMPDIR=/web/tmp
TNS_ADMIN=$ORACLE_HOME/network/admin
export ORAWEB_HOME ORAWEB_SITE ORAWEB_BASE ORAWEB_ADMIN
export ORAWEB_CARTX LD_LIBRARY_PATH PATH TMPDIR TNS_ADMIN
#
# Now start listeners that use ports 443 and 80
#
$ORAWEB_HOME/bin/owsctl start avwssl
$ORAWEB_HOME/bin/owsctl start www
;;
'stop')
echo "Web App Servers stopping."
ORACLE_BASE=/web/app/oracle
ORACLE_HOME=/web/app/oracle/product/7.3.3.0.2
ORACLE_SID=A733
export ORACLE_BASE ORACLE_HOME ORACLE_SID
ORAWEB_HOME=$ORACLE_HOME/ows/3.0
ORAWEB_SITE=WAS30A
ORAWEB_BASE=$ORACLE_HOME/ows
ORAWEB_ADMIN=$ORACLE_BASE/admin
ORAWEB_CARTX=$ORACLE_BASE/admin  # see note, inst gde 2-11
LD_LIBRARY_PATH=$ORACLE_HOME/lib
PATH=$ORAWEB_HOME/bin:$ORACLE_HOME/bin:/usr/ccs/bin:$PATH
TMPDIR=/web/tmp
TNS_ADMIN=$ORACLE_HOME/network/admin
export ORAWEB_HOME ORAWEB_SITE ORAWEB_BASE ORAWEB_ADMIN
export ORAWEB_CARTX LD_LIBRARY_PATH PATH TMPDIR TNS_ADMIN
#
# Note that the listeners and wrb are stopped in the reverse of the
# order they were started in.  What really matters is that the wrb
# be started first, and be stopped last.
#
$ORAWEB_HOME/bin/owsctl stop avwssl
$ORAWEB_HOME/bin/owsctl stop www
/bin/su - webav -c '$ORAWEB_HOME/bin/owsctl stop AV01'
/bin/su - webav -c '$ORAWEB_HOME/bin/owsctl stop admin'
/bin/su - webav -c '$ORAWEB_HOME/bin/owsctl stop wrb'
;;
*)
echo "Usage: /etc/init.d/avwweb30 { start | stop }"
;;
esac
exit 0


On Solaris, save this script as file avwweb30 in the /etc/init.d
directory. Then create file K30web in /etc/rc0.d as a soft-link to the
avwweb30 file. And create file S30web in /etc/rc3.d directory.

At system shutdown, the files in /etc/rc0.d are run, passing the
parameter "stop" to each that starts with "K" (for "kill").  That will
lead to running the "stop" portion of the above script, stopping the
listeners and wrb.

At system startup, as the system enters Run State 3, the files in
/etc/rc3.d are run, passing the parameter "start" to each that starts
with "S".  That leads to running the portion of the script that starts
the wrb and listeners.



##






Toolkit and Procedure Ownership Issues
--------------------------------------

In order to see the most common issue involving ownership of the Web
Developer's Toolkit and procedures that produce output destined for web
browsers,

(1) Use srvmgrl from $ORACLE_HOME/bin where OWAS is installed.

(2) Connect to the database you'll use to test, as a DBA ID like
system/manager.

(3) Create two schemas UserA and UserB, and grant connect and resource
privileges to both.

create user usera identified by usera;
create user userb identified by userb;
grant connect, resource to usera;
grant connect, resource to userb;

(4) Log in as UserB and run the script:

-- Beginning script ...

@$ORAWEB_HOME/admin/owains -- install the Toolkit in this schema

create or replace procedure report_body is
begin
htp.print('This is the body of the report.');
htp.print('It came from UserB procedure report_body.');
htp.print('It is being run by '||user);
end;
/
show errors
set serveroutput on
execute report_body
execute owa_util.showpage

grant execute on report_body to UserA;

-- End of script

Expect to see output like:

This is the body of the report.
It came from UserB procedure report_body.
It is being run by USERB

(5) Log in as UserA and run this script:

-- Beginning of script ...

@$ORAWEB_HOME/admin/owains -- install the Toolkit in this schema

create synonym report_body for UserB.report_body;

create or replace procedure header is
begin
htp.print('This is the header of the report.');
htp.print('It came from UserA procedure header.');
htp.print('It is being run by '||user);
end;
/

create or replace procedure footer is
begin
htp.print('This is the footer of the report.');
htp.print('It came from UserA procedure footer.');
htp.print('It is being run by '||user);
end;
/

create or replace procedure report is
begin
header;
report_body;
footer;
end;
/

set serveroutput on
execute report
execute owa_util.showpage

grant execute on header to UserB;
grant execute on footer to UserB;
grant execute on report to UserB;

-- End of script

Expect to see output like:

This is the header of the report.
It came from UserA procedure header.
It is being run by USERA
This is the footer of the report.
It came from UserA procedure footer.
It is being run by USERA

Note that the report body is missing!

(6) Log in a UserB again and run the script:

-- Beginning of script

create synonym header for UserA.header;
create synonym footer for UserA.footer;
create synonym report for UserA.report;

set serveroutput on
execute report
execute owa_util.showpage

-- End of script

Expect to see output like:

This is the body of the report.
It came from UserB procedure body.
It is being run by USERB

(7) The output demonstrates what a web browser would see, if a URL led
to an agent's connecting to the database as UserA or UserB respectively.

Notice that, when UserA ran its report, the output does not include the
report body.

Conversely, when UserB runs UserA's report procedure, the procedure runs

successfully, but the only output UserB sees is from the procedure it
owns, the body procedure.

The reason is that the output from each procedure is inserted into
temporary PL/SQL tables before being picked up for display by the
owa_util.showpage procedure.  These temporary tables have an owner, and
if owa_util.showpage is not running as that owner, it cannot access the
information in the PL/SQL tables.  Whatever output they were supposed to
provide is missing.

This issue is the main point in this bulletin.

(8) Now drop both UserA and UserB, and all their objects:

drop user UserA cascade;
drop user UserB cascade;

(9) Create them again, along with an ID I'll call TOOLKIT.

create user toolkit identified by toolkit;
create user usera identified by usera;
create user userb identified by userb;
grant connect, resource to toolkit;
grant connect, resource to usera;
grant connect, resource to userb;

(10) Connect as TOOLKIT and run this script:

-- Begin script

set define off  -- if running in sqlplus, "set define off" first
@$ORAWEB_HOME/admin/owains  -- install the Toolkit in this schema

-- Grant execute privileges on toolkit packages to UserA and UserB.
-- (Or grant it to public.  Creating public synonyms here also would
-- simplify later steps.)

grant execute on OWA_INIT to UserA;
grant execute on HTF to UserA;
grant execute on HTP to UserA;
grant execute on OWA_UTIL to UserA;
grant execute on OWA_SEC to UserA;
grant execute on OWA to UserA;
grant execute on OWA_TEXT to UserA;
grant execute on OWA_PATTERN to UserA;
grant execute on OWA_IMAGE to UserA;
grant execute on OWA_COOKIE to UserA;
grant execute on OWA_OPT_LOCK to UserA;

grant execute on OWA_INIT to UserB;
grant execute on HTF to UserB;
grant execute on HTP to UserB;
grant execute on OWA_UTIL to UserB;
grant execute on OWA_SEC to UserB;
grant execute on OWA to UserB;
grant execute on OWA_TEXT to UserB;
grant execute on OWA_PATTERN to UserB;
grant execute on OWA_IMAGE to UserB;
grant execute on OWA_COOKIE to UserB;
grant execute on OWA_OPT_LOCK to UserB;

-- End of script

(11) Now connect as UserB and run a script like the earlier one, but
creating synonyms for the toolkit, rather than installing it in this
schema:

-- Begin script

-- Establish synonyms for the toolkit packages that user toolkit owns.
-- If user toolkit created public synonymns, this wouldn't be needed.


create synonym OWA_INIT for toolkit.OWA_INIT;
create synonym HTF for toolkit.HTF;
create synonym HTP for toolkit.HTP;
create synonym OWA_UTIL for toolkit.OWA_UTIL;
create synonym OWA_SEC for toolkit.OWA_SEC;
create synonym OWA for toolkit.OWA;
create synonym OWA_TEXT for toolkit.OWA_TEXT;
create synonym OWA_PATTERN for toolkit.OWA_PATTERN;
create synonym OWA_IMAGE for toolkit.OWA_IMAGE;
create synonym OWA_COOKIE for toolkit.OWA_COOKIE;
create synonym OWA_OPT_LOCK for toolkit.OWA_OPT_LOCK;

--  Now dow the same as before:

create or replace procedure report_body is
begin
htp.print('This is the body of the report.');
htp.print('It came from UserB procedure report_body.');
htp.print('It is being run by '||user);
end;
/
show errors
set serveroutput on
execute report_body
execute owa_util.showpage

grant execute on report_body to UserA;

-- End of script

Expect the same output as before.  It confirms UserB can see output from
its own procedure.

This is the body of the report.
It came from UserB procedure report_body.
It is being run by USERB

(12) As UserA, run a script similar to the one before, but again setting

up synonyms for the toolkit procedures:

-- Begin script

-- Establish synonyms for the toolk packages toolkit owns.

create synonym OWA_INIT for toolkit.OWA_INIT;
create synonym HTF for toolkit.HTF;
create synonym HTP for toolkit.HTP;
create synonym OWA_UTIL for toolkit.OWA_UTIL;
create synonym OWA_SEC for toolkit.OWA_SEC;
create synonym OWA for toolkit.OWA;
create synonym OWA_TEXT for toolkit.OWA_TEXT;
create synonym OWA_PATTERN for toolkit.OWA_PATTERN;
create synonym OWA_IMAGE for toolkit.OWA_IMAGE;
create synonym OWA_COOKIE for toolkit.OWA_COOKIE;
create synonym OWA_OPT_LOCK for toolkit.OWA_OPT_LOCK;

--  Now dow the same as before:

create synonym report_body for UserB.report_body;

create or replace procedure header is
begin
htp.print('This is the header of the report.');
htp.print('It came from UserA procedure header.');
htp.print('It is being run by '||user);
end;
/

create or replace procedure footer is
begin
htp.print('This is the footer of the report.');
htp.print('It came from UserA procedure footer.');
htp.print('It is being run by '||user);
end;
/

create or replace procedure report is
begin
header;
report_body;
footer;
end;
/

show errors
set serveroutput on
execute report
execute owa_util.showpage

grant execute on header to UserB;
grant execute on footer to UserB;
grant execute on report to UserB;

-- End of script

Expect output like:

This is the header of the report.
It came from UserA procedure header.
It is being run by USERA
This is the body of the report.
It came from UserB procedure report_body.
It is being run by USERA
This is the footer of the report.
It came from UserA procedure footer.
It is being run by USERA

PL/SQL procedure successfully completed.

(13) Connect as UserB and run:

-- Beginning of script

create synonym header for UserA.header;
create synonym footer for UserA.footer;
create synonym report for UserA.report;

set serveroutput on
execute report
execute owa_util.showpage

-- End of script

Expect to see output like:

This is the header of the report.
It came from UserA procedure header.
It is being run by USERB
This is the body of the report.
It came from UserB procedure report_body.
It is being run by USERB
This is the footer of the report.
It came from UserA procedure footer.
It is being run by USERB

PL/SQL procedure successfully completed.

Notice that UserB is running UserA's procedure "report" and UserA's
"header"and "footer" procedures as well, and is now able to see the
output of those procedures.

(14) When neither schema contains the toolkit procedures, either
schema sees all the output from procedures in the other schema as
well as in its own.

This bulletin will explore a more complex configuration of schemas.
But despite the complexity, the issue of who owns the toolkit, who
owns the procedures, and who executes the procedure will behave
essentially as demonstrated above.

 
Hosting by WebRing.