Wednesday October 07, 2009 About LDAP connections in Sun Web Server 7.0
When I have in my server.xml confiured an Sun LDAP server as given below :
<auth-db> <name>ldap</name> <url>ldap://localhost:1369/o%3DTestCentral</url> <property> <name>binddn</name> <value>cn=Directory Manager</value> </property> <property> <name>bindpw</name> <value>...</value><encoded/> </property> </auth-db>
When I have ACL set
acl "uri=/"; deny (all) user="anyone"; allow (all) user="all";
When I send a request via browser as user "alpha" and its correct password.
First it binds as the user specified in server.xml "binddn" property ( in this case "cn=Directory Manager")
Then sends a LDAP search query with filter "uid=alpha".
Third step it does is it binds as that user "alpha" with the password user specified. If bind is successful, access is allowed.
Here are the entries I get in LDAP server access logs:
[07/Oct/2009:13:16:16 +051800] conn=2 op=-1 msgId=-1 - fd=34 slot=34 LDAP connection from 127.0.0.1 to 127.0.0.1 [07/Oct/2009:13:16:16 +051800] conn=2 op=0 msgId=1 - BIND dn="cn=Directory Manager" method=128 version=3 [07/Oct/2009:13:16:16 +051800] conn=2 op=0 msgId=1 - RESULT err=0 tag=97 nentries=0 etime=0 dn="cn=directory manager" [07/Oct/2009:13:16:16 +051800] conn=2 op=1 msgId=2 - SRCH base="o=testcentral" scope=2 filter="(uid=alpha)" attrs="c" [07/Oct/2009:13:16:16 +051800] conn=2 op=1 msgId=2 - RESULT err=0 tag=101 nentries=1 etime=0 [07/Oct/2009:13:16:16 +051800] conn=2 op=2 msgId=3 - BIND dn="uid=alpha,o=TestCentral" method=128 version=3 [07/Oct/2009:13:16:16 +051800] conn=2 op=2 msgId=3 - RESULT err=0 tag=97 nentries=0 etime=0 dn="uid=alpha,o=testcentral"
To understand why we see these three entries, I started debugging Web Server from LASUserEval function and came at get_is_valid_password_ldap function. Note that line numbers in Open Web Server may differ but the concepts are the same :
t@16 (l@16) stopped in get_is_valid_password_ldap at line 455 in file "ldapacl.cpp"
467 if ((rv = ld->find_userdn(raw_user, basedn, &userdn)) == LDAPU_SUCCESS) {
(dbx) p filter
filter = "uid=alpha"
...
t@16 (l@16) stopped in LdapSession::find_userdn at line 1253 in file "LdapOps.cpp"
1253 retval = find(base, LDAP_SCOPE_SUBTREE, filter, attrs, 1 /* no attrs */, res);
(dbx) s
...
t@16 (l@16) stopped in LdapSession::find at line 1174 in file "LdapOps.cpp"
1174 res = search(base, scope, filter, (char **)attrs, attrsonly, 0);
(dbx) p base
base = 0x6ed6048 "o=TestCentral"
(dbx) p filter
filter = 0xfbfbc98c "uid=alpha"
...
(dbx) n
t@16 (l@16) stopped in LdapSession::search at line 289 in file "LdapSession.cpp"
289 rv = bindAsDefault();
(dbx) s
t@16 (l@16) stopped in LdapSession::bindAsDefault at line 235 in file "LdapSession.cpp"
235 int msg_id = ldap_simple_bind(session, ldapRealm->getBindName(), ldapRealm->getBindPwd());
(dbx) p msg_id
msg_id = 1
...
(dbx) n
t@16 (l@16) stopped in LdapSession::bindAsDefault at line 240 in file "LdapSession.cpp"
240 int ret = ldap_result( session, msg_id, 0, &time_out, &res);
(dbx) p ret
ret = 97
...
As we can see Web Server first tries to bindAsDefault ie. bind as cn=Directory Manager. by looking at LDAP Server logs, we confirm this.
[07/Oct/2009:14:52:03 +051800] conn=4 op=-1 msgId=-1 - fd=34 slot=34 LDAP connection from 127.0.0.1 to 127.0.0.1 [07/Oct/2009:14:52:03 +051800] conn=4 op=0 msgId=1 - BIND dn="cn=Directory Manager" method=128 version=3 [07/Oct/2009:14:52:03 +051800] conn=4 op=0 msgId=1 - RESULT err=0 tag=97 nentries=0 etime=0 dn="cn=directory manager"
When bind is successful, now it tries LDAP search on basedn="o=TestCentra" with filter "uid=alpha"
...
(dbx) n
t@16 (l@16) stopped in LdapSession::search at line 296 in file "LdapSession.cpp"
296 rv = lastoprv = ldap_search_ext_s(session, base, scope, filter,
297 attrs, attrsonly,
298 NULL, NULL, &time_out, LDAP_NO_LIMIT, &search_results);
(dbx) p base
base = 0x6ed6048 "o=TestCentral"
(dbx) p scope
scope = 2
(dbx) p filter
filter = 0xfbfbc98c "uid=alpha"
...
(dbx) n
t@16 (l@16) stopped in LdapSession::find at line 1178 in file "LdapOps.cpp"
1178 break;
(dbx) n
t@16 (l@16) stopped in LdapSession::find at line 1187 in file "LdapOps.cpp"
1187 numEntries = res->entries();
(dbx) n
t@16 (l@16) stopped in LdapSession::find at line 1189 in file "LdapOps.cpp"
1189 if (numEntries == 1) {
(dbx) p numEntries
numEntries = 1
(dbx) n
...
(dbx) n
t@16 (l@16) stopped in LdapSession::find_userdn at line 1278 in file "LdapOps.cpp"
1278 *dn = entry->DN();
(dbx) p *dn
*dn = 0x2d87b0 "uid=alpha,o=TestCentral"
(dbx)
...
Looking at LDAP server access logs it has created this "SRCH" entry :
[07/Oct/2009:14:55:51 +051800] conn=4 op=1 msgId=2 - SRCH base="o=testcentral" scope=2 filter="(uid=alpha)" attrs="c" [07/Oct/2009:14:55:51 +051800] conn=4 op=1 msgId=2 - RESULT err=0 tag=101 nentries=1 etime=0
So at the end of find_userdn function, we get our userdn "uid=alpha,o=TestCentral". Coming back to debugger
(dbx) p userdn userdn = 0x2d87b0 "uid=alpha,o=TestCentral" (dbx) t@16 (l@16) stopped in get_is_valid_password_ldap at line 531 in file "ldapacl.cpp" 531 rv = ld->userdn_password(userdn, raw_pw); (dbx) s ... (dbx) n t@16 (l@16) stopped in LdapSession::userdn_password at line 1052 in file "LdapOps.cpp" 1052 int msgid = ldap_simple_bind(session, userdn, password); (dbx) p userdn userdn = 0x2d87b0 "uid=alpha,o=TestCentral" ... (dbx) n t@16 (l@16) stopped in LdapSession::userdn_password at line 1058 in file "LdapOps.cpp" 1058 rc = ldap_result(session, msgid, 0, &zerotime, &res ); (dbx) n (dbx) p rc rc = 97 ...
As we can see Web Server tries to bind to LDAP server with userdn "uid=alpha,o=TestCentral" and we can confirm that by looking at LDAP server logs :
Posted by meena ( Oct 07 2009, 03:47:18 PM IST ) Permalink Comments [4][07/Oct/2009:15:00:37 +051800] conn=4 op=2 msgId=3 - BIND dn="uid=alpha,o=TestCentral" method=128 version=3 [07/Oct/2009:15:00:37 +051800] conn=4 op=2 msgId=3 - RESULT err=0 tag=97 nentries=0 etime=0 dn="uid=alpha,o=testcentral"
Enabling Client Certificate Authentication in Sun Web Server 7.0 reverse proxy server and origin server
For this I have setup two Sun Java System Web Server 7.0 update 6 instances. One acting as a reverse proxy and the other origin server that serves the request. Enabled SSL and client authentication on both these instances. Sent SSL requests with client certificates from a test client.
I created self signed certificate in reverse proxy server.
$cd <ws-install-dir>/https-test/config$rm *.db$../../bin/certutil -N -d .$../../bin/certutil -S -d . -n Server-Cert-Reverse-Proxy-Server -s "CN=test.sun.com" -x -t "CT,CT,CT"$../../bin/certutil -L -d .Certificate Nickname Trust AttributesSSL,S/MIME,JAR/XPI Server-Cert-Reverse-Proxy-Server CTu,Cu,Cu
You can use Admin Server CLI to create a self signed certificate
wadm>create-selfsigned-cert --config=test.sun.com --server-name=test.sun.com --nickname=Server-Cert-Reverse-Proxy-Server
For convenience I copied these *.db to origin server instance config directory, and hence used the same server certificate in origin server. In real world use a new server certificate for origin server.
In obj.conf I have confiugured reverse proxy in such a way that all requests are redirected to origin server. In real world situation you can if you want redirect only certain requests depending on your requirements.
Run create-reverse-proxy CLI from Administration server
wadm>create-reverse-proxy --config test --vs test --uri-prefix=/ --server=https://test.sun.com:4444
*obj.conf gets modified as shown below :
<Object name="default">AuthTrans fn="match-browser" browser="*MSIE*" ssl-unclean-shutdown="true"NameTrans fn="map" from="/" name="reverse-proxy-/" to="/"...</Object><Object ppath="*">Service fn="proxy-retrieve" method="*"</Object><Object name="reverse-proxy-/">Route fn="set-origin-server" server="https://test.sun.com:4444"</Object>...
Enable "ssl" in http-listener, added server certificate nickname (if its different from "Server-Cert") and set client authentication as "required" :
You can use Admin Server CLI to do these steps
wadm> set-ssl-prop --config=test.sun.com --http-listener=http-listener-1
server-cert-nickname=Server-Cert-Reverse-Proxy-Server enabled=true client-auth=requiredwadm> deploy-config test.sun.com<http-listener>
<name>http-listener-1</name>
<port>3333</port>
<server-name>test.sun.com</server-name>
<default-virtual-server-name>test</default-virtual-server-name>
<ssl>
<server-cert-nickname>Server-Cert-Reverse-Proxy-Server</server-cert-nickname>
<client-auth>required</client-auth> </ssl>
</http-listener>
In server.xml I have also modified access log format so that we can see what is happening. This will slow down Web Server performance so do not do this in production environment.
<access-log><file>../logs/access</file><format>%Ses->client.ip% "%Req->reqpb.clf-request%" %Req->srvhdrs.clf-status% %Req->srvhdrs.content-length% %Ses->client.cipher% %Req->vars.auth-cert% </format></access-log>
Enable "ssl" in http-listener, added server certificate nickname (if its different from "Server-Cert") and set client authentication as "required" :
<http-listener><name>http-listener-1</name><port>4444</port><server-name>test.sun.com</server-name><ssl><server-cert-nickname>Server-Cert-Reverse-Proxy-Server</server-cert-nickname><client-auth>required</client-auth></ssl><default-virtual-server-name>test</default-virtual-server-name></http-listener>
In server.xml I have also modified access log format so that we can see what is happening. This will slow down Web Server performance so do not do this in production environment.
<access-log><file>../logs/access</file><format>%Ses->client.ip% "%Req->reqpb.clf-request%" %Req->srvhdrs.clf-status% %Req->srvhdrs.content-length% %Ses->client.cipher% %Req->vars.auth-cert% %Req->headers.proxy-auth-cert%</format></access-log>
Created a test.html file that should be served when the client requests for it :
$cat ../docs/test.htmlThis is test.html on origin server
I used "tstclnt" which is bundled with NSS-NSPR binaries in bin directory. Note that I used the server certificate of reverse proxy server as client certificate because I am too lazy to create more certificates. In real world use a proper client certificate.
Created a test request file :
$cat > sslreq.datGET /test.html HTTP/1.0^M^M
Sent request to the reverse proxy server
$tstclnt -h test.sun.com -p 3333 -n Server-Cert-Reverse-Proxy-Server -d https-test/config -c n -v -o -f < sslreq.dattstclnt: connecting to test.sun.com:3333 (address=xxx.xxx.xxx.xxx)...tstclnt: stdin read 27 byteststclnt: Writing 27 bytes to servertstclnt: SSL version 3.1 using 128-bit RC4 with 160-bit SHA1 MACtstclnt: Server Auth: 1024-bit RSA, Key Exchange: 1024-bit RSAsubject DN: CN=test.sun.comissuer DN: CN=test.sun.com...tstclnt: Read from server 350 bytesHTTP/1.1 200 OKServer: Sun-Java-System-Web-Server/7.0Date: Fri, 18 Sep 2009 10:59:13 GMTContent-type: text/htmlLast-modified: Thu, 17 Sep 2009 10:44:10 GMTContent-length: 35Etag: "23-4ab212fa"Accept-ranges: bytesVia: 1.1 https-testProxy-agent: Sun-Java-System-Web-Server/7.0Connection: closeThis is test.html on origin server...
tstclnt: exiting with return code 0
You can see the request is being served from origin server.
I have used in this test client cipher "n" which is SSL3 RSA WITH RC4 128 SHA because I know this cipher that is enabled in Sun Web Server 7.0 update 6. I can
see that at the time of server startup when run in
<log-level>finest</log-level>. You can use other ciphers as well.
$cat ../logs/access format=%Ses->client.ip% "%Req->reqpb.clf-request%" %Req->srvhdrs.clf-status% %Req->srvhdrs.content-length% %Ses->client.cipher% %Req->vars.auth-cert% xxx.xxx.xxx.xxx "GET /test.html HTTP/1.0" 200 35 RC4 MIIBujCCASOgAwIBAgIFAI566gYwDQYJKo...fBqhD710VkFmOScYjWBxZe1vhnTbu/NexX4NqLsZG9So=Note cipher is RC4.
$cat ../logs/accessformat=%Ses->client.ip% "%Req->reqpb.clf-request%" %Req->srvhdrs.clf-status% %Req->srvhdrs.content-length% %Ses->client.cipher% %Req->vars.auth-cert% %Req->headers.proxy-auth-cert%xxx.xxx.xxx.xxx "GET /test.html HTTP/1.1" 200 35 RC4 MIIBujCCASOgAwIBAgIFAI566gYwDQYJKo...fBqhD710VkFmOScYjWBxZe1vhnTbu/NexX4NqLsZG9So= MIIBujCCASOgAwIBAgIFAI566gYwDQYJKo...fBqhD710VkFmOScYjWBxZe1vhnTbu/NexX4NqLsZG9So=Note that as expected in origin-server, rq->headers pblock has the certificate in "proxy-auth-cert". Reverse proxy server sends the certificate to origin server in this header.
Posted by meena ( Sep 18 2009, 05:32:56 PM IST ) Permalink Comments [0]
- Sun Java System Web Server 7.0 Update 6 Administrator's Configuration File Reference - "forward-auth-cert"
- Configuring Reverse Proxy in Sun Java System Web Server 7.0
- Configuring reverse proxy in Sun Java System Web Server 7.0 when origin server is SSL enabled
- About trust flags of certificates in NSS database that can be modified by certutil
- http://forums.sun.com/thread.jspa?threadID=5397719
- http://forums.sun.com/thread.jspa?threadID=5373182
- http://forums.sun.com/thread.jspa?threadID=5359313
Building Open Web Server on OpenSolaris SPARC
I tried building Open Web Server on OpenSolaris SPARC.
Install package as given in http://wikis.sun.com/display/wsFOSS/Checkout+and+Build+Instructions
SUNWmozldap, SUNWxercesc, SUNWxalanc in http://src.opensolaris.org/source/xref/webstack/ were probably not built for 64 bit. I have only tested on OpenSolaris x86 32 bit. They do not work on SPARC yet.
Run this script it builds and puts Mozilla LDAP C SDK and puts it in /usr/local/include/mozldap/, /usr/local/lib/mozldap, /usr/local/lib/mozldap/64
#!/bin/sh #building 32 bit
cd
cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -P -rLDAPCSDK_6_0_5_RTM DirectorySDKSourceCcd mozilla/directory/c-sdk./configure --with-sasl --with-nspr-inc=/usr/include/mps --with-nspr-lib=/usr/lib/mps --with-nspr --with-nss-inc=/usr/include/mps --with-nss-lib=/usr/lib/mps --with-nssgmakecd ../../dist/sudo mkdir -p /usr/local/include/mozldap /usr/local/lib/mozldapsudo cp public/ldap/* /usr/local/include/mozldap/sudo cp lib/* /usr/local/lib/mozldap/cdmv mozilla mozilla32#building 64 bitcvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -P -rLDAPCSDK_6_0_5_RTM DirectorySDKSourceCcd mozilla/directory/c-sdk./configure --with-sasl --with-nspr-inc=/usr/include/mps --with-nspr-lib=/usr/lib/mps/64 --with-nspr --with-nss-inc=/usr/include/mps --with-nss-lib=/usr/lib/mps/64 --with-nss --enable-64bitgmakecd ../../dist/sudo mkdir -p /usr/local/lib/mozldap/64sudo cp lib/* /usr/local/lib/mozldap/64cdmv mozilla mozilla64
Build Xerces C and Xalan C 32 bit and 64 bit and put it in /usr/local/ area.
Build Xerces C 2.6 from http://xerces.apache.org/xerces-c/build-2.html
Build Xalan C 1.9 from http://xml.apache.org/xalan-c/build_instruct.html
hg clone ssh://anon@hg.opensolaris.org/hg/webstack/webserver
gmake BUILD_VARIANT=OPTIMIZEDIf you want 64 bit support also
gmake BUILD_VARIANT=OPTIMIZED BUILD64=1
gmake BUILD_VARIANT=OPTIMIZED installIf you want 64 bit also
gmake BUILD_VARIANT=OPTIMIZED install BUILD64=1
Go to work/B1/*/https-test/config directory. To run Open Web Server in 64 bit you need to add <platform>64</platfrom> in server.xml "server" element.
If you get error that looks like
ld: fatal: file /usr/lib/64/libsqlite3.so: version `SQLITE_3' does not exist:
required by file /usr/lib/mps/64/libsoftokn3.so
$mv /usr/lib/64/libsqlite3.so /usr/lib/64/libsqlite3.so.BACK
http://wikis.sun.com/display/wsFOSS/Checkout+and+Build+Instructions
http://forums.sun.com/thread.jspa?messageID=10810336#10810336
Posted by meena ( Sep 08 2009, 06:38:35 PM IST ) Permalink Comments [0]Jython Web Application on Sun Web Server 7.0
Download Jython from http://softlayer.dl.sourceforge.net/project/jython/jython/2.5.0/jython_installer-2.5.0.jar
Run Jython installer and install it in lets say in /opt/jython/jython2.5.0
$java -jar jython_installer-2.5.0.jar
Lets try deploying a simple demo web application that comes along with this. This demo application has a simple demo_app.py script.
cd /opt/jython/jython2.5.0/Demo/modjy_webapp/WEB-INFPosted by meena ( Aug 07 2009, 01:30:37 PM IST ) Permalink Comments [0]
cp /opt/jython/jython2.5.0/jython.jar lib/
In web.xml change python.home i.e.
<init-param>
<param-name>python.home</param-name>
<param-value>C:/jython2.5</param-value>
</init-param>
to
<init-param>
<param-name>python.home</param-name>
<param-value>/opt/jython/jython2.5.0</param-value>
</init-param>
cd /ws7-install-dir/https-instance-name/config
Add in server.xml in virtual server element, the location of this web application<web-app> <uri>/modjy_webapp</uri> <path>/opt/jython/jython2.5.0/modjy_webapp</path> </web-app>Start the web server instance, and access the web application via browser using URI http://host:port/modjy_webapyou should see a page starting with the contents:
Python CGIs in Sun Web Server 7.0
Add this test script in <ws7-install-dir>https-<instance-name>/docs/cgi-bin directory and call it hello.cgi
#!/usr/bin/env pythonprint("Content-Type: text/plain;charset=utf-8")print("\r\n")print("Hello World!")
Change obj.conf default object
<Object name="default">AuthTrans fn="match-browser" browser="*MSIE*" ssl-unclean-shutdown="true"NameTrans fn="ntrans-j2ee" name="j2ee"NameTrans fn="pfx2dir" from="/cgi-bin" dir="/<ws-install-dir>/https-<instance-name>/docs/cgi-bin" name="cgi"...<Object name="cgi"> ObjectType fn="force-type" type="magnus-internal/cgi" Service fn="send-cgi" </Object>
Send a request through the browser http://host:post/cgi-bin/hello.cgi
You can see Hello World! displayed.
References
http://docs.python.org/3.1/howto/webservers.html
Running Open Web Server on FreeBSD
Downloaded Free BSD from ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/ISO-IMAGES/7.2/7.2-RELEASE-i386-dvd1.iso.gz
and installed it.
For reference, see http://wikis.sun.com/display/wsFOSS/Checkout+and+Build+Instructions
To search for a package, I used cd /usr/ports; make search name="mercurial" and so on.
First make sure that you already have these components
| GNU make 3.81 | /usr/local/bin/gmake |
| C/C++ Compiler 4.2.1 | /usr/bin/g++ and gcc |
| Zlib | /usr/lib/libz.so already installed |
| Perl 5.8.9 | /usr/bin/perl |
| CVS 1.11.22.1 | /usr/bin/cvs |
| Mercurial |
cd /usr/ports/devel/mercurial; make install |
|
Java SE 5 or 6 |
Due to license problems had to manually download and putting
it in /usr/ports/distfiles
|
| Ant | cd /usr/ports/devel/apache-ant; make install
|
| NSPR | cd /usr/ports/devel/nspr; make install |
| NSS | cd /usr/ports/security/nss; make install |
|
Xerces C++ |
cd
/usr/ports/textproc/xerces-c2; make install cd /usr/ports/textproc/xerces-c2-devel; make install selected Use ICU transcoder option. Build thread safe version of library. Got an error "/usr/bin/ld: can not find -lgcc_pic" For this we need to manually modify "files/filepatch-src-xercesc-Makefile.incl" and change "-lgcc_pic" to "-lgcc" |
|
Xalan C++ |
cd
/usr/ports/textproc/xalan; make install Selected INMEN and TRANSCODER_ICU options. |
| PCRE |
cd /usr/ports/devel/pcre; make install |
| ICU | cd /usr/ports/devel/icu; make install |
| SASL | cd /usr/ports/security/cyrus-sasl2; make install |
|
Mozilla C SDK* |
--with-sasl-lib=/usr/local/lib --with-nspr-lib=/usr/local/lib --with-nspr-inc=/usr/local/include/nspr/ --with-nspr --with-nss-lib=/usr/local/lib/nss --with-nss-inc=/usr/local/include/nss/nss/ --with-nss
|
*Note There is one /usr/ports/net/ldapsdk. It downloads and builds ldapsdk_12311998.tar.gz.
But I can see it in ancient now from mozilla site http://ftp.mozilla.org/pub/mozilla.org/directory/c-sdk/ancient/
So I built Mozilla C SDK myself.
One manual hack you need to do in "/usr/local/include/prinet.h"
#if defined(FREEBSD) || defined(BSDI) || defined(QNX)
#include <rpc/types.h> /* the only place that defines INADDR_LOOPBACK */
#endif
replace it by
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK (u_long)0x7F000001
#endif
Go to work/FreeBSD7.2-RELEASE_OPT.OBJ/https-test/bin/ directory and start the server instance using startserv script.
For the last two gmake commands, you can add WS_INSTALL_ROOT=/opt/ws if you want the server instance to be installed in /opt/ws/https-test
References:
This blog copyright 2009 by meena