% $Id: sas.tex,v 1.6 2004-02-16 11:01:40 gerald Exp $

The Security Attribute Service (SAS) is part of the Common Secure 
Interoperability Specification, Version 2 (CSIv2) CORBA specification.
It is defined in the Secure Interoperability chapter (chapter 24) of the
CORBA 3.0.2 Specification.

\section{Overview}

The SAS specification defines the interchange between a Client Security 
Service (CSS) and a Target Security Service (TSS)
for the exchange of security authentication and authorization
elements. This information is exchanged in the Service Context of the GIOP
request and reply messages. The SAS may be used in conjunction with SSL to
provide privacy of the messages being sent and received.

The SAS service is implemented as a series of standard CORBA interceptors,
one for the CSS and one for the TSS. The service also uses a user specified
SAS context class to support different authentication mechanisms, such as
GSSUP and Kerberos.

The SAS service is activated based on entries in the JacORB properties file
and CORBA Properties assigned to the POA.

The following is a part of the JacORB properties file that is used by 
the SAS.

\begin{scriptsize}
\begin{verbatim}

########################################
#                                      #
#   SAS configuration                  #
#                                      #
########################################

jacorb.SAS.log.verbosity=INFO
jacorb.SAS.CSS.log.verbosity=INFO
jacorb.SAS.TSS.log.verbosity=INFO

# This option defines the specific SAS context generator/validator
# Currently supported contexts include:
#    GssUpContext      - Uses GSSUP security
#    KerberosContext   - uses Kerberos security
# At least one context must be selected for SAS support
jacorb.security.sas.contextClass=org.jacorb.security.sas.GssUpContext
#jacorb.security.sas.contextClass=org.jacorb.security.sas.KerberosContext

# This initializer installs the SAS interceptors
# Comment out this line if you do not want SAS support
org.omg.PortableInterceptor.ORBInitializerClass.SAS=org.jacorb.security.sas.SASInitializer

# This option is used for GSSUP security and sets up the GSS Provider
# Comment out this line if you are not using GSS UP authentication
org.omg.PortableInterceptor.ORBInitializerClass.GSSUPProvider=org.jacorb.security.sas.GSSUPProviderInitializer
\end{verbatim}
\end{scriptsize}


\section{GSSUP Example}

The GSSUP (GSS Username/Password) example demonstrates the simplest 
usage of the SAS service. In this example, username and password
pairs are send via the SAS service. The client registers its username
and password with the GSSUP Context which is later used CSS interceptor
to generate the user's authentication information.
The TSS retrieves the username and password
without validating them. It is assumed by the TSS that the username
and password are correct and/or will be further validated by a later
interceptor or application code.

The following describes a SAS example using GSSUP.

\subsection{GSSUP IDL Example}

\begin{scriptsize}
\begin{verbatim}
module demo{
  module sas{
    interface SASDemo{
      void printSAS();
    };
  };
};
\end{verbatim}
\end{scriptsize}

The IDL contains a single interface. This interface is used to print out
the user principal sent and received by the SAS service.

\subsection{GSSUP Client Example}

The following is a sample GSSUP client.

\begin{scriptsize}
\begin{verbatim}
package demo.sas;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

import org.jacorb.security.sas.GssUpContext;
import org.omg.CORBA.ORB;

public class GssUpClient {
        public static void main(String args[]) {
                if (args.length != 3) {
                        System.out.println("Usage: java demo.sas.GssUpClient <ior_file> <username> <password>");
                        System.exit(1);
                }

                try {
                        // set security credentials
                        GssUpContext.setUsernamePassword(args[1], args[2]);

                        // initialize the ORB.
                        ORB orb = ORB.init(args, null);

                        // get the server
                        File f = new File(args[0]);
                        if (!f.exists()) {
                                System.out.println("File " + args[0] + " does not exist.");
                                System.exit(-1);
                        }
                        if (f.isDirectory()) {
                                System.out.println("File " + args[0] + " is a directory.");
                                System.exit(-1);
                        }
                        BufferedReader br = new BufferedReader(new FileReader(f));
                        org.omg.CORBA.Object obj = orb.string_to_object(br.readLine());
                        br.close();
                        SASDemo demo = SASDemoHelper.narrow(obj);

                        //call single operation
                        demo.printSAS();
                        demo.printSAS();
                        demo.printSAS();

                        System.out.println("Call to server succeeded");
                } catch (Exception ex) {
                        ex.printStackTrace();
                }
        }
}
\end{verbatim}
\end{scriptsize}

