Skip Headers
Oracle® Fusion Middleware WebLogic Tuxedo Connector Programmer's Guide for Oracle WebLogic Server
11g Release 1 (10.3.6)

Part Number E13723-05
Go to Documentation Home
Home
Go to Table of Contents
Contents
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

9 How to Create a Custom AppKey Plug-in

The following sections provide information about how to create custom AppKey generator plug-ins:

How to Create a Custom Plug-In

Note:

You cannot customize Oracle Tuxedo AAA tokens.
  1. Create your custom Java plug-in using the AppKey and UserRec interfaces. You can provide any required initialization parameters or a property file using the param parameter of the init method.

  2. Compile your plug-in. Example:

    javac exampleAppKey.java
    
  3. Update your CLASSPATH to include the path to your compiled plug-in. Example:

    export CLASSPATH=$CLASSPATH:/home/mywork
    
  4. Start your server.

  5. Configure your WTC Service to use the Custom Plug-in. For more information, see the "Custom Plug-in" in WebLogic Tuxedo Connector Administration Guide for Oracle WebLogic Server.

Example Custom Plug-in

The exampleAppKey.java file is an example of a custom plug-in. It utilizes a tpusrfile file as the database to store the AppKey.

Example 9-1 exampleAppKey.Java Custom Plug-In

import java.io.*;
import java.lang.*;
import java.util.*;
import java.security.Principal;
import weblogic.wtc.jatmi.AppKey;
import weblogic.wtc.jatmi.UserRec;
import weblogic.wtc.jatmi.DefaultUserRec;
import weblogic.wtc.jatmi.TPException;
import weblogic.security.acl.internal.AuthenticatedSubject;
import weblogic.security.WLSPrincipals;

/**
 * @author Copyright (c) 2002 by BEA Systems, Inc. All Rights Reserved.
 */

/**
 * @exclude
 * Sample AppKey plug-in using TPUSRFILE as the database for APPKEY.
 * It is installed through "Custom" option.
 * The syntax for option custom plug parameter input contains the full
 * pathname to the <tpusrfile> 
 *
 * @author BEA Systems, Inc.
 */
public class exampleAppKey implements AppKey {
  private String  anon_user = null;
  private String  tpusrfile = null;
  private File    myfile;
  private HashMap userMap;
  private long    l_time;
  private int     dfltAppkey;
  private boolean allowAnon;
  private final static int USRIDX = 0;
  private final static int PWDIDX = 1;
  private final static int UIDIDX = 2;
  private final static int GIDIDX = 3;
  private final static int CLTIDX = 4;

  private final static byte[] tpsysadm_string = {
    (byte)'t', (byte)'p', (byte)'s', (byte)'y', (byte)'s',
    (byte)'a', (byte)'d', (byte)'m' };
  private final static byte[] tpsysop_string = {
    (byte)'t', (byte)'p', (byte)'s', (byte)'y', (byte)'s', (byte)'o',
    (byte)'p' };
  
  public void init(String param, boolean anonAllowed, int dfltAppKey) 
    throws TPException {

    if (param == null) {
      System.out.println("Error: tpusrAppKey.init@param == null");
      throw new TPException(TPException.TPESYSTEM,
                            "Invalid input parameter");
    }

    // get the tpusrfile name
    parseParam(param);

    myfile  = new File(tpusrfile);
    if (myfile.exists() != true) {
      System.out.println("Error: exampleAppKey.init@file \"" + param
                         + "\" does not exist");
      throw new TPException(TPException.TPESYSTEM,
                            "Failed to find TPUSR file");
    }
    if (myfile.isFile() != true) {
      System.out.println("Error: exampleAppKey.init@the specified name \"" +
                         param + "\" is not a file");
      throw new TPException(TPException.TPESYSTEM,
                            "Invalid TPUSR file");
    }
    if (myfile.canRead() != true) {
      System.out.println("Error: exampleAppKey.init@file \"" + param +
                         "\" is not readable");
      throw new TPException(TPException.TPESYSTEM,
                            "Bad TPUSR file permission");
    }

    userMap = new HashMap();

    // create the cache
    if (createCache(tpusrfile) == -1) {
      System.out.println("Error: exampleAppkey.init@fail to create user cache");
      throw new TPException(TPException.TPESYSTEM,
                            "fail to create user cache");
    }

    l_time     = myfile.lastModified();
    anon_user  = weblogic.security.WLSPrincipals.getAnonymousUsername();
    allowAnon  = anonAllowed;
    dfltAppkey = dfltAppKey;

    System.out.println("exampleAppKey installed!");

    return;
  }

