Tech-invite3GPPspaceIETFspace
96959493929190898887868584838281807978777675747372717069686766656463626160595857565554535251504948474645444342414039383736353433323130292827262524232221201918171615141312111009080706050403020100
in Index   Prev   Next

RFC 8353

Generic Security Service API Version 2: Java Bindings Update

Pages: 96
Proposed Standard
Obsoletes:  5653
Part 7 of 7 – Pages 83 to 96
First   Prev   None

Top   ToC   RFC8353 - Page 83   prevText

8. Sample Applications

8.1. Simple GSS Context Initiator

<CODE BEGINS> import org.ietf.jgss.*; /** * This is a partial sketch for a simple client program that acts * as a GSS context initiator. It illustrates how to use the Java * bindings for the GSS-API specified in RFC 8353. * * * This code sketch assumes the existence of a GSS-API * implementation that supports the mechanism that it will need * and is present as a library package (org.ietf.jgss) either as * part of the standard JRE or in the CLASSPATH the application * specifies. */ public class SimpleClient { private String serviceName; // name of peer (i.e., server) private GSSCredential clientCred = null; private GSSContext context = null; private Oid mech; // underlying mechanism to use private GSSManager mgr = GSSManager.getInstance(); ... ... private void clientActions() { initializeGSS(); establishContext(); doCommunication(); } /** * Acquire credentials for the client. */ private void initializeGSS() { try { clientCred = mgr.createCredential(null /*default princ*/, GSSCredential.INDEFINITE_LIFETIME /* max lifetime */, mech /* mechanism to use */,
Top   ToC   RFC8353 - Page 84
                   GSSCredential.INITIATE_ONLY /* init context */);

               print("GSSCredential created for " +
                     clientCred.getName().toString());
               print("Credential lifetime (sec)=" +
                     clientCred.getRemainingLifetime());
           } catch (GSSException e) {
               print("GSS-API error in credential acquisition: "
                     + e.getMessage());
               ...
               ...
           }
           ...
           ...
       }

       /**
        * Does the security context establishment with the
        * server.
        */
       private void establishContext() {

           byte[] inToken = new byte[0];
           byte[] outToken = null;

           try {

               GSSName peer = mgr.createName(serviceName,
                                     GSSName.NT_HOSTBASED_SERVICE);
               context = mgr.createContext(peer, mech, clientCred,
                      GSSContext.INDEFINITE_LIFETIME/*lifetime*/);

               // Will need to support confidentiality
               context.requestConf(true);

               while (!context.isEstablished()) {

                   outToken = context.initSecContext(inToken, 0,
                                                   inToken.length);

                   if (outToken != null)
                       writeGSSToken(outToken);

                   if (!context.isEstablished())
                       inToken = readGSSToken();
               }

               peer = context.getTargName();
Top   ToC   RFC8353 - Page 85
               print("Security context established with " + peer +
                     " using underlying mechanism " + mech.toString());
           } catch (GSSException e) {
                print("GSS-API error during context establishment: "
                      + e.getMessage());

                // If the exception contains an output token,
                // it should be sent to the acceptor.
                byte[] outTok = e.getOutputToken();
                if (outTok != null) {
                    writeGSSToken(outTok);
                }
                ...
                ...
           }
           ...
           ...
       }

       /**
        * Sends some data to the server and reads back the
        * response.
        */
       private void doCommunication()  {
           byte[] inToken = null;
           byte[] outToken = null;
           byte[] buffer;

           // Container for multiple input-output arguments to and
           // from the per-message routines (e.g., wrap/unwrap).
           MessageProp messgInfo = new MessageProp(true);

           try {

               /*
                * Now send some bytes to the server to be
                * processed.  They will be integrity protected
                * but not encrypted for privacy.
                */

               buffer = readFromFile();

               // Set privacy to "false" and use the default QOP
               messgInfo.setPrivacy(false);

               outToken = context.wrap(buffer, 0, buffer.length,
                                       messgInfo);
Top   ToC   RFC8353 - Page 86
               writeGSSToken(outToken);

               /*
                * Now read the response from the server.
                */

               inToken = readGSSToken();
               buffer = context.unwrap(inToken, 0,
                             inToken.length, messgInfo);
               // All ok if no exception was thrown!

               GSSName peer = context.getTargName();

               print("Message from "  + peer.toString()
                     + " arrived.");
               print("Was it encrypted? "  +
                     messgInfo.getPrivacy());
               print("Duplicate Token? "   +
                     messgInfo.isDuplicateToken());
               print("Old Token? "         +
                     messgInfo.isOldToken());
               print("Unsequenced Token? " +
                     messgInfo.isUnseqToken());
               print("Gap Token? "         +
                     messgInfo.isGapToken());
               ...
               ...
           } catch (GSSException e) {
               print("GSS-API error in per-message calls: "
                     + e.getMessage());
               ...
               ...
           }
           ...
           ...
       } // end of doCommunication method

       ...
       ...

   } // end of class SimpleClient
   <CODE ENDS>
