How to install Documentum Developer Edition 6.6

August 28, 2011

The post is just working journal about steps I took to get the Developer Edition 6.6 up and running.

1. Downloaded the installer file from Documentum Developer Edition.

2. Extracted the zip file to a local temporary location.

3. Started the installer by running documentumSetup.exe, and then followed each window the installer showed.

4. After the installer finished the installation, a welcome page showed and listed links to DA, Webtop and Retention Policy Services Administrator.

5. Checked the system, 4 new Documentum related services were created in the system:
– Documentum Docbase Service documentum
– Documentum Docbroker Service Docbroker
– Documentum Java Method Server
– Documentum Master Service

6. The link to Webtop, DA, and Retention Policy Services Administrator worked well for the newly installed Documentum and repository.

As the newly created repository documentum was working as expected, then I tried to create a new repository with the developer edition. Here are several things I found out:

– The executable Server_Configuration_Program.exe found under C:\Documentum\product\6.6\install should be used for creating new repositories.

– The name of the Database Administrator was ‘sa’, and its password was ‘documentum-1′. The information is needed when using the bundled SQL server.

– During repository creation, the step of running headstart.ebs failed.

In its output file, it showed ‘Failed to update docbase config object’. Having checked the ebs source file, it seemed the variable FTVendorStr was still using ‘fast’ with 6.6. After I added the following line to force the Full-text indexing to use Lucene, the script went through.

FTVendorStr = "lucene"
   

References

Documentum Content Server Developer Edition

How to configure SSL for Tomcat?

July 31, 2011

The topic has been discussed many times by many people (see the references below). This post just documents what I did to use a Company Certifying Authority to configure SSL for Tomcat.

1. create a keystore file

c:\jdk1.6.0_21\bin\keytool -genkey -alias myalias -keystore mykeystore \
  -genkeypair -keyalg RSA -keysize 2048
Enter keystore password:
 Re-enter new password:
 What is your first and last name?
 [myhostname.mycompanyname.com]: myhostname.mycompanyname.com
 What is the name of your organizational unit?
 [Unknown]: ITS
 What is the name of your organization?
 [ITS]: MyComp Software, Inc
 What is the name of your City or Locality?
 [My City]: My City
 What is the name of your State or Province?
 [MyState]: MyState
 What is the two-letter country code for this unit?
 [US]: US
 Is CN=myhostname.mycompanyname.com, OU=ITS, O="MyComp Software, Inc", \
    L=My City, ST=MyState, C=US correct?
 [no]: yes
Enter key password for <myalias>
 (RETURN if same as keystore password):

The first and last name will be used to identify the server that would use the certificate. It has to be the server name you want users to identify the server.
The alias (myalias in the sample) can be anything that identifies the certificate. Just needs to make sure the later reference is consistent.

The result of above command will be a keystore file.

2. Generate a Certificate Signing Request (CSR) for the keystore created from last step

c:\jdk1.6.0_21\bin\keytool -certreq -alias myalias -keystore mykeystore \
    -keyalg  RSA -file mycertreq.csr
Enter keystore password:

Please note the usage of myalias, keystorename, and mycertreq.csr. The first two have to be the same from step 1. The latter can be named as you want.

The result of this step is the CSR file, mycertreq.csr.

3. verify the certificate request from VeriSign website:

Just copy and paste the file myertreq.csr into the enrollment form shown by CSR validator from Verisign (open the file in a text editor that does not add extra characters). The verification would check several parameters defined in CSR file. If everything is checked OK, then we can move to the next step.

Actually, the above three steps were documented in Certificate Signing Request (CSR) Generation Instructions- Tomcat.

4. Send the CSR file to the company Certifying Authority(CA) specialist and get it signed

The CA specialist would return two file, one is the company CA certificate file. Another is the signed certificate file for my CSR file created in last step.
Different companies may use different procedures for this. That’s what I have gone through.

5. Import the certificates

Now that you have your certificate you can import it into you local keystore.

Actually, there are several smaller steps involved:

a- Make a copy of the keystore file you created in step 1:
This is only for a backup. As you read further, the original keystore file will be changed when importing certificates to it. It’s better to make a copy in case you want to start all over again.

