copied from OV, added init_arg version 4
authorBarry Jaspan <bjaspan@mit.edu>
Wed, 16 Oct 1996 15:34:07 +0000 (15:34 +0000)
committerBarry Jaspan <bjaspan@mit.edu>
Wed, 16 Oct 1996 15:34:07 +0000 (15:34 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@9181 dc483132-0cff-0310-8789-dd5450dbe970

doc/rpc/design.tex [new file with mode: 0644]

diff --git a/doc/rpc/design.tex b/doc/rpc/design.tex
new file mode 100644 (file)
index 0000000..0ccee47
--- /dev/null
@@ -0,0 +1,1037 @@
+\documentstyle[fullpage,12pt]{article}
+
+\title{GSS-API Extensions to Sun RPC}
+\date{Draft---\today}
+\author{Barry Jaspan}
+
+\setlength{\parskip}{.7\baselineskip}
+\setlength{\parindent}{0pt}
+
+\makeatletter
+\newcount\savecnt\savecnt=0
+\def\saveenum#1{\global\savecnt=\csname c@enum#1\endcsname}
+\def\restoreenum#1{\csname c@enum#1\endcsname=\savecnt}
+\makeatother
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Make _ actually generate an _, and allow line-breaking after it.
+\let\underscore=\_
+\catcode`_=13
+\def_{\underscore\penalty75\relax}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\begin{document}
+
+
+{\setlength{\parskip}{0pt}\maketitle\tableofcontents}
+
+\section{Introduction}
+
+This document describes the integration of GSS-API authentication and
+security with Sun RPC.
+
+\section{Requirements}
+
+The requirements of the GSS-API authentication system for Sun RPC are:
+
+\begin{enumerate}
+\item It must provide mutual authentication between RPC clients and
+servers.
+
+\item It must provide for integrity checking and encryption of all
+procedure arguments and results passed over the network.
+\saveenum{i}
+\end{enumerate}
+
+The following features are desired, but not mandatory:
+
+\begin{enumerate}
+\restoreenum{i}
+\item It should provide for integrity checking and encryption of all
+``header information'' that specifies the program and procedure being
+called.
+
+\item It should obey the Sun RPC protocol so that clients using
+it can interoperate with existing servers.  In this case,
+``interoperate'' means that existing servers will return an error code
+indicating that they do not understand the authentication flavor, but
+not that they do not understand the request at all.
+
+\item It should require minimal or no changes to the standard Sun RPC
+programming paradigm for either clients or servers so that existing
+code can use it with little or no effort.
+
+\item It should operate correctly with all the standard Sun RPC
+transport mechansims (e.g. UDP and TCP).
+\saveenum{i}
+\end{enumerate}
+
+\section{Functional Specification}
+
+This section describes the programmer's interface to the GSS-API
+authentication flavor.   Knowledge of standard Sun RPC programming is
+assumed.
+
+\subsection{Client Side}
+
+A RPC client can select the GSS-API authentication flavor in the same
+way it can select any other authentication flavor, by setting the
+cl_auth field of the CLIENT structure to the appropriate value:
+
+\begin{verbatim}
+    clnt = clnt_create(server_host, PROG_NUM, PROG_VERS, protocol);
+    clnt->cl_auth = auth_gssapi_create(clnt, ...);
+\end{verbatim}
+
+There are two functions that create GSS-API authentication flavor
+structures for the cl_auth field, auth_gssapi_create and
+auth_gssapi_create_default.
+
+\begin{verbatim}
+AUTH *auth_gssapi_create(CLIENT         *clnt,
+                        OM_uint32       *major_status,
+                        OM_uint32       *minor_status,
+                        gss_cred_id_t   claimant_cred_handle,
+                        gss_name_t      target_name,
+                        gss_OID         mech_type,
+                        int             req_flags,
+                        int             time_req,
+                        gss_OID         *actual_mech_type,
+                        int             *ret_flags,
+                        OM_uint32       *time_rec);
+\end{verbatim}
+
+auth_gssapi_create creates a GSS-API authentication structure and
+provides most of the flexibility of gss_init_sec_context.  The
+arguments have the same interpretation as those of
+gss_init_sec_context with the same name, except:
+
+\begin{description}
+\item[clnt] The CLIENT structure returned by client_create or one of
+its relatives.  It is not modified.
+\end{description}
+
+auth_gssapi_create calls gss_init_sec_context as needed, passing each
+generated token to and processing each token returned from the RPC
+server specified by the RPC handle clnt.  On return, if major_status
+is GSS_S_COMPLETE, the context has been established, the returned AUTH
+structure is valid, and all of the arguments filled in by
+gss_init_sec_context have the correct values.  If major_status is not
+GSS_S_COMPLETE then it and minor_status contain error codes that can
+be passed to gss_display_status and the returned value is NULL.
+
+\begin{verbatim}
+AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name);
+\end{verbatim}
+
+auth_gssapi_create_default is a shorthand for auth_gssapi_create that
+attempts to create a context that provides procedure call and result
+integrity, using the default credentials and GSS-API mechanism.
+service_name is parsed as a GSS-API ``service'' name and used as the
+target name.  The other arguments to auth_gssapi_create are as follows:
+
+\begin{verbatim}
+auth_gssapi_create(clnt,
+                   &dummy,
+                   &dummy,
+                   GSS_C_NO_CREDENTIAL,
+                   target_name,
+                   GSS_C_NULL_OID,
+                   GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+                   0,
+                   NULL,
+                   NULL,
+                   NULL);
+\end{verbatim}
+
+Note that if the underlying default mechanism does not support data
+integrity (e.g. the trust mechanism), this function will fail.
+
+The GSS-API major and minor status codes can be interpreted with
+auth_gssapi_display_status:
+
+\begin{verbatim}
+void auth_gssapi_display_status(char *msg, OM_uint32 major, 
+                                OM_uint32 minor); 
+\end{verbatim}
+
+All of the error messages associated with the major and minor status
+are displated on the standard error output, preceeded by the message
+``GSS-API authentication error $<$msg$>$:''.
+
+\subsection{Server Side}
+
+\subsubsection{Service Name Registration}
+
+An application server must register the service name(s) that it will
+use for GSS-API connections before any AUTH_GSSAPI requests will
+succeed.
+
+\begin{verbatim}
+typedef struct _auth_gssapi_name {
+     char *name;
+     gss_OID type;
+} auth_gssapi_name;
+
+bool_t _svcauth_gssapi_set_names(auth_gssapi_name *names, int num);
+\end{verbatim}
+
+names is an array of name specifications, each of which consists of a
+null-terminated ASCII representation of a name and the GSS-API name
+type that should be used to import it with gss_import_name.  The
+name type ``gss_nt_service_name'' is recommended.
+
+\subsubsection{Calling Client and Service Identification}
+
+Each application server's dispatch function is passed two arguments,
+the transport mechanism (transp) and the RPC service request (rqstp).
+If the service request's credential flavor (rq_cred.oa_flavor) is
+AUTH_GSSAPI (300001)\footnote{The value 4 was originally used, but
+300001 has been officially assigned by the IETF.}, then the call has
+been authenticated.  The rq_clntcred field of transp contains the
+gss_name_t of the authenticated caller and can be passed to
+gss_display_name to obtain a string represtation or gss_compare_name
+to compare it with other names.  The rq_svccred field of transp
+contains the GSS-API context established with the caller and can be
+passed to gss_inquire_context.
+
+\subsubsection{Error Logging}
+
+An application server can register a function to be called when a
+failure occurs during GSS-API context establishment with
+_svcauth_set_log_badauth_func.
+
+\begin{verbatim}
+typedef void (*auth_gssapi_log_badauth_func)(OM_uint32 major,
+                                             OM_uint32 minor,
+                                             struct sockaddr_in *raddr,
+                                             caddr_t data);
+   
+void _svcauth_set_log_badauth_func(auth_gssapi_log_badauth_func func,
+                                   caddr_t data); 
+\end{verbatim}
+
+The function func is called each time gss_accept_sec_context fails.
+The major and minor arguments indicate the GSS-API major and minor
+status codes returned.  The raddr field contains the INET socket that
+the request came from, and the data field contains the data argument
+of _svcauth_gssapi_set_log_badauth_func.
+
+An application server can register a function to be called when an RPC
+request with an invalid verifier arrives with
+_svcauth_set_log_badverf_func.
+
+\begin{verbatim}
+typedef void (*auth_gssapi_log_badverf_func)(gss_name_t client,
+                                             gss_name_t server,
+                                             struct svc_req *rqst,
+                                             struct rpc_msg *msg,
+                                             caddr_t data);
+
+void _svcauth_set_log_badverf_func(auth_gssapi_log_badverf_func func,
+                                   caddr_t data); 
+\end{verbatim}
+
+The function specified in func is called each time an invalid verifier
+is received.  The client and server fields identify the (falsely
+claimed) originating client and the server it originally authenticated
+to.  The raddr and addrlen fields contain the INET socket that the
+request (claims to have) come from, and data contains the data
+argument of _svcauth_set_log_badverf_func.
+
+\section{Modifications to Sun RPC}
+
+The Sun RPC extensible authentication mechanism is designed to allow
+different authentication systems to be integrated into Sun RPC easily.
+Unfortunately, it has two drawbacks.  First, the existing system has a
+number of non-general design properties that are intended specifically
+for Sun's Secure RPC, and second, the existing system has no concept
+of or ability to perform authentication-flavor-specific operations on
+function arguments and results passed over the wire.  The first
+problem merely makes the system confusing, since a number of features
+touted as ``general'' do not make any sense for arbitrary
+authentication systems.  The second problem is more substantial, and
+can only be corrected by modifications to Sun RPC internals.
+
+The following sections describe the necessary modifications to Sun
+RPC.
+
+\subsection{Client Side Authentication, AUTH Structure}
+
+The AUTH structure (figure \ref{fig:auth}) encapsulates the data and
+function pointers for an authentication flavor instance.  It has been
+changed in two ways.
+
+\begin{figure}[htbp]
+\begin{verbatim}
+typedef struct {
+        struct  opaque_auth     ah_cred;
+        struct  opaque_auth     ah_verf;
+        union   des_block       ah_key;
+        struct auth_ops {
+                void    (*ah_nextverf)();
+                int     (*ah_marshal)();        /* nextverf & serialize */
+                int     (*ah_validate)();       /* validate varifier */
+                int     (*ah_refresh)();        /* refresh credentials */
+                int     (*ah_wrap)();           /* encode data for wire */
+                int     (*ah_unwrap)();         /* decode data from wire */
+                void    (*ah_destroy)();        /* destroy this structure */
+        } *ah_ops;
+        caddr_t ah_private;
+} AUTH;
+\end{verbatim}
+\caption{The AUTH structure, with the new function pointers ah_wrap
+and ah_unwrap.}
+\label{fig:auth}
+\end{figure}
+
+First, the new functions ah_wrap and ah_unwrap prepare function
+arguments and results for transmission over the wire.  The
+authentication mechanism can use them to sign, encrypt, or perform any
+other operation on the data.  Their prototype is:
+
+\begin{verbatim}
+bool_t ah_wrap(AUTH *auth, XDR *out_xdrs, xdrproc_t func, caddr_t ptr);
+bool_t ah_unwrap(AUTH *auth, XDR *in_xdrs, xdrproc_t func, caddr_t ptr);
+\end{verbatim}
+
+ah_wrap encodes function arguments for transmission.  func and ptr are
+the XDR procedure and pointer that serialize the arguments, and
+out_xdrs is the xdr stream that the encoded arguments should be
+written to.  ah_unwrap decodes function arguments received from the
+network.  Its arguments are the converse of those to ah_wrap.
+
+It is the responsibility of RPC transport mechanisms to call an
+authorization flavor's ah_wrap and ah_unwrap functions when function
+arguments or results would normally be written to or read from the
+wire.  Authorization flavors that do not need to perform any encoding
+or decoding can use the provided function authany_wrap for ah_wrap
+and ah_unwrap; it consists of the single statement ``return
+(*func)(out_xdrs, ptr)'' (or in_xdrs, as appropriate).
+
+Second, the function ah_refresh has been changed to take the RPC error
+message that resulted in its being called as an argument.  This is
+necessary since the contents of the error message may dictate how
+ah_refresh should go about correcting the authentication failure.
+
+\subsection{Client Side Transport Mechanisms}
+
+Each client side transport mechanism must be modified to call the
+ah_wrap and ah_unwrap functions from the cl_auth field of the CLIENT
+structure during the call and reply process.  The modification is
+fairly simple.  For example, the UDP transport mechanism used to
+encode procedure calls like this:
+
+\begin{verbatim}
+        if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+            (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+            (! (*xargs)(xdrs, argsp)))
+                return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+\end{verbatim}
+
+The last function call in the conditional serializes the arguments
+onto the xdr stream.  This must be replaced with a call to the
+appropriate ah_wrap function:
+
+\begin{verbatim}
+        if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+            (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+            (! AUTH_WRAP(cl->cl_auth, xdrs, xargs, argsp)))
+                return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+\end{verbatim}
+
+AUTH_WRAP is a macro that takes the four arguments for an ah_wrap
+function and extracts and calls the function pointer from the cl_auth
+structure with the specified arguments.
+
+Similarly, the transport mechanism must unwrap procedure results.
+Again, the UDP mechanism will be instructive.  It used to deserialize
+function results like this:
+
+\begin{verbatim}
+        reply_msg.acpted_rply.ar_results.where = resultsp;
+        reply_msg.acpted_rply.ar_results.proc = xresults;
+
+        ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+\end{verbatim}
+
+The problem here is that xdr_replymsg deserializes an entire reply
+message, including the results.  Since xresults and resultsp are the
+function and pointer to decode the results, they will be automatically
+deserialized {\it without} ah_unwrap being invoked.  The simplest
+solution (which is also the normal method used by the TCP mechanism)
+is to arrange to deserialize the function results explicitly:
+
+\begin{verbatim}
+        reply_msg.acpted_rply.ar_results.where = NULL;
+        reply_msg.acpted_rply.ar_results.proc = xdr_void;
+
+        if ((! xdr_replymsg(&reply_xdrs, &reply_msg)) ||
+            (! AUTH_UNWRAP(cl->cl_auth, reply_xdrs, xresults,
+                           resultsp))) {
+                return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+        }
+\end{verbatim}
+
+Since xdr_void does not read any data from the XDR stream, the
+function results are still available when AUTH_UNWRAP is called.  Note
+that AUTH_UNWRAP should only be called on {\it successfull} calls; if
+the reply message status is not RPC_SUCCESS there are no arguments to
+read.
+
+Currently, the UDP and TCP transport mechanisms has been
+converted.\footnote{The ``raw'' mechanism, for direct connections, has
+not been.}
+
+\subsection{Service Side Authentication, SVCAUTH and XPRT}
+
+Standard Sun RPC service-side authentication consists of a single
+function per authentication flavor; there is no concept of an AUTH
+structure containing function pointers and private data as with the
+client side.  Previously, nothing else was necessary, because each
+flavor only did a single thing (authenticated individual calls in a
+stateless manner).  More functions and state are now required,
+however; they are stored in the SVCAUTH structure, see figure
+\ref{fig:svcauth}.
+
+\begin{figure}[htbp]
+\begin{verbatim}
+typedef struct {
+     struct svc_auth_ops {
+          int   (*svc_ah_wrap)();
+          int   (*svc_ah_unwrap)();
+     } *svc_ah_ops;
+     caddr_t svc_ah_private;
+} SVCAUTH;
+\end{verbatim}
+\caption{The new SVCAUTH structure.}
+\label{fig:svcauth}
+\end{figure}
+
+There is one SVCAUTH structure per authentication flavor (there is a
+default, svc_auth_any, for existing authentication flavors that do not
+need the extra functionality).  The svc_ah_wrap and svc_ah_unwrap
+perform the same logical function as their client-side counterparts.
+
+Just as with the client side, it is the responsibility of the
+transport mechanism to call the svc_ah_wrap and svc_ah_unwrap
+functions associated with the authentication flavor associated with
+each RPC call at the appropriate time.  Unfortunately, the transport
+mechanism code does not have access to the RPC call structure
+containing the authenticator flavor because the RPC call structure
+itself is not passed as an argument to the necessary functions.  The
+present solution is to add another argument to the transport mechanism
+structure, xp_auth, that stores the SVCAUTH of the {\it current} call
+on that mechanism; see figure \ref{fig:xprt}.  xp_auth is initialized
+to svc_auth_any so that existing authentication mechanisms that do not
+set the field will still operate correctly.  \footnote{This is not an
+great solution, because it forces each transport mechanism to be
+single threaded.  The correct solution is to store the SVCAUTH
+associated with each RPC call in the RPC call structure; however,
+doing so would require changing a lot of code to pass around the RPC
+call structure that currently does not do so.  Since other parts of
+Sun RPC use the XPRT structure in a non-reentrant way, the present
+solution does not make the situation any
+worse.}$^{\mbox{,}}$\footnote{A somewhat irrelevant side effect of
+adding SVCAUTH to XPRT is that the standard include file
+$<$rpc/rpc.h$>$ had to be changed to include $<$rpc/svc_auth$>$ before
+$<$rpc/svc.h$>$, whereas they used to be in the opposite order.}
+
+\begin{figure}[htbp]
+\begin{verbatim}
+typedef struct {
+        int             xp_sock;
+        u_short         xp_port;         /* associated port number */
+        struct xp_ops {
+            bool_t      (*xp_recv)();    /* receive incomming requests */
+            enum xprt_stat (*xp_stat)(); /* get transport status */
+            bool_t      (*xp_getargs)(); /* get arguments */
+            bool_t      (*xp_reply)();   /* send reply */
+            bool_t      (*xp_freeargs)();/* free mem allocated for args */
+            void        (*xp_destroy)(); /* destroy this struct */
+        } *xp_ops;
+        int             xp_addrlen;      /* length of remote address */
+        struct sockaddr_in xp_raddr;     /* remote address */
+        struct opaque_auth xp_verf;      /* raw response verifier */
+        SVCAUTH         *xp_auth;        /* auth flavor of current req */
+        caddr_t         xp_p1;           /* private */
+        caddr_t         xp_p2;           /* private */
+} SVCXPRT;
+\end{verbatim}
+\caption{The modified XPRT structure, with the xp_auth field.}
+\label{fig:xprt}
+\end{figure}
+
+Finally, with the modified XPRT structure carrying around the
+authentication flavor structure, the functions that serialize and
+deserialize function arguments and results must be modified to use the
+svc_ah_wrap and svc_ah_unwrap functions.  Each service-side transport
+mechanism has getargs and reply functions that must be modified to use
+the SVCAUTH_UNWRAP and SVCAUTH_WRAP macros, respectively, in a manner
+completely parallel to the client side.
+
+\subsection{Authenticated Service Identification, svc_req}
+
+Sun RPC provides the authenticated credentials of a client to the
+application server via rq_clntcred (``cooked credentials'') field of
+the service request (svc_req) structure.  In many authentication
+systems, services are also named entities, and there is no reason that
+an RPC should be restricted to accepting connections as a single
+authenticated service name.  However, access control decisions may be
+based on the service name a client authenticated to, so that
+information must be available to the application server.
+
+Figure \ref{fig:svc-req} shows the modified service request structure
+that contains a single new field, rq_svccred.  Like rq_clntcred, the
+authentication flavor is responsible for setting rq_svccred to the
+``cooked'' service credentials associated with a given RPC call.
+Authentication flavors that do not have the concept of service names
+can of course leave this field blank.
+
+\begin{figure}[htbp]
+\begin{verbatim}
+struct svc_req {
+        u_long          rq_prog;        /* service program number */
+        u_long          rq_vers;        /* service protocol version */
+        u_long          rq_proc;        /* the desired procedure */
+        struct opaque_auth rq_cred;     /* raw creds from the wire */
+        caddr_t         rq_clntcred;    /* read only cooked client cred */
+        caddr_t         rq_svccred;     /* read only cooked svc cred */
+        SVCXPRT         *rq_xprt;       /* associated transport */
+};
+\end{verbatim}
+\caption{The modified svc_req structure, with the rq_svccred field.}
+\label{fig:svc-req}
+\end{figure}
+
+
+
+\subsection{Authentication Negotiation, no_dispatch}
+
+In order to avoid having to transmit a full set of authentication
+information with every call, the service-side authentication mechanism
+must save state between calls.  Establishing that state may require
+multiple messages between the client-side and service-side
+authentication mechanisms.  The client-side authentication mechanism
+can make arbitrary RPC calls to the server simply by requiring the
+programmer to specify the CLIENT structure to the authentication
+flavor initialization routine.  The service side, however, is more
+complex.  In the normal course of events, an RPC call comes in, is
+authenticated, and is then dispatched to the appropriate procedure.
+For client- and service-side authentication flavors to communicate
+indepedent of the server implemented above the RPC layer, the
+service-side flavor must be able to send a reply to the client
+directly and {\it prevent} the call from being dispatched.
+
+This is implemented by a simple modification to the _authenticate
+routine, which dispatches each RPC call to the appropriate
+authentication flavor; see figure \ref{fig:authenticate}.  It takes an
+additional argument, no_dispatch, that instructs the mechanism not to
+dispatch the RPC call to the specified procedure.
+
+\begin{figure}[htbp]
+\begin{verbatim}
+                why=_authenticate(&r, &msg, &no_dispatch);
+                if (why != AUTH_OK) {
+                     svcerr_auth(xprt, why);
+                     goto call_done;
+                } else if (no_dispatch) {
+                     goto call_done;
+                }
+\end{verbatim}
+\caption{A call to the modified _authenticate.}
+\label{fig:authenticate}
+\end{figure}
+
+If _authenticate sets no_dispatch to true, the call is considered
+finished and no procedure dispatch takes place.  Presumably, an
+authentication flavor that sets no_dispatch to true also replies to
+the RPC call with svc_sendreply.  Authentication flavors that do not
+modify no_dispatch implicitly leave it set to false, so the normal
+dispatch takes place.
+
+\subsection{Affected Files}
+
+Table \ref{tab:modfiles} lists the files that were
+affected for each of the modifications described in previous sections.
+
+\begin{table}[htbp]
+\centering
+\caption{Files modified for each change to Sun RPC.}
+\label{tab:modfiles}
+\begin{tabular}{ll}
+AUTH structure                  & auth.h \\
+                                & auth_none.c \\
+                                & auth_exit.c \\
+                                & auth_any.c \\
+Client Transport Mechanisms     & clnt_udp.c \\
+                                & clnt_tcp.c \\
+SVCAUTH and XPRT structures     & rpc.h \\
+                                & svc.h \\
+                                & svc_auth.h \\
+                                & svc.c \\
+                                & svc_auth.c \\
+                                & svc_auth_any.c \\
+                                & svc_auth_unix.c \\
+Server Transport Mechanisms     & svc_udp.c \\
+                                & svc_tcp.c
+\end{tabular}
+\end{table}
+
+\section{GSS-API Authentication Flavor}
+
+The following sections describe the implemetation of the GSS-API
+authentication flavor for Sun RPC.
+
+\subsection{Authentication Algorithms}
+\label{sec:algorithms}
+
+\subsubsection{Context Initiation}
+
+The client creates a GSS-API context with the server each time it
+calls auth_gssapi_create.  The context is created using the standard
+gss_init_sec_context and gss_accept_sec_context function calls.  The
+generated tokens are passed between the client and server as arguments
+and results of normal RPC calls.
+
+The client side, in auth_gssapi_create, performs the following steps
+to initiate a context:
+
+\begin{enumerate}
+\item\label{item:process-token} The client calls gss_init_sec_context.
+On the first such call, no input token is provided; on subsequent
+calls, the token received from the server is provided.
+
+\item If gss_init_sec_context produces an output token:
+
+\begin{enumerate}
+\item The client transmits the token to the server, identifying itself
+with client_handle if it has already been received (see next step).
+The return value from the server will contain a client_handle and one
+or both of a token and a signed initial sequence number.  
+
+\item If this is the first response from the server, the client_handle
+is stored for subsequent calls.  Otherwise, the client_handle should be
+the same as returned on the previous call.
+
+\item If the response contains a signed initian sequence number but
+the context is not yet established, then the response also contains a
+token that will established the context.  The signed initial sequence
+number is stored.
+
+\item If the response contains a token, step \ref{item:process-token}
+repeated.
+\end{enumerate}
+
+\item The signed initial sequence number is verified using the
+established context.
+\end{enumerate}
+
+The server side, in _svcauth_gssapi, performs the following steps to
+initiate a context:
+
+\begin{enumerate}
+\item If a call arrives with no client_handle, a new client_handle is
+allocated and stored in the database.  Otherwise, the client's
+previous state is is looked up in the database.
+
+\item The received token is passed to gss_accept_sec_context.  If an
+output token is generated, it is returned to the client.  Note that
+since the application server may have registered multiple service
+names and there is no way to determine {\it a priori} which service a
+token is for, _svcauth_gssapi calls gss_accept_sec_context once for
+each registered credential until one of them succeedes.  The code
+assumes that GSS_S_FAILURE is the only error that can result from a
+credential mismatch, so any other error terminates the loop
+immediately.
+
+\item If the context is established, the server signs an initial
+sequence number and returns it to the client.
+\end{enumerate}
+
+Note that these algorithms require context establishment to be
+synchronous.  If gss_init_sec_context returns GSS_S_COMPLETE upon
+processing a token, it will either produce a token or not.  If it
+does, then gss_accept_sec_context will return GSS_S_COMPLETE when that
+token is processed; if it does not, then gss_accept_sec_context
+already returned GSS_S_COMPLETE (and presumably returned the token
+that caused gss_init_sec_context to return GSS_S_COMPLETE when
+processed).  The reverse is also true.
+
+\subsubsection{RPC Calls}
+
+After the GSS-API context is established, both the server and the
+client posess a client handle and a corresponding sequence number.
+Each call from the client contains the client handle as the
+``credential'' so that the server can identify which context to apply
+to the call.
+
+Each client call and server response includes a ``verifier'' that
+contains the sealed current sequence number.\footnote{In a future
+version, the verifier will also contain a signature block for the call
+header, including the procedure number called.} The sequence number
+prevents replay attacks\footnote{Although some GSS-API mechanisms
+provide replay detection themselves, not all of them do; explicitly
+including the sequence number in the RPC therefore provides better
+end-to-end security}, but by itself it does not prevent splicing
+attacks.
+
+Each procedure argument and result block consists of the current
+sequence number and the actual serialized argument string, all sealed
+with gss_seal.  Combining the sequence number with the argument/result
+data prevents splicing attacks.
+
+The sequence number is incremented by one for each RPC call and by one
+for each response.  The client and server will both reject messages
+that do not contain the expected sequence number.  Packets
+retransmitted by the client should use the {\it same} sequence number
+as the original packet, since even if the server receives multiple
+copies only one will be honored.
+
+\subsection{RPC Call Credential Structure}
+
+Every message transmitted from the client to the server has a
+credentials (cb_cred) field of the type auth_gssapi_creds:
+
+\begin{verbatim}
+typedef struct _auth_gssapi_creds {
+        bool_t       auth_msg;
+        gss_buffer_desc client_handle;
+};
+\end{verbatim}
+
+The auth_msg field indicates whether the message is intended for the
+authentication mechanism for the actual server.  Any message whose
+auth_msg field is true is processed by the authentication mechanism;
+any message whose auth_msg is false is passed to the application
+server's dispatch function if authentication suceeds.  All messages
+must have an auth_msg of true until the context is established, since
+authentication cannot succeed until it is.
+
+The client_handle field contains the client handle obtained from the
+first call to the server.  On the first call, this field is empty.
+
+\subsection{GSS-API Authentication Flavor Procedures}
+
+The GSS-API authentication flavor uses standard RPC calls over the
+client handle it is provided for the interactions described in
+\ref{sec:algorithms}.  All of the following procedures require the
+auth_msg field in the credentials to be true; otherwise, the
+server-side authentication flavor will simply attempt to authenticate
+the caller and pass the call to the application server.  The
+server-side authentication flavor uses the no_dispatch variable to
+indicate that it has handled the call.
+
+\subsubsection{AUTH_GSSAPI_INIT, AUTH_GSSAPI_CONTINUE_INIT}
+
+Context initiation is performed via AUTH_GSSAPI_INIT and
+AUTH_GSSAPI_CONTINUE_INIT.  The former is used to transfer the first
+token generated by gss_init_sec_context, when no client handle is
+included in the credentials; the latter is used on subsequent calls,
+when a client handle is included.
+
+Both procedures take an argument of type auth_gssapi_init_arg and
+return results of the type auth_gssapi_init_res.
+
+\begin{verbatim}
+typedef struct _auth_gssapi_init_arg {
+        u_long       version;
+        gss_buffer_desc token;
+} auth_gssapi_init_arg;
+\end{verbatim}
+
+\begin{description}
+\item[version]  Three versions are presently defined.
+
+\begin{description}
+\item[1] The original version, as described in this document
+
+\item[2] In earlier versions of Secure there was a bug in the GSS-API
+library that affected the contents of accept_sec_context output
+tokens.  A client specifies version 2 to indicate that it expects the
+correct (fixed) behavior.  If the server indicates AUTH_BADCRED or
+AUTH_FAILED it does not understand this version, so the client should
+fall back to version 1.
+
+\item[3] Version three indicates that channel bindings are in use.
+The client must specify channel bindings with the version, and the
+server will as well.  If the server indicates AUTH_BADCRED or
+AUTH_FAILED it does not understand this version, so the client should
+fall back to version 2 (and cease specifying channel bindings).
+
+\item[4] The previous versions all used the old GSS-API krb5 mechanism
+oid; this version uses the new one specified in the RFC.  
+\end{description}
+
+\item[token] The token field contains the token generated by
+gss_init_sec_context.
+\end{description}
+
+\begin{verbatim}
+typedef struct _auth_gssapi_init_res {
+        u_long       version;
+        gss_buffer_desc client_handle;
+        gss_buffer_desc token;
+        OM_uint32 gss_major, gss_minor;
+        gss_buffer_desc signed_isn;
+} auth_gssapi_init_res;
+\end{verbatim}
+
+\begin{description}
+\item[version] There are two versions currently defined.
+\begin{description}
+\item[1] The original version, as described in this document.  This is
+the response version for {\it both} versions 1 and 2.  The Secure 1.1
+server will always return this version.
+
+\item[3] Version three indicates that the server specified channel
+bindings in response to a call arg version number of three.  The
+server must not specify this version unless the client does.
+\end{description}
+
+\item[client_handle] The client_handle field contains the client
+handle that the client must use in the credentials field in all
+subsequent RPC calls.  In response to AUTH_GSSAPI_CONTINUE_INIT, it is
+the same client handle that arrived in the credentials.
+
+\item[gss_major, gss_minor] The GSS-API error codes that resulted from
+processing the auth_gssapi_init_arg.  If gss_major is GSS_S_COMPLETE,
+the argument token was processed successfully.  Otherwise, gss_major
+and gss_minor contain the relevant major and minor status codes, and
+the context currently being negotiated is no longer valid.
+
+\item[token] In any response that the client is expecting another
+token (i.e.: gss_init_sec_context last returned GSS_S_CONTINUE), the
+token field contains the output token from gss_accept_sec_context.  If
+the client is not expecting a token and this field is not empty, an
+error has occurred.
+
+\item[signed_isn]  If the client is not expecting another token (i.e.:
+the previous call to gss_init_sec_context yielded a token and returned
+GSS_S_COMPLETE) or the supplied token completes the context, the
+signed_isn field contains the signed initial sequence number.  The
+server expects the first RPC call to have a sequence number one
+greater than the initial sequence number (so that the signed_isn block
+cannot be replayed).  If the client is expecting another token and the
+signed_isn field is not empty, an error has occurred.
+\end{description}
+
+\subsubsection{AUTH_GSSAPI_DESTROY}
+
+Context tear-down is performed via AUTH_GSSAPI_DESTROY.  This
+procedure takes no arguments and returns no results; it merely informs
+the server that the client wishes to destroy the established context.
+
+When a client wishes to tear down an established context between
+itself and a server, auth_gssapi_destroy first calls the
+AUTH_GSSAPI_DESTROY procedure.  The server authenticates the message
+and immediately sends a ``success'' response with no results.  The
+client and server then both independently call gss_delete_sec_context
+and discard the context-destruction token that is generated.
+
+No RPC error checking is performed by either the client or the server.
+The client waits a brief time for a success response from the server,
+but if none arrives it destroys the context anyway since presumably
+the user is waiting for the application to exit.  The server similar
+ignores any RPC errors since it knows that the client will ignore any
+errors that are reported.
+
+\subsection{RPC Call Authentication Implementation}
+
+Once the context has been established, all subsequent RPC calls are
+authenticated via the verifier described in section
+\ref{sec:algorithms}.
+
+auth_gssapi_marshall, invoked via AUTH_MARSHALL while the RPC call is
+being created on the client side, serializes the client_handle
+obtained during context initiation {\it in plaintext} as the
+credentials and serializes the current sequence number, sealed with
+gss_seal, as the verifier.
+
+auth_gssapi_wrap, invoked next via AUTH_WRAP, serializes a sealed
+token containing both the sequence number of the current call and the
+serialized arguments.
+
+_svcauth_gssapi, invoked on the server side by _authenticate, uses the
+client_handle contained in the credentials to look up the correct
+context and verifies the sequence number provided in the verifier; if
+the sequence number is not correct, it declares a potential replay
+attack.\footnote{Retransmitted packets will appear as replay attacks,
+of course.} The response verifier is set to the serialized sealed
+incremented sequence number.
+
+svc_auth_gssapi_unwrap, invoked when either the application server or
+_svcauth_gssapi (in response to an AUTH_GSSAPI authentication flavor
+message) attempts to read its arguments, deserialzes and unseals the
+block containing the current sequence number and serialized arguments.
+If the sequence number is incorrect, it declares a splicing attack;
+otherwise, it unserializes the arguments into the original structure.
+
+svc_auth_gssapi_wrap, invoked when either the application server or
+_svcauth_gssapi attempts to write its response, performs the same
+operation as auth_gssapi_wrap.
+
+auth_gssapi_validate, invoked by the client-side RPC mechanism when
+an RPC_SUCCESS response is received, verifies that the returned sequence
+number is one greater than the previous value sent by
+auth_gssapi_marshall.
+
+Finally, auth_gssapi_unwrap, invokved by the client-side RPC mechanism
+after auth_gssapi_validate succeeds, performs the same operation as
+svc_auth_gssapi_unwrap.
+
+If an RPC request generates an error message (a status of other than
+RPC_SUCCESS), auth_gssapi_refresh is called.  If the error status is
+AUTH_REJECTEDVERF, then the server rejected the sequence number as
+invalid or replayed.  The client guesses that, on some previous call,
+the server received a message but the server's response did not make
+it back to the client; this could happen if the packet got lost or if
+the server was being debugged and the client timed out waiting for it.
+As a result, the server is expected a higher sequence number than the
+client sent.  auth_gssapi_refresh increments the sequence number and
+returns true so that the call will be tried again.  The transport
+mechanism will only call auth_gssapi_refresh twice for each RPC
+request, so if some other error occurred an infinite loop will not
+result; however, it is unlikely the the client and server will be able
+to resynchronize after such an event.
+
+\subsection{Client State Information}
+
+The client-side GSS-API authentication flavor maintains an
+auth_gssapi_data structure for each authentication instance:
+
+\begin{verbatim}
+struct auth_gssapi_data {
+     bool_t established;
+     CLIENT *clnt;
+     gss_ctx_id_t context;
+     gss_buffer_desc client_handle;
+     u_long seq_num;
+     int def_cred;
+
+     /* pre-serialized ah_cred */
+     u_char cred_buf[MAX_AUTH_BYTES];
+     u_long cred_len;
+};
+\end{verbatim}
+
+The established field indicates whether the authentication context
+between the client and server has been established.  It is set to true
+when gss_init_sec_context returns GSS_S_COM\-PLETE.  When this field is
+false, the auth_gssapi functions marshall, validate, wrap, and unwrap
+mimic the ``no authentication'' flavor since there is no context with
+which to perform authentication functions.\footnote{This field is
+necessary because, when auth_gssapi_create calls clnt_call to make an
+RPC call, it has to have set the client's authentication flavor to
+AUTH_GSSAPI; otherwise, the service-side RPC mechanism will not know
+to dispatch the call to _svcauth_gssapi.  However, with the client's
+authentication flavor set, all of the authentication flavor's
+functions will be automatically invoked, even though they are not
+ready to operate.}
+
+The clnt field contains the RPC client structure that can be used to
+communicate with the GSS-API authentication flavor on the server.
+
+The context field contains the context structure created by
+gss_init_sec_context.
+
+The client_handle field contains the client handle used on all RPC
+calls except the first one; the handle is obtained as the result of
+the first call.
+
+The sequence_number field contains the sequence number that will be
+used when transmitting RPC calls to the server and verifing the
+server's responses after the context is initialized.
+
+The def_cred field is true if gss_init_sec_context created a default
+credential, in which case the authentication mechanism is responsible
+for releasing the default credential that gets automatically
+allocated.
+
+The cred_buf and cred_len fields contain the pre-serialized
+credentials structure used in each call.  This provides a small
+performance enhancement since the credentials structure does not
+change very often; the same pre-serialized version can be used on
+virtually every call.
+
+\subsection{Server State Information}
+\label{sec:server-state}
+
+The server-side GSS-API authentication flavor maintains an
+svcauth_gssapi_data structure for each established or partially
+established context:
+
+\begin{verbatim}
+typedef struct _svc_auth_gssapi_data {
+     bool_t established;
+     gss_ctx_id_t context;
+     gss_name_t client_name, server_name;
+     gss_cred_id_t server_creds;
+
+     u_long expiration;
+     u_long seq_num;
+     u_long key;
+
+     SVCAUTH svcauth;
+} svc_auth_gssapi_data;
+\end{verbatim}
+
+The established field indicates whether the context is fully
+established.
+
+The context field contains the context created by
+gss_accept_sec_context.
+
+The client_name field contains the client's authenticated name, as
+returned by gss_accept_sec_context.  _svcauth_gssapi sets the ``cooked
+credentials'' field of the RPC call structure to this value after the
+call is authenticated; the application server can use it to perform
+authorization.
+
+The server_name field contains the service name that the client
+established a context with.  This is useful if the application server
+registered more than one service name with the library; it allows the
+server to determine which service the client chose.
+
+The server_creds field contains the service credentials that the
+client established a context with.  It is used to avoid having to scan
+through the server_creds_list multiple times in the case that context
+establishment requires more than one round-trip to the server.
+
+The expiration field contains the expiration time of the context, as a
+Unix timestamp.  If a context has no expiration (time_rec is
+GSS_C_INDEFINITE), the expiration time is set to 24 hours in the
+future.  When the structure is created, before the context is
+established, the expiration time is initialized to small duration
+(currently 5 minutes) so that partially created and abandoned contexts
+will be expired quickly.
+
+The seq_num field is the current sequence number for the client.
+
+The key field is the client's key into the hash table (see below).
+The client_handle field sent to the client is the key treated as an
+arbitrary four-byte string.
+
+The svcauth field is a kludge that allows the svc_auth_gssapi
+functions to access the per-client data structure while processing a
+call.  One SVCAUTH structure is allocated for each client structure,
+and the svc_ah_private field is set to the corresponding client.  The
+client's svcauth field is then set to the new SVCAUTH structure, so
+that client_data->svcauth->svc_ah_private == client_data.  As each
+request is processed, the transport mechanism's xp_auth field is set
+to the client's svcauth field; thus, the server-side functions that
+dispatch to server-side authentication flavors can access an
+appropriate SVCAUTH structure, and the server-side authentication
+function that is called can determine the appropriate per-client
+structure from the SVCAUTH structure.
+
+The per-client structures are all stored both in a BSD 4.4 db library
+hash table and b-tree.  The hash table maps client handles (key
+fields) the client structures, and is used to look up client
+structures based on the client_handle field of a call's credentials
+structure.  The b-tree stores the client structures as keys, sorted by
+their expiration time.  Each time _svcauth_gssapi is activated, it
+traverses the tree and destroys all client structures that have
+expired.
+
+\end{document}