Top   ToC   RFC8353 - Page 87

8.2. Simple GSS Context Acceptor

<CODE BEGINS> import org.ietf.jgss.*; /** * This is a partial sketch for a simple server program that acts * as a GSS context acceptor. It illustrates how to use the Java * bindings for the GSS-API specified in * Generic Security Service API Version 2 : Java Bindings. * * This code sketch assumes the existence of a GSS-API * implementation that supports the mechanisms that it will need * and is present as a library package (org.ietf.jgss) either as * part of the standard JRE or in the CLASSPATH the application * specifies. */ import org.ietf.jgss.*; public class SimpleServer { private String serviceName; private GSSName name; private GSSCredential cred; private GSSManager mgr; ... ... /** * Wait for client connections, establish security contexts, * and provide service. */ private void loop() throws Exception { ... ... mgr = GSSManager.getInstance(); name = mgr.createName(serviceName, GSSName.NT_HOSTBASED_SERVICE); cred = mgr.createCredential(name, GSSCredential.INDEFINITE_LIFETIME, (Oid[])null, GSSCredential.ACCEPT_ONLY);
Top   ToC   RFC8353 - Page 88
           // Loop infinitely
           while (true) {
               Socket s = serverSock.accept();

               // Start a new thread to serve this connection
               Thread serverThread = new ServerThread(s);
               serverThread.start();
           }
       }

       /**
        * Inner class ServerThread whose run() method provides the
        * secure service to a connection.
        */

       private class ServerThread extends Thread {

           ...
           ...

           /**
            * Deals with the connection from one client.  It also
            * handles all GSSException's thrown while talking to
            * this client.
            */
           public void run() {

               byte[] inToken = null;
               byte[] outToken = null;
               byte[] buffer;


               // Container for multiple input-output arguments to
               // and from the per-message routines
               // (i.e., wrap/unwrap).
               MessageProp supplInfo = new MessageProp(true);

               try {
                   // Now do the context establishment loop
                   GSSContext context = mgr.createContext(cred);

                   while (!context.isEstablished()) {

                       inToken = readGSSToken();
                       outToken = context.acceptSecContext(inToken,
                                                0, inToken.length);
                       if (outToken != null)
                           writeGSSToken(outToken);
Top   ToC   RFC8353 - Page 89
                   }

                   // SimpleServer wants confidentiality to be
                   // available.  Check for it.
                   if (!context.getConfState()){
                       ...
                       ...
                   }

                   GSSName peer = context.getSrcName();
                   Oid mech = context.getMech();
                   print("Security context established with " +
                          peer.toString() +
                         " using underlying mechanism " +
                         mech.toString());

                   // Now read the bytes sent by the client to be
                   // processed.
                   inToken = readGSSToken();

                   // Unwrap the message
                   buffer = context.unwrap(inToken, 0,
                               inToken.length, supplInfo);
                   // All ok if no exception was thrown!

                   // Print other supplementary per-message status
                   // information.

                   print("Message from " +
                           peer.toString() + " arrived.");
                   print("Was it encrypted? " +
                           supplInfo.getPrivacy());
                   print("Duplicate Token? " +
                           supplInfo.isDuplicateToken());
                   print("Old Token? "  + supplInfo.isOldToken());
                   print("Unsequenced Token? " +
                           supplInfo.isUnseqToken());
                   print("Gap Token? "  + supplInfo.isGapToken());

                   /*
                    * Now process the bytes and send back an
                    * encrypted response.
                    */

                   buffer = serverProcess(buffer);
Top   ToC   RFC8353 - Page 90
                   // Encipher it and send it across

                   supplInfo.setPrivacy(true); // privacy requested
                   supplInfo.setQOP(0); // default QOP
                   outToken = context.wrap(buffer, 0, buffer.length,
                                              supplInfo);
                   writeGSSToken(outToken);

               } catch (GSSException e) {
                   print("GSS-API Error: " + e.getMessage());
                   // Alternatively, could call e.getMajorMessage()
                   // and e.getMinorMessage()

                   // If the exception contains an output token,
                   // it should be sent to the initiator.
                   byte[] outTok = e.getOutputToken();
                   if (outTok != null) {
                       writeGSSToken(outTok);
                   }
                   print("Abandoning security context.");
                   ...
                   ...
               }
               ...
               ...
           } // end of run method in ServerThread

       } // end of inner class ServerThread

       ...
       ...

   } // end of class SimpleServer
   <CODE ENDS>