b-Import a Chain Certificate or Root Certificate into keystore:
Remember the two files I got from company CA, one is the company CA certificate file, say CompanyCA.crt.txt. First, we have to import it into the local keystore. Please note the alias used here is root.

c:\jdk1.6.0_21\bin\keytool -import -alias root -keystore mykeystore -trustcacerts -file CompanyCA.crt.txt
Enter keystore password:
Owner: CN=MyComp Certifying Authority, O=MyComp Software, L=My City, ST=MyState, C=US
Issuer: CN=MyComp Certifying Authority, O=MyComp Software, L=My City, ST=MyState, C=US
Serial number: 0
Valid from: Tue Dec 14 09:48:58 CST 2004 until: Tue Dec 31 09:48:58 CST 2024
Certificate fingerprints:
         MD5:  D7:1B:39:8A:1A:C9:40:89:1D:20:2E:CA:DE:EF:5A:C9
         SHA1: 48:48:98:9A:42:5A:52:44:EC:C4:FB:2E:4B:11:4A:32:60:49:41:4B
         Signature algorithm name: MD5withRSA
         Version: 3

Extensions:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: EB 74 BE 70 76 47 4A A0   D0 D8 9D 5F 68 EB E0 F3  .t.pvGJ...._h...
0010: 1E 36 AA A4                                        .6..
]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen:2147483647
]

#3: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: EB 74 BE 70 76 47 4A A0   D0 D8 9D 5F 68 EB E0 F3  .t.pvGJ...._h...
0010: 1E 36 AA A4                                        .6..
]

[CN=MyComp Certifying Authority, O=MyComp Software, L=My City, ST=MyState, C=US]
SerialNumber: [    00]
]

Trust this certificate? [no]:  yes
Certificate was added to keystore

c- Then we need importing the signed Certificate, myserver.crt.txt.

c:\jdk1.6.0_21\bin\keytool -import -alias myalias -keystore mykeystore -trustcacerts -file myserver.crt.txt
Enter keystore password:
Certificate reply was installed in keystore

Please note the usage of myalias, and mykeystore. Both are consistent from all previous steps.

d- You may want to check what inside the keystore is saved right now to get an idea about the results of importing certificates.

 
c:\jdk1.6.0_21\bin\keytool -list -keystore mykeystore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 2 entries

root, Nov 10, 2010, trustedCertEntry,
Certificate fingerprint (MD5): D7:1B:39:8A:1A:C9:40:89:1D:20:2E:CA:DE:EF:5A:C9
myalias, Nov 10, 2010, PrivateKeyEntry,
Certificate fingerprint (MD5): A8:C5:37:7B:78:2D:A9:95:1E:62:8E:1B:9E:82:CE:17

6. Edit the Tomcat Configuration File

This is the last step for the configuration. SSL Configuration How to has detailed explanation and steps to do that. Here is my configuration for Tomcat 6.x.

 
<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector protocol="org.apache.coyote.http11.Http11Protocol"
           port="8443" maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="${user.home}/mykeystore" keystorePass="changeit"
           clientAuth="false" sslProtocol="TLS"/>

Please note the location of mykeystore and the usage of keystore password.

Then you can start Tomcat to get HTTPS supported from Tomcat for your web applications.

Reference:

Certificate Signing Request (CSR) Generation Instructions- Tomcat
SSL Checker
Apache 2 with SSL/TLS: Step-by-Step
A Simple Step-By-Step Guide To Apache Tomcat SSL Configuration
Set up secure web service with Tomcat and Apache

Documentum vs FileNet P8, underlying DB table management

July 23, 2011

It’s been a while since working with FileNet P8 (v4.5), and I have observed very interesting differences regarding how to manage underlying DB tables from Documentum and FileNet P8.

In Documentum, each type would usually have two DB tables created to record single and repeating attributes, <object type name>_s for single attributes and <object type name>_r for repeating ones. Many types are sub-types of dm_sysobject. In order to get all the attributes defined for a particular type that was sub-types of others, many pair of  xxx_s and xxx_r tables need to be consulted.