The key to the client is the call to:
\begin{scriptsize}
\begin{verbatim}
    GssUpContext.setUsernamePassword(args[1], args[2]);
\end{verbatim}
\end{scriptsize}
This call registers the client's username and password with the GSSUP context.
This information will then later be used by the CSS interceptor as the user's
authentication information.

\subsection{GSSUP Target Example}

The following is a sample GSSUP target.

\begin{scriptsize}
\begin{verbatim}
package demo.sas;

import java.io.FileWriter;
import java.io.PrintWriter;

import org.jacorb.sasPolicy.SASPolicyValues;
import org.jacorb.sasPolicy.SAS_POLICY_TYPE;
import org.jacorb.sasPolicy.SASPolicyValuesHelper;
import org.omg.PortableServer.IdAssignmentPolicyValue;
import org.omg.PortableServer.LifespanPolicyValue;
import org.omg.PortableServer.POA;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Any;
import org.omg.CSIIOP.EstablishTrustInClient;

public class GssUpServer extends SASDemoPOA {

        private ORB orb;

        public GssUpServer(ORB orb) {
                this.orb = orb;
        }

        public void printSAS() {
                try {
                        org.omg.PortableInterceptor.Current current = (org.omg.PortableInterceptor.Current)orb.resolve_initial_references("PICurrent");
                        org.omg.CORBA.Any anyName = current.get_slot(org.jacorb.security.sas.SASInitializer.sasPrincipalNamePIC);
                        if( anyName.type().kind().value() == org.omg.CORBA.TCKind._tk_null ) {
                                System.out.println("Null Name");
                        } else {
                                String name = anyName.extract_string();
                                System.out.println("printSAS for user " + name);
                        }
                } catch (Exception e) {
                        System.out.println("printSAS Error: " + e);
                }
        }

        public static void main(String[] args) {
                if (args.length != 1) {
                        System.out.println("Usage: java demo.sas.GssUpServer <ior_file>");
                        System.exit(-1);
                }

                try {
                        // initialize the ORB and POA.
                        ORB orb = ORB.init(args, null);
                        POA rootPOA = (POA) orb.resolve_initial_references("RootPOA");
                        org.omg.CORBA.Policy [] policies = new org.omg.CORBA.Policy[3];
                        policies[0] = rootPOA.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID);
                        policies[1] = rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT);
                        Any sasAny = orb.create_any();
                        SASPolicyValuesHelper.insert( sasAny, new SASPolicyValues(EstablishTrustInClient.value, EstablishTrustInClient.value, true) );
                        policies[2] = orb.create_policy(SAS_POLICY_TYPE.value, sasAny);
                        POA securePOA = rootPOA.create_POA("SecurePOA", rootPOA.the_POAManager(), policies);
                        rootPOA.the_POAManager().activate();
                        
                        // create object and write out IOR
                        GssUpServer server = new GssUpServer(orb);
                        securePOA.activate_object_with_id("SecureObject".getBytes(), server);
                        org.omg.CORBA.Object demo = securePOA.servant_to_reference(server);
                        PrintWriter pw = new PrintWriter(new FileWriter(args[0]));
                        pw.println(orb.object_to_string(demo));
                        pw.flush();
                        pw.close();
                        
                        // run the ORB
                        orb.run();
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }
}
\end{verbatim}
\end{scriptsize}

\section{Kerberos Example}

The Kerberos example demonstrates how to integrate the use of a kerberos
service to provide authentication credentials to the SAS service. 
In this example, the Java(TM) Authentication and Authorization Service (JAAS)
is used to perform the Kerberos login
and to return the principal and Kerberos ticket.
The actual username and password may either be entered by the user
or derived from the current user's Kerberos login session.
For Windows 2000 Active Directory networks, this means that the user's
credentials can be automatically obtained from the Windows login.

The following describes a SAS example using Kerberos.