9. Security Considerations

The Java language security model allows platform providers to have policy-based fine-grained access control over any resource that an application wants. When using a Java security manager (such as, but not limited to, the case of applets running in browsers), the application code is in a sandbox by default. Administrators of the platform JRE determine what permissions, if any, are to be given to source from different codebases. Thus, the administrator has to be aware of any special requirements that the GSS provider might have for system resources. For instance, a Kerberos provider might wish to make a network connection to the Key
Top   ToC   RFC8353 - Page 91
   Distribution Center (KDC) to obtain initial credentials.  This would
   not be allowed under the sandbox unless the administrator had granted
   permissions for this.  Also, note that this granting and checking of
   permissions happens transparently to the application and is outside
   the scope of this document.

   The Java language allows administrators to pre-configure a list of
   security service providers in the <JRE>/lib/security/java.security
   file.  At runtime, the system approaches these providers in order of
   preference when looking for security-related services.  Applications
   have a means to modify this list through methods in the "Security"
   class in the "java.security" package.  However, since these
   modifications would be visible in the entire Java Virtual Machine
   (JVM) and thus affect all code executing in it, this operation is not
   available in the sandbox and requires special permissions to perform.
   Thus, when a GSS application has special needs that are met by a
   particular security provider, it has two choices:

   1) Install the provider on a JVM-wide basis using the
      java.security.Security class and then depend on the system to find
      the right provider automatically when the need arises.  (This
      would require the application to be granted a "insertProvider
      SecurityPermission".)

   2) Pass an instance of the provider to the local instance of
      GSSManager so that only factory calls going through that
      GSSManager use the desired provider.  (This would not require any
      permissions.)

10. IANA Considerations

This document has no IANA actions.

11. Changes since RFC 5653

This document has following changes: 1) New error token embedded in GSSException There is a design flaw in the initSecContext and acceptSecContext methods of the GSSContext class defined in "Generic Security Service API Version 2: Java Bindings Update" [RFC5653]. The methods could either return a token (possibly null if no more tokens are needed) when the call succeeds or throw a GSSException if there is a failure, but NOT both. On the other hand, the C-bindings of GSS-API [RFC2744] can return both; that is to say, a
Top   ToC   RFC8353 - Page 92
      call to the GSS_Init_sec_context() function can return a major
      status code, and at the same time, fill in the output_token
      argument if there is one.

      Without the ability to emit an error token when there is a
      failure, a Java application has no mechanism to tell the other
      side what the error is.  For example, a "reject" NegTokenResp
      token can never be transmitted for the SPNEGO mechanism [RFC4178].

      While a Java method can never return a value and throw an
      exception at the same time, we can embed the error token inside
      the exception so that the caller has a chance to retrieve it.
      This update adds a new GSSException constructor to include this
      token inside a GSSException object and a getOutputToken() method
      to retrieve the token.  The specification for the initSecContext
      and acceptSecContext methods are updated to describe the new
      behavior.  Various examples are also updated.

      New JGSS programs SHOULD make use of this new feature, but it is
      not mandatory.  A program that intends to run with both old and
      new GSS Java bindings can use reflection to check the availability
      of this new method and call it accordingly.

   2) Removing Stream-Based GSSContext Methods

      The overloaded methods of GSSContext that use input and output
      streams as the means to convey authentication and per-message
      GSS-API tokens as described in Section 5.15 of RFC 5653 [RFC5653]
      are removed in this update as the wire protocol should be defined
      by an application and not a library.  It's also impossible to
      implement these methods correctly when the token has no self-
      framing (where the end cannot be determined), or the library has
      no knowledge of the token format (for example, as a bridge talking
      to another GSS library).  These methods include initSecContext
      (Section 7.4.5 of RFC 5653 [RFC5653]), acceptSecContext
      (Section 7.4.9 of RFC 5653 [RFC5653]), wrap (Section 7.4.15 of RFC
      5653 [RFC5653]), unwrap (Section 7.4.17 of RFC 5653 [RFC5653]),
      getMIC (Section 7.4.19 of RFC 5653 [RFC5653]), and verifyMIC
      (Section 7.4.21 of RFC 5653 [RFC5653]).
Top   ToC   RFC8353 - Page 93

12. Changes since RFC 2853