In FileNet, Document (one of several main Document classes) is acting like dm_sysobject in Documentum as the main super class. Document and all its sub-Document classes share ONE DB table, DOCVERSION. All the attributes of Document and its sub classes are defined as columns in DOCVERSION.  The custom column name from DOCVERION is in the format of U<xxx>_<property name>, where <xxx> is a hexadecimal representation string of  the sequential number of the attribute, <property name> is the property name given to the particular Document class.

Based on the above observation, here are some interesting topics regarding the underlying DB for FileNet:

- What if different Document Classes have same attribute defined? How the column is defined in DOCVERSION?

If Document Class A has attrA defined with one type of Property, say String,  and Document Class B also has AttrA defined by with a different type of Property, say Integer, what the system would treat the attributes, AttrA for Document Class A and B?

- How the Document Class inheritance relationship is defined?

- How are the versions of the same record defined and implemented?

Documentum system employed a complicated schema to define and create the underlying DB tables to support object type definition, which results in many tables for a system. However, FileNet P8 only uses one table to hold almost all the data, when retrieving the properties with Content Engine (CE) API, many subtle procedures are needed to locate the proper record and column from the table, DocVersion.

If you want to know more about the comparison between FileNet and Documentum, here are some wonderful discussions:

Filenet P8 vs. Documentum, a comparison
Documentum and FileNet – users and groups

How to obtain and authenticate Kerberos and SPNEGO tokens with JGSS

October 16, 2010

When working on solutions using Kerberos/SPENGO to achieve user authentication, one side of the equation is for the client to obtain Kerberos/SPNEGO token from KDC. The another side is for the server (also called service provider) to authenticate the token presented by the client.

Probably the most familiar client application is web browsers, such as Misrosoft Internet Explorer (IE) and Firefox. Both could obtain SPNEGO token from KDC on the login user’s behalf and send it to a web server when negotiation authentication is triggered (when the browser receives HTTP request header, authentication : negatiate). As for the server side implementation, mod_auth_kerb may be one of the most discussed solutions dealing with SPNEGO token.

In order to easily verify SPNEGO-based user authentication solutions, many times I felt the need to get SPNEGO/Kerberos tokens created for the clients and then verified by the servers. Here are two Java programs to address the need, TokenCreation and TokenConsumption.

The setup

You may refer to Kerberos setup for ways to get kerberso configured properly. The configuration file, bcsLogin.conf used by the code is as following:

/**
 * Login Configuration for JAAS.
 */

com.sun.security.jgss.initiate {
  com.sun.security.auth.module.Krb5LoginModule required
  	debug=true
	useTicketCache=true
	principal="mypersonal";
};

com.sun.security.jgss.accept {
  com.sun.security.auth.module.Krb5LoginModule required storeKey=true
  	debug=true
  	useKeyTab=true
  	storeKey=true
  	keyTab=mykeytab.keytab
  	principal="HTTP/myserver.mycorp.com"
	isInitiator=false;
};

The usage of the program

The usage of the two program is very simple. TokenCreation would create either Kerberos or SPNEGO token for the user. The token will be also output in Base64 encoded format. TokenConsumption will take the token created by TokenCreation and authenticate to resolve who the client is.

TokenCreation

import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;

import sun.misc.BASE64Encoder;
import org.apache.commons.codec.binary.Base64; 

public class TokenCreation {

