Archive for September, 2010

Build mod_auth_kerb on AIX

September 6, 2010

As I needed kerberizing a component largely based on Kerberos Module for Apache, in order to make sure I could compile it properly, I needed first to get mod_auth_kerb compiled and setup properly on my platform, which was AIX 5.3.

Run configure for mod_auth_kerb

Following the installation guide for mod_auth_kerb, I was using the command:

./configure --with-krb5=/software/krb5-1.8.2/usr/local	\
            --with-krb4=no				\
            --with-apache=/software/apache-2.0.47

However, the configuration could not find Kerberos environment as shown in the configure output.

checking for gcc... no
checking for cc... cc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... no
checking whether cc accepts -g... yes
checking for cc option to accept ISO C89... -qlanglvl=extc89
checking whether make sets $(MAKE)... yes
checking for main in -lresolv... no
checking how to run the C preprocessor... cc -qlanglvl=extc89 -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking limits.h usability... yes
checking limits.h presence... yes
checking for limits.h... yes
checking netdb.h usability... yes
checking netdb.h presence... yes
checking for netdb.h... yes
checking stddef.h usability... yes
checking stddef.h presence... yes
checking for stddef.h... yes
checking for stdlib.h... (cached) yes
checking for string.h... (cached) yes
checking for unistd.h... (cached) yes
checking for size_t... yes
checking whether struct tm is in sys/time.h or time.h... time.h
checking gssapi.h usability... no
checking gssapi.h presence... no
checking for gssapi.h... no
checking gssapi/gssapi.h usability... no
checking gssapi/gssapi.h presence... no
checking for gssapi/gssapi.h... no
checking for krb5_init_context in -lkrb5... no
checking for krb5_init_context in -lkrb5... (cached) no
checking for krb5_init_context in -lkrb5... (cached) no
configure: error: No Kerberos enviroment found

Checking the config.log, the following was listed in it:

configure:3846: checking gssapi.h usability
configure:3863: cc -qlanglvl=extc89 -c -g  -I/usr/local/include conftest.c >&5
"conftest.c", line 57.10: 1506-296 (S) #include file  not found.
... ...

configure:3888: checking gssapi.h presence
configure:3903: cc -qlanglvl=extc89 -E  -I/usr/local/include conftest.c
"conftest.c", line 24.10: 1506-296 (S) #include file  not found.
... ...
configure:3998: checking gssapi/gssapi.h usability
configure:4015: cc -qlanglvl=extc89 -c -g  -I/usr/local/include conftest.c >&5
"conftest.c", line 57.10: 1506-296 (S) #include file  not found.
... ...
configure:4040: checking gssapi/gssapi.h presence
configure:4055: cc -qlanglvl=extc89 -E  -I/usr/local/include conftest.c
"conftest.c", line 24.10: 1506-296 (S) #include file  not found.
... ...
configure:4109: checking for gssapi/gssapi.h
configure:4118: result: no
configure:4142: checking for krb5_init_context in -lkrb5
configure:4177: cc -qlanglvl=extc89 -o conftest -g   conftest.c -lkrb5   \
        -L/usr/local/lib -blibpath:/usr/local/lib::/usr/lib:/lib -brtl \
        -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lpthreads  >&5
ld: 0706-006 Cannot find or open library file: -l krb5
        ld:open(): No such file or directory
ld: 0706-006 Cannot find or open library file: -l gssapi_krb5
        ld:open(): No such file or directory
ld: 0706-006 Cannot find or open library file: -l krb5
        ld:open(): No such file or directory
ld: 0706-006 Cannot find or open library file: -l k5crypto
        ld:open(): No such file or directory
ld: 0706-006 Cannot find or open library file: -l com_err
        ld:open(): No such file or directory

From the output, it showed the checking was just done by running a compiling of a file, conftest.c. Apparently the compiling directives did not include any possible Kerberos include folders or files. It seemed the configure could not take into account the paths passed from the command option, even with_krb5 was provided.

From the help of configure, it showed CPPFLAGS could be used as a way to provide additional preprocessor flags. Then I tried with the following:

./configure --with-krb5=/software/krb5-1.8.2/usr/local	\
            --with-krb4=no				\
            --with-apache=/software/apache-2.0.47      \
            CPPFLAGS=-I/software/krb5-1.8.2//src/include

However, the result of configure still showed no Kerberos environment found, but with a bit progress that the gssapi.h was available this time.