\subsection{Kerberos IDL Example}

\begin{scriptsize}
\begin{verbatim}
module demo{
  module sas{
    interface SASDemo{
      void printSAS();
    };
  };
};
\end{verbatim}
\end{scriptsize}

The IDL contains a single interface. This interface is used to print out
the user principal sent and received by the SAS service.

\subsection{Kerberos Client Example}

The following is a sample Kerberos client.

\begin{scriptsize}
\begin{verbatim}
package demo.sas;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.security.Principal;
import java.security.PrivilegedAction;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.omg.CORBA.ORB;

public class KerberosClient {
        private static Principal myPrincipal = null; 
        private static Subject mySubject = null;        
        private static ORB orb = null;
        
        public KerberosClient(String args[]) {

                try {
                        // initialize the ORB.
                        orb = ORB.init(args, null);

                        // get the server
                        File f = new File(args[0]);
                        if (!f.exists()) {
                                System.out.println("File " + args[0] + " does not exist.");
                                System.exit(-1);
                        }
                        if (f.isDirectory()) {
                                System.out.println("File " + args[0] + " is a directory.");
                                System.exit(-1);
                        }
                        BufferedReader br = new BufferedReader(new FileReader(f));
                        org.omg.CORBA.Object obj = orb.string_to_object(br.readLine());
                        br.close();
                        SASDemo demo = SASDemoHelper.narrow(obj);

                        //call single operation
                        demo.printSAS();
                        demo.printSAS();
                        demo.printSAS();

                        System.out.println("Call to server succeeded");
                } catch (Exception ex) {
                        ex.printStackTrace();
                }
        }
        
        public static void main(String args[]) {
                if (args.length != 3) {
                        System.out.println("Usage: java demo.sas.KerberosClient <ior_file> <username> <password>");
                        System.exit(1);
                }

                // login - with Kerberos
                LoginContext loginContext = null;
                try {
                        JaasTxtCalbackHandler txtHandler = new JaasTxtCalbackHandler();
                        txtHandler.setMyUsername(args[1]);
                        txtHandler.setMyPassword(args[2].toCharArray());
                        loginContext = new LoginContext("KerberosClient", txtHandler);
                        loginContext.login();
                } catch (LoginException le) {
                        System.out.println("Login error: " + le);
                        System.exit(1);
                }
                mySubject = loginContext.getSubject();
                myPrincipal = (Principal) mySubject.getPrincipals().iterator().next();
                System.out.println("Found principal " + myPrincipal.getName());

                // run in privileged mode
                final String[] finalArgs = args;
                try {
                        Subject.doAs(mySubject, new PrivilegedAction() {
                                public Object run() {
                                        try {
                                                KerberosClient client = new KerberosClient(finalArgs);
                                                orb.run();
                                        } catch (Exception e) {
                                                System.out.println("Error running program: "+e);
                                        }
                                        System.out.println("Exiting privileged operation");
                                        return null;
                                }
                        });
                } catch (Exception e) {
                        System.out.println("Error running privileged: "+e);
                }
        }
}
\end{verbatim}
\end{scriptsize}

The CSS uses JAAS to logon and return the user's Kerberos credentials.
The CSS must then run the rest of the application as a PrivilegedAction using
the logged on credentials. This allows the CSS interceptor to retrieve the
Kerberos ticket from the logon session.

The following is the JAAS logon configuration for the CSS:

\begin{scriptsize}
\begin{verbatim}
KerberosClient 
{
    com.sun.security.auth.module.Krb5LoginModule required storeKey=true useTicketCache=true debug=true;
};
\end{verbatim}
\end{scriptsize}


\subsection{Kerberos Target Example}

The following is a sample Kerberos target.

\begin{scriptsize}
\begin{verbatim}
package demo.sas;

import java.io.FileWriter;
import java.io.PrintWriter;
import java.security.Principal;
import java.security.PrivilegedAction;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.jacorb.sasPolicy.SASPolicyValues;
import org.jacorb.sasPolicy.SAS_POLICY_TYPE;
import org.jacorb.sasPolicy.SASPolicyValuesHelper;
import org.omg.PortableServer.IdAssignmentPolicyValue;
import org.omg.PortableServer.LifespanPolicyValue;
import org.omg.PortableServer.POA;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Any;
import org.omg.CSIIOP.EstablishTrustInClient;