    public static GSSCredential createCredential(Oid mechOid, String userName)
    {
        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
        System.setProperty("java.security.auth.login.config", "bcsLogin.conf");

        GSSCredential clientGssCreds = null;
        try {
            GSSManager manager = GSSManager.getInstance();

            GSSName gssUserName = manager.createName(
                    userName,
                    GSSName.NT_USER_NAME,
                    mechOid);

            clientGssCreds = manager.createCredential(
                    gssUserName.canonicalize(mechOid),
                    GSSCredential.INDEFINITE_LIFETIME,
                    mechOid,
                    GSSCredential.INITIATE_ONLY);

        } catch (GSSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return clientGssCreds;
    }

    /**
     *
     * @param sUserName
     * @param sServerSpn
     * @param sTokenType
     * @return
     */
    public static void createToken(String sUserName, String sServerSpn, String sTokenType)
    {
        try {
            Oid mechOid = null;
            if (sTokenType.compareTo("krb5") == 0) {
                mechOid = new Oid("1.2.840.113554.1.2.2");
            } else {
                if (sTokenType.compareTo("spnego") == 0) {
                    mechOid = new Oid("1.3.6.1.5.5.2");
                } else {
                    System.out.println("Token type [" + sTokenType + "] was not supported.");
                    System.out.println("Usage: java TokenCreation krb5 | spnego");
                }
            }
            if (mechOid != null) {
                GSSCredential gsscredential = createCredential(mechOid, sUserName);

                if (gsscredential != null) {
                    byte[] token = createToken(gsscredential, sServerSpn, mechOid);

                    if (token != null) {
                        outputToken(token, sTokenType);
                    }
                }
            }

        } catch (GSSException e) {
            e.printStackTrace();
        }

    }

    public static byte[] createToken(GSSCredential clientGssCreds,
            String sServerSpn, Oid mechOid)
    {
        byte[] token = new byte[0];
        try {
            GSSManager manager = GSSManager.getInstance();

            // create target server SPN
            GSSName gssServerName = manager.createName(
                    sServerSpn,
                    GSSName.NT_USER_NAME);

            GSSContext clientContext = manager.createContext(
                    gssServerName.canonicalize(mechOid),
                    mechOid,
                    clientGssCreds,
                    GSSContext.DEFAULT_LIFETIME);

            // optional enable GSS credential delegation
            clientContext.requestCredDeleg(true);

            // create a SPNEGO token for the target server
            token = clientContext.initSecContext(token, 0, token.length);

        } catch (GSSException e) {
            e.printStackTrace();
        }
        return token;
    }

    public static void outputToken(byte[] token, String sType)
    {
        if (token != null) {
            System.out.println("Token Length = " + token.length);

            Hexdump.hexdump(System.out, token, 0, token.length);
            FileUtil.writeByte2File(token, sType + "_token.txt");

            BASE64Encoder encoder = new BASE64Encoder();
            String encodedToken = encoder.encode( token);
            System.out.println("Token Base64 = \n" + encodedToken);

            Base64 base64 = new Base64(0);
            String encodedToken2 = base64.encodeToString(token);
            FileUtil.writeByte2File(encodedToken2.getBytes(), sType + "_token_64.txt");
        }
    }

    private static final String getHexBytes(byte[] bytes, int pos, int len)
    {
        StringBuffer sb = new StringBuffer();
        for (int i = pos; i >4) & 0x0f;
            int b2 = bytes[i] & 0x0f;

            sb.append(Integer.toHexString(b1));
            sb.append(Integer.toHexString(b2));
            sb.append(' ');
        }
        return sb.toString();
        }

        private static final String getHexBytes(byte[] bytes) {
        return getHexBytes(bytes, 0, bytes.length);
    }

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        String sServerSpn = "HTTP/myserver.mycorp.com";

        if (args.length < 1) {
            System.out.println("Usage: java TokenCreation krb5 | spnego");
        } else {
            if (args[0].compareTo("krb5") == 0 || args[0].compareTo("spnego") == 0) {
                TokenCreation.createToken("mypersonal", sServerSpn, args[0]);
                System.out.println("\n\nToken file [" + args[0] + "_token.txt] was created");
            } else {
                System.out.println("Usage: java TokenCreation krb5 | spnego");
            }
        }
    }

}

TokenConsumption

import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;

import org.apache.commons.codec.binary.Base64; 

/**
 * @author Allen
 *
 */
public class TokenConsumption {

    public static void consumeToken(byte[] token, String sTokenType)
    {
        try {
            Oid mechOid = null;
            if (sTokenType.compareTo("krb5") == 0) {
                mechOid = new Oid("1.2.840.113554.1.2.2");
            } else {
                if (sTokenType.compareTo("spnego") == 0) {
                    mechOid = new Oid("1.3.6.1.5.5.2");
                } else {
                    System.out.println("Token type [" + sTokenType + "] was not supported.");
                    System.out.println("Usage: java TokenCreation krb5 | spnego");
                }
            }
            if (mechOid != null) {
                consumeToken(token, mechOid);
            }

        } catch (GSSException e) {
            e.printStackTrace();
        }

    }