... ...
checking for size_t... yes
checking whether struct tm is in sys/time.h or time.h... time.h
checking gssapi.h usability... yes
checking gssapi.h presence... yes
checking for gssapi.h... yes
checking for krb5_init_context in -lkrb5... no
checking for krb5_init_context in -lkrb5... (cached) no
checking for krb5_init_context in -lkrb5... (cached) no
checking for krb5_init_context in -lkrb5... (cached) no
configure: error: No Kerberos enviroment found

Checking the file config.log, it still showed the error I saw with last run:

... ...
configure:4142: checking for krb5_init_context in -lkrb5
configure:4177: cc -qlanglvl=extc89 -o conftest -g \ 
        -I/software/krb5-1.8.2//src/include  \
        conftest.c -lkrb5 \
        -L/usr/local/lib -blibpath:/usr/local/lib::/usr/lib:/lib -brtl \
        -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lpthreads  >&5

ld: 0706-006 Cannot find or open library file: -l krb5
        ld:open(): No such file or directory
ld: 0706-006 Cannot find or open library file: -l gssapi_krb5
        ld:open(): No such file or directory
ld: 0706-006 Cannot find or open library file: -l krb5
        ld:open(): No such file or directory
ld: 0706-006 Cannot find or open library file: -l k5crypto
        ld:open(): No such file or directory
ld: 0706-006 Cannot find or open library file: -l com_err
        ld:open(): No such file or directory

From the experience to build MIT Kerberos on AIX, I already knew the way to fix the issue. So I tried the third configure option:

./configure --with-krb5=/software/krb5-1.8.2/usr/local	 \
            --with-krb4=no				 \
            --with-apache=/software/apache-2.0.47       \
            CPPFLAGS=-I/software/krb5-1.8.2/src/include \
            LDFLAGS="-brtl -L/software/krb5-1.8.2/src/lib"

This time the Kerberos environment was found and all the configuration passed.

... ...
checking for size_t... yes
checking whether struct tm is in sys/time.h or time.h... time.h
checking gssapi.h usability... yes
checking gssapi.h presence... yes
checking for gssapi.h... yes
checking for krb5_init_context in -lkrb5... yes
checking for krb5_cc_new_unique in -lkrb5... yes
checking whether we are using Heimdal... no
checking whether the GSSAPI libraries support SPNEGO... no
checking for apxs... /software/apache-2.0.47/bin/apxs
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged

Next step is run make for mod_auth_kerb with newly created Makefile from the configure running above.

Run make for mod_auth_kerb

The result was not as expected. It created tons of errors, mainly complaining header files were not found.

... ...
"src/mod_auth_kerb.c", line 90.10: 1506-296 (S) #include file  not found.
"src/mod_auth_kerb.c", line 94.12: 1506-296 (S) #include file  not found.
"src/mod_auth_kerb.c", line 95.12: 1506-296 (S) #include file  not found.
"src/mod_auth_kerb.c", line 96.12: 1506-296 (S) #include file  not found.
"spnegokrb5/spnegokrb5.h", line 12.12: 1506-296 (S) #include file  not found.
"spnegokrb5/spnegokrb5.h", line 23.1: 1506-166 (S) Definition of function OM_uint32 requires parentheses.
"spnegokrb5/spnegokrb5.h", line 23.29: 1506-276 (S) Syntax error: possible missing '{'?
"src/mod_auth_kerb.c", line 174.3: 1506-273 (E) Missing type in declaration of kerb_auth_config.
... ...

Checking the Makefile showed neither KRB5_CPPFLAGS nor KRB5_LDFLAGS contained the paths I patched for configure.

... ... 
KRB5_CPPFLAGS = -I/usr/local/include
KRB5_LDFLAGS = -L/usr/local/lib \
                -blibpath:/usr/local/lib::/usr/lib:/lib \ 
                -brtl -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lpthreads
... ... 

With the following two lines replacing the above two, the make ran successfully.

... ...
KRB5_CPPFLAGS = -I/software/krb5-1.8.2/usr/local/include
KRB5_LDFLAGS = -L/software/krb5-1.8.2/usr/local/lib \
                -blibpath:/usr/local/lib::/usr/lib:/lib \ 
                -brtl -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lpthreads
... ...

Run make install for mod_auth_kerb