This document has the following changes: 1) Major GSS Status Code Constant Values RFC 2853 listed all the GSS status code values in two different sections: Section 4.12.1 defined numeric values for them, and Section 6.8.1 defined them as static constants in the GSSException class without assigning any values. Due to an inconsistent ordering between these two sections, all of the GSS major status codes resulted in misalignment and a subsequent disagreement between deployed implementations. This document defines the numeric values of the GSS status codes in both sections, while maintaining the original ordering from Section 6.8.1 of RFC 2853 [RFC2853], and it obsoletes the GSS status code values defined in Section 4.12.1. The relevant sections in this document are Sections 5.12.1 and 7.8.1. 2) GSS Credential Usage Constant Values RFC 2853, Section 6.3.2 defines static constants for the GSSCredential usage flags. However, the values of these constants were not defined anywhere in RFC 2853 [RFC2853]. This document defines the credential usage values in Section 7.3.1. The original ordering of these values from Section 6.3.2 of RFC 2853 [RFC2853] is maintained. 3) GSS Host-Based Service Name RFC 2853 [RFC2853], Section 6.2.2 defines the static constant for the GSS host-based service OID NT_HOSTBASED_SERVICE, using a deprecated OID value. This document updates the NT_HOSTBASED_SERVICE OID value in Section 7.2.1 to be consistent with the C-bindings in RFC 2744 [RFC2744].
Top   ToC   RFC8353 - Page 94

13. References

13.1. Normative References

[RFC2025] Adams, C., "The Simple Public-Key GSS-API Mechanism (SPKM)", RFC 2025, DOI 10.17487/RFC2025, October 1996, <https://www.rfc-editor.org/info/rfc2025>. [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>. [RFC2743] Linn, J., "Generic Security Service Application Program Interface Version 2, Update 1", RFC 2743, DOI 10.17487/RFC2743, January 2000, <https://www.rfc-editor.org/info/rfc2743>. [RFC2744] Wray, J., "Generic Security Service API Version 2 : C-bindings", RFC 2744, DOI 10.17487/RFC2744, January 2000, <https://www.rfc-editor.org/info/rfc2744>. [RFC2853] Kabat, J. and M. Upadhyay, "Generic Security Service API Version 2 : Java Bindings", RFC 2853, DOI 10.17487/RFC2853, June 2000, <https://www.rfc-editor.org/info/rfc2853>. [RFC4121] Zhu, L., Jaganathan, K., and S. Hartman, "The Kerberos Version 5 Generic Security Service Application Program Interface (GSS-API) Mechanism: Version 2", RFC 4121, DOI 10.17487/RFC4121, July 2005, <https://www.rfc-editor.org/info/rfc4121>. [RFC4178] Zhu, L., Leach, P., Jaganathan, K., and W. Ingersoll, "The Simple and Protected Generic Security Service Application Program Interface (GSS-API) Negotiation Mechanism", RFC 4178, DOI 10.17487/RFC4178, October 2005, <https://www.rfc-editor.org/info/rfc4178>. [RFC5653] Upadhyay, M. and S. Malkani, "Generic Security Service API Version 2: Java Bindings Update", RFC 5653, DOI 10.17487/RFC5653, August 2009, <https://www.rfc-editor.org/info/rfc5653>. [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.
Top   ToC   RFC8353 - Page 95

13.2. Informative References

[ISOIEC-8824] International Organization for Standardization, "Information technology -- Abstract Syntax Notation One (ASN.1): Specification of basic notation", ISO/ IEC 8824-1:2014, November 2015, <https://www.iso.org/standard/68350.html>. [ISOIEC-8825] International Organization for Standardization, "Information technology -- ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)", ISO/IEC 8825-1:2015, November 2015, <https://www.iso.org/standard/68345.html>. [JLS] Gosling, J., Joy, B., Steele, G., Bracha, G., Buckley, A., and D. Smith, "The Java Language Specification", Java SE 10 Edition, February 2018, <https://docs.oracle.com/javase/specs/jls/se10/html/ index.html>.
Top   ToC   RFC8353 - Page 96

Acknowledgments

We would like to thank Mike Eisler, Lin Ling, Ram Marti, Michael Saltz, and other members of Sun's development team for their helpful input, comments, and suggestions. We would also like to thank Greg Hudson, Benjamin Kaduk, Joe Salowey and Michael Smith for many insightful ideas and suggestions that have contributed to this document.

Authors' Addresses

Mayank D. Upadhyay Google Inc. 1600 Amphitheatre Parkway Mountain View, CA 94043 United States of America Email: m.d.upadhyay+ietf@gmail.com Seema Malkani ActivIdentity Corp. 6623 Dumbarton Circle Fremont, California 94555 United States of America Email: Seema.Malkani@gmail.com Weijun Wang Oracle Building No. 24, Zhongguancun Software Park Beijing 100193 China Email: weijun.wang@oracle.com