    public static void consumeToken(byte[] token, Oid mechOid)
    {
        String endpointSPN = null;

        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
        System.setProperty("java.security.auth.login.config", "bcsLogin.conf");

        try {
            GSSManager manager = GSSManager.getInstance();

            //first obtain it's own credentials...
            GSSCredential myCred = manager.createCredential(null,
                  GSSCredential.DEFAULT_LIFETIME,
                  mechOid,
                  GSSCredential.ACCEPT_ONLY);

            //...and create a context for this credentials...
            GSSContext context = manager.createContext(myCred);

            //...then use that context to authenticate the calling peer by reading his token
            byte[] tokenForPeer = context.acceptSecContext(token, 0, token.length);

            if (!context.isEstablished()) {
              System.out.println("Context was not established!");
              return;
          }

          if (tokenForPeer != null) {
              System.out.println("there is a token to send back to the peer, but I leave this out for now");
              Hexdump.hexdump(System.out, tokenForPeer, 0, tokenForPeer.length);
          }

          //...then obtain information from the context
          System.out.println("Client principal is " + context.getSrcName());
          System.out.println("Server principal is " + context.getTargName());

          if (context.getCredDelegState()) {
              System.out.println("The token is delegatable.");
          } else {
              System.out.println("The token is NOT delegatable");
          }

        } catch (GSSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        if ( args.length < 1 ||
                ( args[0].compareTo("krb5") != 0 && args[0].compareTo("spnego") != 0) ) {
            System.out.println("Usage: java TokenConsumption krb5 | spnego [64]");
        } else {
            if (args.length == 2) {
                if (args[1].compareTo("64") == 0) {
                    System.out.println("\n\n *** Token file [" + args[0] + "_token_64.txt] will be consumed *** \n\n");
                    byte[] token64 = FileUtil.readByteFromFile(args[0] + "_token_64.txt");
                    byte[] token = Base64.decodeBase64(token64);
                    TokenConsumption.consumeToken(token, args[0]);
                }
            } else {
                // process normal token from the file
                System.out.println("\n\n *** Token file [" + args[0] + "_token.txt] will be consumed *** \n\n");
                TokenConsumption.consumeToken(FileUtil.readByteFromFile(args[0] + "_token.txt"), args[0]);
            }
        }
    }
    }
}

FileUtil.java

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class FileUtil {
    public static void writeByte2File(byte bytes[], String strFilePath)
    {
        try {
            FileOutputStream fos = new FileOutputStream(strFilePath);
            fos.write(bytes);
            fos.close();
        } catch (FileNotFoundException ex) {
            System.out.println("FileNotFoundException : " + ex);
        } catch (IOException ioe) {
            System.out.println("IOException : " + ioe);
        }
    }

    public static byte[] readByteFromFile(String strFilePath)
    {
        byte[] bytes = null;
        try {
           File file = new File(strFilePath);
           InputStream is = new FileInputStream(file);
           DataInputStream dis = new DataInputStream(is);
           long length = file.length();
           if (length > Integer.MAX_VALUE) {
              throw new IOException("File is too large");
           } else {
              bytes = new byte[(int)length];
              int offset = 0;
              int numRead = 0;
              while (offset = 0) {
                 offset += numRead;
              }
              if (offset < bytes.length) {
                 throw new IOException("Could not completely read file "+file.getName());
              }
              dis.close();
              is.close();
           }
        } catch (Exception e) {
           e.printStackTrace();
        }
        return bytes;
    }
}

Hexdump.java

Hexdump from Souce code for Hexdump.java was also used in the programs with a bit change to remove the package definition to make it simpler to test.

Codec from Apache commons was used to encode and decode the Base64 string.

References

The Jave Monkey Client/Server Hello World in Kerberos, Java and GSS!
Creating SPNEGO tokens

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.


Follow

Get every new post delivered to your Inbox.