public class KerberosServer extends SASDemoPOA {
        private static Principal myPrincipal = null; 
        private static Subject mySubject = null;        
        private ORB orb;

        public KerberosServer(ORB orb) {
                this.orb = orb;
        }

        public void printSAS() {
                try {
                        org.omg.PortableInterceptor.Current current = (org.omg.PortableInterceptor.Current) orb.resolve_initial_references("PICurrent");
                        org.omg.CORBA.Any anyName = current.get_slot(org.jacorb.security.sas.SASInitializer.sasPrincipalNamePIC);
                        String name = anyName.extract_string();
                        System.out.println("printSAS for user " + name);
                } catch (Exception e) {
                        System.out.println("printSAS Error: " + e);
                }
        }
        
        public KerberosServer(String[] args) {
                try {
                        // initialize the ORB and POA.
                        orb = ORB.init(args, null);
                        POA rootPOA = (POA) orb.resolve_initial_references("RootPOA");
                        org.omg.CORBA.Policy [] policies = new org.omg.CORBA.Policy[3];
                        policies[0] = rootPOA.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID);
                        policies[1] = rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT);
                        Any sasAny = orb.create_any();
                        SASPolicyValuesHelper.insert( sasAny, new SASPolicyValues(EstablishTrustInClient.value, EstablishTrustInClient.value, true) );
                        policies[2] = orb.create_policy(SAS_POLICY_TYPE.value, sasAny);
                        POA securePOA = rootPOA.create_POA("SecurePOA", rootPOA.the_POAManager(), policies);
                        rootPOA.the_POAManager().activate();
                        
                        // create object and write out IOR
                        securePOA.activate_object_with_id("SecureObject".getBytes(), this);
                        org.omg.CORBA.Object demo = securePOA.servant_to_reference(this);
                        PrintWriter pw = new PrintWriter(new FileWriter(args[0]));
                        pw.println(orb.object_to_string(demo));
                        pw.flush();
                        pw.close();
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }

        public static void main(String[] args) {
                if (args.length != 2) {
                        System.out.println("Usage: java demo.sas.KerberosServer <ior_file> <password>");
                        System.exit(-1);
                }

                // login - with Kerberos
                LoginContext loginContext = null;
                try {
                        JaasTxtCalbackHandler cbHandler = new JaasTxtCalbackHandler();
                        cbHandler.setMyPassword(args[1].toCharArray());
                        loginContext = new LoginContext("KerberosService", cbHandler);
                        loginContext.login();
                } catch (LoginException le) {
                        System.out.println("Login error: " + le);
                        System.exit(1);
                }
                mySubject = loginContext.getSubject();
                myPrincipal = (Principal) mySubject.getPrincipals().iterator().next();
                System.out.println("Found principal " + myPrincipal.getName());

                // run in privileged mode
                final String[] finalArgs = args;
                try {
                        Subject.doAs(mySubject, new PrivilegedAction() {
                                public Object run() {
                                        try {
                                                // create application
                                                KerberosServer app = new KerberosServer(finalArgs);
                                                app.orb.run();
                                        } catch (Exception e) {
                                                System.out.println("Error running program: "+e);
                                        }
                                        return null;
                                }
                        });
                } catch (Exception e) {
                        System.out.println("Error running privileged: "+e);
                }
        }
}
\end{verbatim}
\end{scriptsize}

The TSS uses JAAS to logon and return the user's Kerberos credentials. The
logon principal to use is defined in the JAAS login configuration file.
The TSS must then run the rest of the application as a PrivilegedAction using
the logged on credentials. This allows the TSS interceptor to retrieve the
Kerberos ticket from the logon session.

The following is the JAAS logon configuration for the TSS:

\begin{scriptsize}
\begin{verbatim}
KerberosService 
{
    com.sun.security.auth.module.Krb5LoginModule required storeKey=true principal="testService@OPENROADSCONSULTING.COM" debug=true;
};
\end{verbatim}
\end{scriptsize}

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "../ProgrammingGuide"
%%% End: 