  public void uninit() throws TPException {
    if (userMap != null) {
      userMap.clear();
    }
    return;
  }

  public UserRec getTuxedoUserRecord(AuthenticatedSubject subj) {
    Object[] obj = subj.getPrincipals().toArray();
    if (obj == null || obj.length == 0) {
      // a subject without principals is an anonymous user
      if (allowAnon) {
        return new DefaultUserRec(anon_user, dfltAppkey);
      }
                System.out.println("Error: exampleAppKey.
                getTuxedoUserRecord@return " +
                         "anonymous user not allowed");
      return null;
    }

    // looping through all Principal names if necessary to get first user
    // name defined in tpuser file
    Principal user;
    String    username;
    int       key;
    UserRec   rec;

    for (int i = 0; i < obj.length; i++) {
      user     = (Principal)obj[i];
      username = user.getName();
      if (username.equals(anon_user)) {
        return new DefaultUserRec(anon_user, dfltAppkey);
      }
      if ((rec = (UserRec)userMap.get(username)) != null) {
        return rec;
      }
    }
    System.out.println("WARN: exampleAppKey.getTuxedoUserRecord@return " +
                       "null UserRec");
    return null;
  } 
      
  private int createCache(String fname) {
    FileInputStream fin;
    byte[]          line;

    try {
      fin = new FileInputStream(fname);

      while ((line = readOneLine(fin)) != null) {
        DefaultUserRec newUser = parseOneLine(line);
        if (newUser != null) {
          userMap.put(newUser.getRemoteUserName(), newUser);
        }
      }
      fin.close();
    }
    catch (FileNotFoundException fnfe) {
      System.out.println("Error: exampleAppKey.createCache@reason: " + fnfe);
      return -1;
    }
    catch (SecurityException se) {
      System.out.println("Error: exampleAppKey.createCache@reason: " + se);
      return -1;
    }
    catch (IOException ioe) {
      System.out.println("Error: exampleAppKey.createCache@reason: " + ioe);
      return -1;
    }
    catch (Exception e) {
      System.out.println("Error: exampleAppKey.createCache@reason: " + e);
      return -1;
    }
    return 0;
  }

  private byte[] readOneLine(FileInputStream fh) {
    int    len  = 80;
    byte[] line = new byte[len];
    int    inp  = -1;
    int    idx  = 0;

    try {
      while ((inp = fh.read()) != -1) {
        if (idx == 0 && (inp == '\n' || inp == '\0')) {
          continue;
        }
        if (inp == '\n') {
          break;
        }
        if (idx == (len - 1)) {
          byte[] tmp = new byte[len + 80];
          System.arraycopy(line, 0, tmp, 0, len);
          line = tmp;
          len += 80;
        }
        line[idx] = (byte)inp;
        idx++;
      }
    }
    catch (Exception e) {
      System.out.println("Error: exampleAppKey.readOneLine@reason: " + e);
      return null;
    }

    if (inp == -1 && idx == 0) {
      return null;
    }

    byte[] tmp = new byte[idx];
    System.arraycopy(line, 0, tmp, 0, idx);

    return tmp;
  }

