Previous | Contents | Index |
The Generic Security Service (GSS) provides an application programming interface that lets you extend DCE security to distributed applications that handle network communications by themselves.
Figure 12-1 shows the relationships among the interfaces to the DCE security server and the relationship of Security interfaces to DCE applications.
Figure 12-1 DCE Security and the DCE Application Environment
This chapter provides the following information, which augments the information in the OSF DCE Application Development Guide:
For detailed information about the GSSAPI routines, see the Digital
DCE for OpenVMS VAX and OpenVMS Alpha Reference Guide.
12.1 About the Generic Security Service API
With GSSAPI, you can include established applications in DCE and ensure the security and integrity of the applications and their data. The GSSAPI is defined in the Internet RFC 1508, Generic Security Service Application Programming Interface, and RFC 1509, Generic Security Service API : C-bindings. Additions have been made to the API to accommodate peer-to-peer applications in the DCE.
In communications between peer applications in a DCE environment, the application that establishes the secure connection is the context initiator or simply initiator. The context initiator is like a DCE RPC client. The application that accepts the secure connection is the context acceptor or simply acceptor. The context acceptor is like a DCE RPC server.
GSSAPI credentials enable applications to identify themselves as DCE principals.
The GSS available with DCE includes two sets of routines:
While some GSS routines use RPC themselves, applications that use GSS can themselves be designed and implemented without RPC and still run securely on DCE servers.
The GSSAPI combines authentication and authorization under a single security mechanism type. The security mechanism provides applications a choice of either authenticated Kerberos security or authenticated PAC authorization under DCE Security.
As an alternative to authenticated RPC, the GSSAPI provides an API to
the DCE Authentication Service and Privilege Service. The Login
facility and authenticated RPC or GSSAPI encapsulate interactions
between a principal and the Privilege Service.
12.2 GSSAPI and Authentication
This section explains concepts related to authentication.
With authenticated RPC, you can choose the authentication protocol and
authorization protocol that your applications use. With GSSAPI, you
select one of the two supported security mechanisms: DCE Security or
Kerberos. Both DCE Security and Kerberos use the DCE shared-secret
authentication protocol. However, if you select DCE Security, your
applications use the authenticated PAC authorization protocol, allowing
the context acceptor to use DCE ACLs to determine whether access should
be permitted. If you select Kerberos as the security mechanism, the
applications use a name-based authorization protocol, where the context
acceptor receives only the context initiator's registered name.
12.2.1 GSSAPI and Protection Levels
Protection levels specify how much of network messages exchanged by principals are encrypted. As a rule, the higher the protection level, the greater the negative impact on performance.
The DCE implementation of the GSSAPI supports only one level, or quality, of protection, which applications can apply using the GSSAPI per-message protection services. Applications request per-message protection using GSSAPI routines gss_sign( ) and gss_seal( ). The routines offer the following protection:
This section describes the process by which applications that manage network communications without RPC can use GSSAPI and DCE Security to authenticate the applications with which they communicate.
The peer applications establish a secure connection in the following way. The numbers of the stages described correspond to callouts in Figure 12-2.
Figure 12-2 The Context Initiator Authenticates a Context Acceptor
A GSSAPI credential is a data structure that provides proof of an application's claim to a principal name. An application uses a credential to establish its global identity. The global identity can be, but is not necessarily, related to the local user name under which the application (either the initiator or the acceptor) is running.
A credential can consist of either of the following:
Table 12-1 lists the types of credentials.
Credential Type | Consists of... | Identifies applications that... |
INITIATE | Login context only | Only initiate security contexts |
ACCEPT | Principal name and associated entry key table | Only accept security contexts |
BOTH | Login context and principal name with key table entry | Can either initiate or accept security contexts |
Credentials are maintained internally to GSSAPI. When they establish a security context, applications use credential handles to point to the credentials they need.
When an application initiates or accepts a security context, it can use GSSAPI routines with either a default credential or a specific credential handle. This chapter discusses how applications:
For detailed information on the GSSAPI routines referred to in this
chapter, see the OSF DCE Application Development Reference.
12.3.1 Using Default Credentials
A default credential is a credential that is:
When an application calls the GSSAPI routine to either initiate (gss_init_sec_context( )) or accept (gss_accept_sec_context( )) a security context, it can specify the use of its default credential.
Use default credentials to help ensure the portability of your
applications.
12.3.1.1 Initiate a Security Context
To use a default credential when initiating a security context, an application calls the gss_init_sec_context( ) routine and specifies GSS_C_NO_CREDENTIAL as the input claimant credential handle to the routine. The routine uses the initiator's DCE default login context to generate the default credential. The credential is an INITIATE type credential.
You can change the default login context by calling the DCE
sec_login routines. For information on the sec_login
routines, see the OSF DCE Application Development Reference.
12.3.1.2 Accept a Security Context
To use a default credential when accepting a security context, an
application calls the gss_accept_security_context( ) routine and
specifies GSS_C_NO_CREDENTIAL as the verifier credential handle to the
routine. The GSSAPI uses a principal name registered for the context
acceptor to generate the default credential handle. The credential is
an ACCEPT credential type.
12.3.2 Creating New Credential Handles
An application can create a new credential handle to pass to the gss_init_sec_context( ) or gss_accept_sec_context( ) routines. An application might create a credential handle rather than use the default credential for the following reasons:
To create a credential handle for an INITIATE credential type, the application calls the gssdce_login_context_to_cred( ) routine and specifies its login context as input to the routine. The routine creates a credential handle that points to the credential consisting of that login context.
An application can also use a BOTH type credential to initiate a security context. Use the gss_acquire_cred( ) routine to create a BOTH type credential, as explained in the next section.
When the application uses a BOTH credential, the gss_acquire_cred( )
routine creates a login context from the key table information. Then,
it uses the login context to create the a credential. For more details,
refer to the OSF DCE Application Development Reference.
12.3.2.2 Accepting a Security Context Using New Credential Handles
To create new credential handle for an ACCEPT or BOTH type credential, an application calls the gss_acquire_cred( ) routine.
The gss_acquire_cred( ) routine uses a principal name and its entry in the key table to generate the credential handle. If the principal name has not yet been registered (using gssdce_register_acceptor_identity( ) or the rpc_server_register_auth_info( ) routines), the gss_acquire_cred( ) routine automatically registers it.
Digital DCE for OpenVMS VAX and OpenVMS Alpha contains the Interface Definition Language (IDL). The IDL supports a number of C++ language syntax features that provide a distributed object framework. The DCE RPC runtime environment supports C++ bindings to remote objects. The combination of these new features creates an Object-Oriented RPC.
In an object-oriented application, the implementation details of data are hidden. The developer can model data as objects that provide their own interfaces and implementation. Objects can be reused as building blocks or components in a solution to complex problems.
The Interface Definition Language allows the DCE application developer to define an interface to remote procedures. With Object-Oriented RPC, you can use the IDL language to define an interface to remote objects. The interface is treated as an abstract class and its operations are treated like the public methods exported by the class.
When you write a distributed application using Object-Oriented RPC, you can do the following:
This chapter contains the following sections:
Appendix A describes two examples that implement a 2x2 matrix in a server application. The examples also allow the client application to manipulate the matrix with an IDL interface.
The Digital DCE for OpenVMS VAX and OpenVMS Alpha Reference
Guide contains reference information (IDL-supplied member
functions, ACF attributes, and exceptions) for Object-Oriented RPC.
13.1 Overview of C++
This section presents a brief overview of the C++ language for DCE
application developers who are unfamiliar with C++. If you are familiar
with C++, you can skip this section. Refer to the C++ reference
documentation for more specific details of the language.
13.1.1 Class Definition
A class definition is used to define a new data type to the compiler. Class definitions are more powerful than traditional data type definitions because they allow data and functions to be grouped together. They also offer protection levels for the data and functions they contain to control how the elements of the class can be accessed.
A C++ class definition defines the operations (also known as methods) and data supported by a particular class. Each operation and data element may have one of three different protection attributes associated with it. A public protection attribute is the most open protection level because it allows free access to the operation or data element it represents. Protected and private protection levels are more restrictive in allowing access to the elements with which they are associated.
A common object-oriented technique is to define a public interface for
an object and to make that interface available to users. In C++ this is
done by creating an abstract class and using the polymorphic behavior
of the language to implement the methods defined in the abstract or
interface class. (See Section 13.1.4 for more information about
polymorphic behavior.)
13.1.2 Objects
An instantiation of a C++ class is called an object. There can be any number of objects of the same class type in a program, limited only by the amount of memory available to run the program. Each object has its own exclusive data members. Access to the object's data and operations is governed by the protection attribute of the data or operation.
A C++ object has an implied this pointer associated with it. The this pointer distinguishes one object from another at runtime and requires no user intervention when invoking operations or accessing data. The C++ compiler generates code that supplies the implied this pointer.
In the following code fragment, the class type Test contains an operation and data element that can be referenced by any object of type Test. The variable f is an object or class instantiation. A message is sent to f asking for the value of its encapsulated data.
class Test { public: int x; int getData() { return x; } }; 2 int data; Test f; // f is an object data = f.getData(); // send a message to f |
C++ supports the concept of class inheritance. If class B inherits from
class A, then class B is termed a derived class and class A is a base
class. A derived class inherits all of the public member functions and
data from the base class. This allows access to the base class members
from an object that has a derived class type. A derived class is said
to have an is-a relationship with the base class. This
means that an object of class type B can also be considered as an
object of class type A. A B object can be assigned to a variable of
type A.
13.1.4 Polymorphic Operations
Polymorphism means many forms. The major benefits of polymorphism are that it makes objects more independent of each other and it allows new objects to be added with minimal changes to existing objects.
For example, when the same operation is defined in both the base class and derived class, associating the virtual keyword with the operation name in the base class causes an invocation of the operation from a base class pointer or reference to automatically forward the call to the derived object. This is desirable in the case where a derived object is assigned to a base object, because it allows the programmer to interact with the base definition but allows the runtime support to interact with the multitude of different objects that may be derived from the base class.
The following code fragment illustrates inheritance and virtual functions.
class Base { public: virtual void op1() { cout << "I'm in Base::op1()n"; } void op2() { cout << "I'm in Base::op2()n"; } }; class Derived : public Base { public: void op1() { cout << "I'm in Derived::op1()n"; } void op2() { cout << "I'm in Derived::op2()n"; } }; Derived d; Base *pb = &d; // pointer to the Base part of object d Derived *pd = &d; // pointer to the Derived part of object d pd-) op1(); // prints "I'm in Derived::op1()" pd->op2(); // prints "I'm in Derived::op2()" pb->op1(); // prints "I'm in Derived::op1()" pb->op2(); // prints "I'm in Base::op2()" |
Previous | Next | Contents | Index |