With the modified Makefile, make install successfully created the module, mod_auth_kerb.so under /software/apache-2.0.47/modules. Following configuration guilde from Kerberos Module for Apache, the Apache server was configured with Kerberos authentication.

A tip to configure SPNEGO authentication with Windows 7

September 4, 2010

If you are using Tomcat or JBoss as web server to implement single sign-on (SSO) with SPNEGO, and notice SSO would work when using Internet Explorer (IE) from Windows XP or Windows 2003, but not from Windows 7, you may run into the issue of longer SPNEGO token created by Windows 7.

Tomcat has a configurable parameter, MaxHttpHeaderSize within Connector node from <Tomcat Root>\conf\server.xml to control the maximum size of the request and response HTTP header. If not specified, this attribute is set to 8192 (8 KB). After I added the parameter into my Tomcat instance with value of 16384, connections made from my Windows 7 worked.

Later I checked the base64 encoded SPNEGO tokens from several Windows versions, it showed various size of them.

---------------------------------------------------------
Platform                              Token Size
---------------------------------------------------------
Windows 2003 SR2                4624, 4636, 4648, 4656
---------------------------------------------------------
Windows XP SP3                  5708
---------------------------------------------------------
Windows 7                       6092, 6104
---------------------------------------------------------

Given the fact almost every web application has lots of cookies sent back and forth with each request, it could very easily surpass the default maximium length specified by Tomcat. Actually I think the issue could also exist for other web application servers as long as a similar limitation is set. If you are working with Windows 7, it would better increate the parameter anyway to avoid the problem.

Interestingly I noticed that the setting of MaxHttpHeaderSize did not create trouble for Firefox on all the Windows platforms I tested. Maybe Firefox handles the scenario differently from IE. Overall the support to SPNEGO from Firefox seems much stabler than IE.

Usability of Single Sign-on for Webtop with multiple repositories

September 4, 2010

With the SSO implemenation presented recently, I noticed two usability issues when working with multiple repositories.

The first one was that there was no way to establish a second SSO session. As Webtop browser tree is able to list available repositories running on the Content Server, when I tried to click one repository node from the browser tree, normal login page showed up. I was hoping a SSO session could be made for the second repository automatically.

The second one was that after logging off from a SSO session and trying the login back, it directly logged into a repository. What I expected was the login page to present me the option to select which repository to log in. Actually the repository selection option would be available if I cleared browser cookies and then started Webtop from scratch.

Interestingly, the solution using SpengoHttpFilter I initially presented did not bear those two issues. After carefully examining what SpengoHttpFilter did to avoid the first issue, I noticed actually it was benefited from caching SpnegoPrincipal into HttpSession. Following the same wisdom, I cached AcceptResult into ClientSessionState within KerberosSSOAuthenticationScheme::authenticate() after the SPNEGO token from user’s browser was confirmed. Next time when KerberosSSOAuthenticationScheme::authenticate() was called, ClientSessionState was checked to see if it contained the cached AcceptResult object, if yes, then the delegated credential for the user would be retrieved from AcceptResult and used to create a new SPNEGO token that can be passed to the authentication plug-in.

As for the second issue, the SpnegoHttpFilter approach did not provide much help. When tracing the running of KerberosSSOAuthenticationScheme::authenticate(), it revealed actually the reason for the second issue was that a repository name was somehow known to KerberosSSOAuthenticationScheme. It would never need to ask for which repository to connect to. After some searching, I found out the repository name was cached as entry “application.authentication.docbase” in the preference store. With a bit customization to LogOff component to reset the entry, the second issue was resolved as well.

public class MyLogoff extends Logoff 
{ 
  public void onInit(ArgumentList args) 
  {
    super.onInit(args);

    IPreferenceStore preferenceStore = PreferenceService.getPreferenceStore(); 
    preferenceStore.writeString("application.authentication.docbase", ""); 

    } 
}

Here is a related note about different authentication schemes. WDK development guide stated that:

Caution: The DFC session manager does not support mixed authentication schemes. For example, if the user logs into the first repository with a user principal login and logs into the second repository with a session login dialog, the second login attempt with thrown an exception.

Ironically, with the existence of the first issue, I could obtain access to the first repository with SSO and the second one with normal user name/password login. Even with my fix having the issue resolved, I still can make a connection to second respository with DocbaseLoginAuthenticationScheme, provided that the second repository does not support SSO or the client does not have a valid account to the repository.