  private DefaultUserRec parseOneLine(byte[] line) {
    String      name;
    int         key   = 0;
    DefaultUserRec usr;
    int         firstCharacter;
    int         i;
    int         sidx;
    int         fldlen;
    int         fn;
    byte[]      buid  = null;
    byte[]      bgid  = null;
    byte[]      clt   = null;
    byte[]      uname = null;

    firstCharacter = (int)line[0];
    if (firstCharacter == '#' || firstCharacter == '\n' ||
        firstCharacter == '!' || firstCharacter == '\0' ||
        firstCharacter == '\r') {
      return null;
    }
    fldlen = 0;
    sidx   = 0;
    for (i = 0, fn = 0; i < line.length && fn <= CLTIDX; i++) {
      if (line[i] == (byte)':') {
        switch (fn) {
        case USRIDX:
          uname = new byte[fldlen];
          System.arraycopy(line, sidx, uname, 0, fldlen);
          break;
        case UIDIDX:
          buid = new byte[fldlen];
          System.arraycopy(line, sidx, buid, 0, fldlen);
          break;
        case GIDIDX:
          bgid = new byte[fldlen];
          System.arraycopy(line, sidx, bgid, 0, fldlen);
          break;
        case CLTIDX:
                         if (line[sidx  ] == (byte)'T' &&
                                  line[sidx+1] == (byte)'P' &&
                                  line[sidx+2] == (byte)'C' &&
                                  line[sidx+3] == (byte)'L' &&
                                  line[sidx+4] == (byte)'T' &&
                                  line[sidx+5] == (byte)'N' &&
                                  line[sidx+6] == (byte)'M' &&
                                  line[sidx+7] == (byte)',') {
                                sidx   += 8;
                                fldlen -= 8;
                         }
          if (fldlen > 0) {
                                 clt = new byte[fldlen];
                                 System.arraycopy(line, sidx, clt, 0, fldlen);
          }
          break;
        default:
          break;
        }   // end of switch
        fn++;
        fldlen = 0;
        sidx   = i + 1;
      }     // end of if
      else {
        fldlen++;
      }
    }
    
    // try to tolerate incomplete line
    if (fn <= CLTIDX && fldlen > 0) {
                 switch (fn) {
                  case USRIDX:
                         uname = new byte[fldlen];
                         System.arraycopy(line, sidx, uname, 0, fldlen);
                         break;
                  case UIDIDX:
                         buid = new byte[fldlen];
                         System.arraycopy(line, sidx, buid, 0, fldlen);
                         break;
                  case GIDIDX:
                         bgid = new byte[fldlen];
                         System.arraycopy(line, sidx, bgid, 0, fldlen);
                         break;
                  case CLTIDX:
                         if (line[sidx  ] == (byte)'T' &&
                                  line[sidx+1] == (byte)'P' &&
                                  line[sidx+2] == (byte)'C' &&
                                  line[sidx+3] == (byte)'L' &&
                                  line[sidx+4] == (byte)'T' &&
                                  line[sidx+5] == (byte)'N' &&
                                  line[sidx+6] == (byte)'M' &&
                                  line[sidx+7] == (byte)',') {
                                sidx   += 8;
                                fldlen -= 8;
                         }
                         clt = new byte[fldlen];
                         System.arraycopy(line, sidx, clt, 0, fldlen);
                         break;
                 }
    }

    if (uname == null || buid == null || bgid == null) {
      return null;
    }

    name = new String(uname);
    if (clt != null) {
      if (Arrays.equals(tpsysadm_string, clt) == true) {
        key = TPSYSADM_KEY;
      }
      else if (Arrays.equals(tpsysop_string, clt) == true) {
        key = TPSYSOP_KEY;
      }
    }

    if (key == 0) {
      Integer u_val;
      Integer g_val;
      int uid = 0;
      int gid = 0;

      try {
        u_val = new Integer(new String(buid));
        g_val = new Integer(new String(bgid));
        uid   = u_val.intValue();
        gid   = g_val.intValue();
        uid &= UIDMASK;
        gid &= GIDMASK;
        key = uid | (gid << GIDSHIFT);
      }
      catch (NumberFormatException nfe) {
        System.out.println("Error: exampleAppKey.readOneLine@reason: " + nfe);
        return null;
      }
    }

    return new DefaultUserRec(name, key);
  }

  private void parseParam(String param) {
    String str;

    // trim the input
    tpusrfile = param.trim();

    return;
  }
}