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