1\documentstyle[fullpage,12pt]{article} 2 3\title{GSS-API Extensions to Sun RPC} 4\date{Draft---\today} 5\author{Barry Jaspan} 6 7\setlength{\parskip}{.7\baselineskip} 8\setlength{\parindent}{0pt} 9 10\makeatletter 11\newcount\savecnt\savecnt=0 12\def\saveenum#1{\global\savecnt=\csname c@enum#1\endcsname} 13\def\restoreenum#1{\csname c@enum#1\endcsname=\savecnt} 14\makeatother 15 16%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17%% Make _ actually generate an _, and allow line-breaking after it. 18\let\underscore=\_ 19\catcode`_=13 20\def_{\underscore\penalty75\relax} 21%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 23\begin{document} 24 25 26{\setlength{\parskip}{0pt}\maketitle\tableofcontents} 27 28\section{Introduction} 29 30This document describes the integration of GSS-API authentication and 31security with Sun RPC. 32 33\section{Requirements} 34 35The requirements of the GSS-API authentication system for Sun RPC are: 36 37\begin{enumerate} 38\item It must provide mutual authentication between RPC clients and 39servers. 40 41\item It must provide for integrity checking and encryption of all 42procedure arguments and results passed over the network. 43\saveenum{i} 44\end{enumerate} 45 46The following features are desired, but not mandatory: 47 48\begin{enumerate} 49\restoreenum{i} 50\item It should provide for integrity checking and encryption of all 51``header information'' that specifies the program and procedure being 52called. 53 54\item It should obey the Sun RPC protocol so that clients using 55it can interoperate with existing servers. In this case, 56``interoperate'' means that existing servers will return an error code 57indicating that they do not understand the authentication flavor, but 58not that they do not understand the request at all. 59 60\item It should require minimal or no changes to the standard Sun RPC 61programming paradigm for either clients or servers so that existing 62code can use it with little or no effort. 63 64\item It should operate correctly with all the standard Sun RPC 65transport mechansims (e.g. UDP and TCP). 66\saveenum{i} 67\end{enumerate} 68 69\section{Functional Specification} 70 71This section describes the programmer's interface to the GSS-API 72authentication flavor. Knowledge of standard Sun RPC programming is 73assumed. 74 75\subsection{Client Side} 76 77A RPC client can select the GSS-API authentication flavor in the same 78way it can select any other authentication flavor, by setting the 79cl_auth field of the CLIENT structure to the appropriate value: 80 81\begin{verbatim} 82 clnt = clnt_create(server_host, PROG_NUM, PROG_VERS, protocol); 83 clnt->cl_auth = auth_gssapi_create(clnt, ...); 84\end{verbatim} 85 86There are two functions that create GSS-API authentication flavor 87structures for the cl_auth field, auth_gssapi_create and 88auth_gssapi_create_default. 89 90\begin{verbatim} 91AUTH *auth_gssapi_create(CLIENT *clnt, 92 OM_uint32 *major_status, 93 OM_uint32 *minor_status, 94 gss_cred_id_t claimant_cred_handle, 95 gss_name_t target_name, 96 gss_OID mech_type, 97 int req_flags, 98 int time_req, 99 gss_OID *actual_mech_type, 100 int *ret_flags, 101 OM_uint32 *time_rec); 102\end{verbatim} 103 104auth_gssapi_create creates a GSS-API authentication structure and 105provides most of the flexibility of gss_init_sec_context. The 106arguments have the same interpretation as those of 107gss_init_sec_context with the same name, except: 108 109\begin{description} 110\item[clnt] The CLIENT structure returned by client_create or one of 111its relatives. It is not modified. 112\end{description} 113 114auth_gssapi_create calls gss_init_sec_context as needed, passing each 115generated token to and processing each token returned from the RPC 116server specified by the RPC handle clnt. On return, if major_status 117is GSS_S_COMPLETE, the context has been established, the returned AUTH 118structure is valid, and all of the arguments filled in by 119gss_init_sec_context have the correct values. If major_status is not 120GSS_S_COMPLETE then it and minor_status contain error codes that can 121be passed to gss_display_status and the returned value is NULL. 122 123\begin{verbatim} 124AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name); 125\end{verbatim} 126 127auth_gssapi_create_default is a shorthand for auth_gssapi_create that 128attempts to create a context that provides procedure call and result 129integrity, using the default credentials and GSS-API mechanism. 130service_name is parsed as a GSS-API ``service'' name and used as the 131target name. The other arguments to auth_gssapi_create are as follows: 132 133\begin{verbatim} 134auth_gssapi_create(clnt, 135 &dummy, 136 &dummy, 137 GSS_C_NO_CREDENTIAL, 138 target_name, 139 GSS_C_NULL_OID, 140 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, 141 0, 142 NULL, 143 NULL, 144 NULL); 145\end{verbatim} 146 147Note that if the underlying default mechanism does not support data 148integrity (e.g. the trust mechanism), this function will fail. 149 150The GSS-API major and minor status codes can be interpreted with 151auth_gssapi_display_status: 152 153\begin{verbatim} 154void auth_gssapi_display_status(char *msg, OM_uint32 major, 155 OM_uint32 minor); 156\end{verbatim} 157 158All of the error messages associated with the major and minor status 159are displated on the standard error output, preceeded by the message 160``GSS-API authentication error $<$msg$>$:''. 161 162\subsection{Server Side} 163 164\subsubsection{Service Name Registration} 165 166An application server must register the service name(s) that it will 167use for GSS-API connections before any AUTH_GSSAPI requests will 168succeed. 169 170\begin{verbatim} 171typedef struct _auth_gssapi_name { 172 char *name; 173 gss_OID type; 174} auth_gssapi_name; 175 176bool_t _svcauth_gssapi_set_names(auth_gssapi_name *names, int num); 177\end{verbatim} 178 179names is an array of name specifications, each of which consists of a 180null-terminated ASCII representation of a name and the GSS-API name 181type that should be used to import it with gss_import_name. The 182name type ``gss_nt_service_name'' is recommended. 183 184\subsubsection{Calling Client and Service Identification} 185 186Each application server's dispatch function is passed two arguments, 187the transport mechanism (transp) and the RPC service request (rqstp). 188If the service request's credential flavor (rq_cred.oa_flavor) is 189AUTH_GSSAPI (300001)\footnote{The value 4 was originally used, but 190300001 has been officially assigned by the IETF.}, then the call has 191been authenticated. The rq_clntcred field of transp contains the 192gss_name_t of the authenticated caller and can be passed to 193gss_display_name to obtain a string represtation or gss_compare_name 194to compare it with other names. The rq_svccred field of transp 195contains the GSS-API context established with the caller and can be 196passed to gss_inquire_context. 197 198\subsubsection{Error Logging} 199 200An application server can register a function to be called when a 201failure occurs during GSS-API context establishment with 202_svcauth_set_log_badauth_func. 203 204\begin{verbatim} 205typedef void (*auth_gssapi_log_badauth_func)(OM_uint32 major, 206 OM_uint32 minor, 207 struct sockaddr_in *raddr, 208 caddr_t data); 209 210void _svcauth_set_log_badauth_func(auth_gssapi_log_badauth_func func, 211 caddr_t data); 212\end{verbatim} 213 214The function func is called each time gss_accept_sec_context fails. 215The major and minor arguments indicate the GSS-API major and minor 216status codes returned. The raddr field contains the INET socket that 217the request came from, and the data field contains the data argument 218of _svcauth_gssapi_set_log_badauth_func. 219 220An application server can register a function to be called when an RPC 221request with an invalid verifier arrives with 222_svcauth_set_log_badverf_func. 223 224\begin{verbatim} 225typedef void (*auth_gssapi_log_badverf_func)(gss_name_t client, 226 gss_name_t server, 227 struct svc_req *rqst, 228 struct rpc_msg *msg, 229 caddr_t data); 230 231void _svcauth_set_log_badverf_func(auth_gssapi_log_badverf_func func, 232 caddr_t data); 233\end{verbatim} 234 235The function specified in func is called each time an invalid verifier 236is received. The client and server fields identify the (falsely 237claimed) originating client and the server it originally authenticated 238to. The raddr and addrlen fields contain the INET socket that the 239request (claims to have) come from, and data contains the data 240argument of _svcauth_set_log_badverf_func. 241 242\section{Modifications to Sun RPC} 243 244The Sun RPC extensible authentication mechanism is designed to allow 245different authentication systems to be integrated into Sun RPC easily. 246Unfortunately, it has two drawbacks. First, the existing system has a 247number of non-general design properties that are intended specifically 248for Sun's Secure RPC, and second, the existing system has no concept 249of or ability to perform authentication-flavor-specific operations on 250function arguments and results passed over the wire. The first 251problem merely makes the system confusing, since a number of features 252touted as ``general'' do not make any sense for arbitrary 253authentication systems. The second problem is more substantial, and 254can only be corrected by modifications to Sun RPC internals. 255 256The following sections describe the necessary modifications to Sun 257RPC. 258 259\subsection{Client Side Authentication, AUTH Structure} 260 261The AUTH structure (figure \ref{fig:auth}) encapsulates the data and 262function pointers for an authentication flavor instance. It has been 263changed in two ways. 264 265\begin{figure}[htbp] 266\begin{verbatim} 267typedef struct { 268 struct opaque_auth ah_cred; 269 struct opaque_auth ah_verf; 270 union des_block ah_key; 271 struct auth_ops { 272 void (*ah_nextverf)(); 273 int (*ah_marshal)(); /* nextverf & serialize */ 274 int (*ah_validate)(); /* validate varifier */ 275 int (*ah_refresh)(); /* refresh credentials */ 276 int (*ah_wrap)(); /* encode data for wire */ 277 int (*ah_unwrap)(); /* decode data from wire */ 278 void (*ah_destroy)(); /* destroy this structure */ 279 } *ah_ops; 280 caddr_t ah_private; 281} AUTH; 282\end{verbatim} 283\caption{The AUTH structure, with the new function pointers ah_wrap 284and ah_unwrap.} 285\label{fig:auth} 286\end{figure} 287 288First, the new functions ah_wrap and ah_unwrap prepare function 289arguments and results for transmission over the wire. The 290authentication mechanism can use them to sign, encrypt, or perform any 291other operation on the data. Their prototype is: 292 293\begin{verbatim} 294bool_t ah_wrap(AUTH *auth, XDR *out_xdrs, xdrproc_t func, caddr_t ptr); 295bool_t ah_unwrap(AUTH *auth, XDR *in_xdrs, xdrproc_t func, caddr_t ptr); 296\end{verbatim} 297 298ah_wrap encodes function arguments for transmission. func and ptr are 299the XDR procedure and pointer that serialize the arguments, and 300out_xdrs is the xdr stream that the encoded arguments should be 301written to. ah_unwrap decodes function arguments received from the 302network. Its arguments are the converse of those to ah_wrap. 303 304It is the responsibility of RPC transport mechanisms to call an 305authorization flavor's ah_wrap and ah_unwrap functions when function 306arguments or results would normally be written to or read from the 307wire. Authorization flavors that do not need to perform any encoding 308or decoding can use the provided function authany_wrap for ah_wrap 309and ah_unwrap; it consists of the single statement ``return 310(*func)(out_xdrs, ptr)'' (or in_xdrs, as appropriate). 311 312Second, the function ah_refresh has been changed to take the RPC error 313message that resulted in its being called as an argument. This is 314necessary since the contents of the error message may dictate how 315ah_refresh should go about correcting the authentication failure. 316 317\subsection{Client Side Transport Mechanisms} 318 319Each client side transport mechanism must be modified to call the 320ah_wrap and ah_unwrap functions from the cl_auth field of the CLIENT 321structure during the call and reply process. The modification is 322fairly simple. For example, the UDP transport mechanism used to 323encode procedure calls like this: 324 325\begin{verbatim} 326 if ((! XDR_PUTLONG(xdrs, (long *)&proc)) || 327 (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || 328 (! (*xargs)(xdrs, argsp))) 329 return (cu->cu_error.re_status = RPC_CANTENCODEARGS); 330\end{verbatim} 331 332The last function call in the conditional serializes the arguments 333onto the xdr stream. This must be replaced with a call to the 334appropriate ah_wrap function: 335 336\begin{verbatim} 337 if ((! XDR_PUTLONG(xdrs, (long *)&proc)) || 338 (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || 339 (! AUTH_WRAP(cl->cl_auth, xdrs, xargs, argsp))) 340 return (cu->cu_error.re_status = RPC_CANTENCODEARGS); 341\end{verbatim} 342 343AUTH_WRAP is a macro that takes the four arguments for an ah_wrap 344function and extracts and calls the function pointer from the cl_auth 345structure with the specified arguments. 346 347Similarly, the transport mechanism must unwrap procedure results. 348Again, the UDP mechanism will be instructive. It used to deserialize 349function results like this: 350 351\begin{verbatim} 352 reply_msg.acpted_rply.ar_results.where = resultsp; 353 reply_msg.acpted_rply.ar_results.proc = xresults; 354 355 ok = xdr_replymsg(&reply_xdrs, &reply_msg); 356\end{verbatim} 357 358The problem here is that xdr_replymsg deserializes an entire reply 359message, including the results. Since xresults and resultsp are the 360function and pointer to decode the results, they will be automatically 361deserialized {\it without} ah_unwrap being invoked. The simplest 362solution (which is also the normal method used by the TCP mechanism) 363is to arrange to deserialize the function results explicitly: 364 365\begin{verbatim} 366 reply_msg.acpted_rply.ar_results.where = NULL; 367 reply_msg.acpted_rply.ar_results.proc = xdr_void; 368 369 if ((! xdr_replymsg(&reply_xdrs, &reply_msg)) || 370 (! AUTH_UNWRAP(cl->cl_auth, reply_xdrs, xresults, 371 resultsp))) { 372 return (cu->cu_error.re_status = RPC_CANTENCODEARGS); 373 } 374\end{verbatim} 375 376Since xdr_void does not read any data from the XDR stream, the 377function results are still available when AUTH_UNWRAP is called. Note 378that AUTH_UNWRAP should only be called on {\it successful} calls; if 379the reply message status is not RPC_SUCCESS there are no arguments to 380read. 381 382Currently, the UDP and TCP transport mechanisms has been 383converted.\footnote{The ``raw'' mechanism, for direct connections, has 384not been.} 385 386\subsection{Service Side Authentication, SVCAUTH and XPRT} 387 388Standard Sun RPC service-side authentication consists of a single 389function per authentication flavor; there is no concept of an AUTH 390structure containing function pointers and private data as with the 391client side. Previously, nothing else was necessary, because each 392flavor only did a single thing (authenticated individual calls in a 393stateless manner). More functions and state are now required, 394however; they are stored in the SVCAUTH structure, see figure 395\ref{fig:svcauth}. 396 397\begin{figure}[htbp] 398\begin{verbatim} 399typedef struct { 400 struct svc_auth_ops { 401 int (*svc_ah_wrap)(); 402 int (*svc_ah_unwrap)(); 403 } *svc_ah_ops; 404 caddr_t svc_ah_private; 405} SVCAUTH; 406\end{verbatim} 407\caption{The new SVCAUTH structure.} 408\label{fig:svcauth} 409\end{figure} 410 411There is one SVCAUTH structure per authentication flavor (there is a 412default, svc_auth_any, for existing authentication flavors that do not 413need the extra functionality). The svc_ah_wrap and svc_ah_unwrap 414perform the same logical function as their client-side counterparts. 415 416Just as with the client side, it is the responsibility of the 417transport mechanism to call the svc_ah_wrap and svc_ah_unwrap 418functions associated with the authentication flavor associated with 419each RPC call at the appropriate time. Unfortunately, the transport 420mechanism code does not have access to the RPC call structure 421containing the authenticator flavor because the RPC call structure 422itself is not passed as an argument to the necessary functions. The 423present solution is to add another argument to the transport mechanism 424structure, xp_auth, that stores the SVCAUTH of the {\it current} call 425on that mechanism; see figure \ref{fig:xprt}. xp_auth is initialized 426to svc_auth_any so that existing authentication mechanisms that do not 427set the field will still operate correctly. \footnote{This is not an 428great solution, because it forces each transport mechanism to be 429single threaded. The correct solution is to store the SVCAUTH 430associated with each RPC call in the RPC call structure; however, 431doing so would require changing a lot of code to pass around the RPC 432call structure that currently does not do so. Since other parts of 433Sun RPC use the XPRT structure in a non-reentrant way, the present 434solution does not make the situation any 435worse.}$^{\mbox{,}}$\footnote{A somewhat irrelevant side effect of 436adding SVCAUTH to XPRT is that the standard include file 437$<$rpc/rpc.h$>$ had to be changed to include $<$rpc/svc_auth$>$ before 438$<$rpc/svc.h$>$, whereas they used to be in the opposite order.} 439 440\begin{figure}[htbp] 441\begin{verbatim} 442typedef struct { 443 int xp_sock; 444 u_short xp_port; /* associated port number */ 445 struct xp_ops { 446 bool_t (*xp_recv)(); /* receive incomming requests */ 447 enum xprt_stat (*xp_stat)(); /* get transport status */ 448 bool_t (*xp_getargs)(); /* get arguments */ 449 bool_t (*xp_reply)(); /* send reply */ 450 bool_t (*xp_freeargs)();/* free mem allocated for args */ 451 void (*xp_destroy)(); /* destroy this struct */ 452 } *xp_ops; 453 int xp_addrlen; /* length of remote address */ 454 struct sockaddr_in xp_raddr; /* remote address */ 455 struct opaque_auth xp_verf; /* raw response verifier */ 456 SVCAUTH *xp_auth; /* auth flavor of current req */ 457 caddr_t xp_p1; /* private */ 458 caddr_t xp_p2; /* private */ 459} SVCXPRT; 460\end{verbatim} 461\caption{The modified XPRT structure, with the xp_auth field.} 462\label{fig:xprt} 463\end{figure} 464 465Finally, with the modified XPRT structure carrying around the 466authentication flavor structure, the functions that serialize and 467deserialize function arguments and results must be modified to use the 468svc_ah_wrap and svc_ah_unwrap functions. Each service-side transport 469mechanism has getargs and reply functions that must be modified to use 470the SVCAUTH_UNWRAP and SVCAUTH_WRAP macros, respectively, in a manner 471completely parallel to the client side. 472 473\subsection{Authenticated Service Identification, svc_req} 474 475Sun RPC provides the authenticated credentials of a client to the 476application server via rq_clntcred (``cooked credentials'') field of 477the service request (svc_req) structure. In many authentication 478systems, services are also named entities, and there is no reason that 479an RPC should be restricted to accepting connections as a single 480authenticated service name. However, access control decisions may be 481based on the service name a client authenticated to, so that 482information must be available to the application server. 483 484Figure \ref{fig:svc-req} shows the modified service request structure 485that contains a single new field, rq_svccred. Like rq_clntcred, the 486authentication flavor is responsible for setting rq_svccred to the 487``cooked'' service credentials associated with a given RPC call. 488Authentication flavors that do not have the concept of service names 489can of course leave this field blank. 490 491\begin{figure}[htbp] 492\begin{verbatim} 493struct svc_req { 494 u_long rq_prog; /* service program number */ 495 u_long rq_vers; /* service protocol version */ 496 u_long rq_proc; /* the desired procedure */ 497 struct opaque_auth rq_cred; /* raw creds from the wire */ 498 caddr_t rq_clntcred; /* read only cooked client cred */ 499 caddr_t rq_svccred; /* read only cooked svc cred */ 500 SVCXPRT *rq_xprt; /* associated transport */ 501}; 502\end{verbatim} 503\caption{The modified svc_req structure, with the rq_svccred field.} 504\label{fig:svc-req} 505\end{figure} 506 507 508 509\subsection{Authentication Negotiation, no_dispatch} 510 511In order to avoid having to transmit a full set of authentication 512information with every call, the service-side authentication mechanism 513must save state between calls. Establishing that state may require 514multiple messages between the client-side and service-side 515authentication mechanisms. The client-side authentication mechanism 516can make arbitrary RPC calls to the server simply by requiring the 517programmer to specify the CLIENT structure to the authentication 518flavor initialization routine. The service side, however, is more 519complex. In the normal course of events, an RPC call comes in, is 520authenticated, and is then dispatched to the appropriate procedure. 521For client- and service-side authentication flavors to communicate 522independent of the server implemented above the RPC layer, the 523service-side flavor must be able to send a reply to the client 524directly and {\it prevent} the call from being dispatched. 525 526This is implemented by a simple modification to the _authenticate 527routine, which dispatches each RPC call to the appropriate 528authentication flavor; see figure \ref{fig:authenticate}. It takes an 529additional argument, no_dispatch, that instructs the mechanism not to 530dispatch the RPC call to the specified procedure. 531 532\begin{figure}[htbp] 533\begin{verbatim} 534 why=_authenticate(&r, &msg, &no_dispatch); 535 if (why != AUTH_OK) { 536 svcerr_auth(xprt, why); 537 goto call_done; 538 } else if (no_dispatch) { 539 goto call_done; 540 } 541\end{verbatim} 542\caption{A call to the modified _authenticate.} 543\label{fig:authenticate} 544\end{figure} 545 546If _authenticate sets no_dispatch to true, the call is considered 547finished and no procedure dispatch takes place. Presumably, an 548authentication flavor that sets no_dispatch to true also replies to 549the RPC call with svc_sendreply. Authentication flavors that do not 550modify no_dispatch implicitly leave it set to false, so the normal 551dispatch takes place. 552 553\subsection{Affected Files} 554 555Table \ref{tab:modfiles} lists the files that were 556affected for each of the modifications described in previous sections. 557 558\begin{table}[htbp] 559\centering 560\caption{Files modified for each change to Sun RPC.} 561\label{tab:modfiles} 562\begin{tabular}{ll} 563AUTH structure & auth.h \\ 564 & auth_none.c \\ 565 & auth_exit.c \\ 566 & auth_any.c \\ 567Client Transport Mechanisms & clnt_udp.c \\ 568 & clnt_tcp.c \\ 569SVCAUTH and XPRT structures & rpc.h \\ 570 & svc.h \\ 571 & svc_auth.h \\ 572 & svc.c \\ 573 & svc_auth.c \\ 574 & svc_auth_any.c \\ 575 & svc_auth_unix.c \\ 576Server Transport Mechanisms & svc_udp.c \\ 577 & svc_tcp.c 578\end{tabular} 579\end{table} 580 581\section{GSS-API Authentication Flavor} 582 583The following sections describe the implementation of the GSS-API 584authentication flavor for Sun RPC. 585 586\subsection{Authentication Algorithms} 587\label{sec:algorithms} 588 589\subsubsection{Context Initiation} 590 591The client creates a GSS-API context with the server each time it 592calls auth_gssapi_create. The context is created using the standard 593gss_init_sec_context and gss_accept_sec_context function calls. The 594generated tokens are passed between the client and server as arguments 595and results of normal RPC calls. 596 597The client side, in auth_gssapi_create, performs the following steps 598to initiate a context: 599 600\begin{enumerate} 601\item\label{item:process-token} The client calls gss_init_sec_context. 602On the first such call, no input token is provided; on subsequent 603calls, the token received from the server is provided. 604 605\item If gss_init_sec_context produces an output token: 606 607\begin{enumerate} 608\item The client transmits the token to the server, identifying itself 609with client_handle if it has already been received (see next step). 610The return value from the server will contain a client_handle and one 611or both of a token and a signed initial sequence number. 612 613\item If this is the first response from the server, the client_handle 614is stored for subsequent calls. Otherwise, the client_handle should be 615the same as returned on the previous call. 616 617\item If the response contains a signed initian sequence number but 618the context is not yet established, then the response also contains a 619token that will established the context. The signed initial sequence 620number is stored. 621 622\item If the response contains a token, step \ref{item:process-token} 623repeated. 624\end{enumerate} 625 626\item The signed initial sequence number is verified using the 627established context. 628\end{enumerate} 629 630The server side, in _svcauth_gssapi, performs the following steps to 631initiate a context: 632 633\begin{enumerate} 634\item If a call arrives with no client_handle, a new client_handle is 635allocated and stored in the database. Otherwise, the client's 636previous state is is looked up in the database. 637 638\item The received token is passed to gss_accept_sec_context. If an 639output token is generated, it is returned to the client. Note that 640since the application server may have registered multiple service 641names and there is no way to determine {\it a priori} which service a 642token is for, _svcauth_gssapi calls gss_accept_sec_context once for 643each registered credential until one of them succeeds. The code 644assumes that GSS_S_FAILURE is the only error that can result from a 645credential mismatch, so any other error terminates the loop 646immediately. 647 648\item If the context is established, the server signs an initial 649sequence number and returns it to the client. 650\end{enumerate} 651 652Note that these algorithms require context establishment to be 653synchronous. If gss_init_sec_context returns GSS_S_COMPLETE upon 654processing a token, it will either produce a token or not. If it 655does, then gss_accept_sec_context will return GSS_S_COMPLETE when that 656token is processed; if it does not, then gss_accept_sec_context 657already returned GSS_S_COMPLETE (and presumably returned the token 658that caused gss_init_sec_context to return GSS_S_COMPLETE when 659processed). The reverse is also true. 660 661\subsubsection{RPC Calls} 662 663After the GSS-API context is established, both the server and the 664client possess a client handle and a corresponding sequence number. 665Each call from the client contains the client handle as the 666``credential'' so that the server can identify which context to apply 667to the call. 668 669Each client call and server response includes a ``verifier'' that 670contains the sealed current sequence number.\footnote{In a future 671version, the verifier will also contain a signature block for the call 672header, including the procedure number called.} The sequence number 673prevents replay attacks\footnote{Although some GSS-API mechanisms 674provide replay detection themselves, not all of them do; explicitly 675including the sequence number in the RPC therefore provides better 676end-to-end security}, but by itself it does not prevent splicing 677attacks. 678 679Each procedure argument and result block consists of the current 680sequence number and the actual serialized argument string, all sealed 681with gss_seal. Combining the sequence number with the argument/result 682data prevents splicing attacks. 683 684The sequence number is incremented by one for each RPC call and by one 685for each response. The client and server will both reject messages 686that do not contain the expected sequence number. Packets 687retransmitted by the client should use the {\it same} sequence number 688as the original packet, since even if the server receives multiple 689copies only one will be honored. 690 691\subsection{RPC Call Credential Structure} 692 693Every message transmitted from the client to the server has a 694credentials (cb_cred) field of the type auth_gssapi_creds: 695 696\begin{verbatim} 697typedef struct _auth_gssapi_creds { 698 bool_t auth_msg; 699 gss_buffer_desc client_handle; 700}; 701\end{verbatim} 702 703The auth_msg field indicates whether the message is intended for the 704authentication mechanism for the actual server. Any message whose 705auth_msg field is true is processed by the authentication mechanism; 706any message whose auth_msg is false is passed to the application 707server's dispatch function if authentication succeeds. All messages 708must have an auth_msg of true until the context is established, since 709authentication cannot succeed until it is. 710 711The client_handle field contains the client handle obtained from the 712first call to the server. On the first call, this field is empty. 713 714\subsection{GSS-API Authentication Flavor Procedures} 715 716The GSS-API authentication flavor uses standard RPC calls over the 717client handle it is provided for the interactions described in 718\ref{sec:algorithms}. All of the following procedures require the 719auth_msg field in the credentials to be true; otherwise, the 720server-side authentication flavor will simply attempt to authenticate 721the caller and pass the call to the application server. The 722server-side authentication flavor uses the no_dispatch variable to 723indicate that it has handled the call. 724 725\subsubsection{AUTH_GSSAPI_INIT, AUTH_GSSAPI_CONTINUE_INIT} 726 727Context initiation is performed via AUTH_GSSAPI_INIT and 728AUTH_GSSAPI_CONTINUE_INIT. The former is used to transfer the first 729token generated by gss_init_sec_context, when no client handle is 730included in the credentials; the latter is used on subsequent calls, 731when a client handle is included. 732 733Both procedures take an argument of type auth_gssapi_init_arg and 734return results of the type auth_gssapi_init_res. 735 736\begin{verbatim} 737typedef struct _auth_gssapi_init_arg { 738 u_long version; 739 gss_buffer_desc token; 740} auth_gssapi_init_arg; 741\end{verbatim} 742 743\begin{description} 744\item[version] Three versions are presently defined. 745 746\begin{description} 747\item[1] The original version, as described in this document 748 749\item[2] In earlier versions of Secure there was a bug in the GSS-API 750library that affected the contents of accept_sec_context output 751tokens. A client specifies version 2 to indicate that it expects the 752correct (fixed) behavior. If the server indicates AUTH_BADCRED or 753AUTH_FAILED it does not understand this version, so the client should 754fall back to version 1. 755 756\item[3] Version three indicates that channel bindings are in use. 757The client must specify channel bindings with the version, and the 758server will as well. If the server indicates AUTH_BADCRED or 759AUTH_FAILED it does not understand this version, so the client should 760fall back to version 2 (and cease specifying channel bindings). 761 762\item[4] The previous versions all used the old GSS-API krb5 mechanism 763oid; this version uses the new one specified in the RFC. 764\end{description} 765 766\item[token] The token field contains the token generated by 767gss_init_sec_context. 768\end{description} 769 770\begin{verbatim} 771typedef struct _auth_gssapi_init_res { 772 u_long version; 773 gss_buffer_desc client_handle; 774 gss_buffer_desc token; 775 OM_uint32 gss_major, gss_minor; 776 gss_buffer_desc signed_isn; 777} auth_gssapi_init_res; 778\end{verbatim} 779 780\begin{description} 781\item[version] There are two versions currently defined. 782\begin{description} 783\item[1] The original version, as described in this document. This is 784the response version for {\it both} versions 1 and 2. The Secure 1.1 785server will always return this version. 786 787\item[3] Version three indicates that the server specified channel 788bindings in response to a call arg version number of three. The 789server must not specify this version unless the client does. 790\end{description} 791 792\item[client_handle] The client_handle field contains the client 793handle that the client must use in the credentials field in all 794subsequent RPC calls. In response to AUTH_GSSAPI_CONTINUE_INIT, it is 795the same client handle that arrived in the credentials. 796 797\item[gss_major, gss_minor] The GSS-API error codes that resulted from 798processing the auth_gssapi_init_arg. If gss_major is GSS_S_COMPLETE, 799the argument token was processed successfully. Otherwise, gss_major 800and gss_minor contain the relevant major and minor status codes, and 801the context currently being negotiated is no longer valid. 802 803\item[token] In any response that the client is expecting another 804token (i.e.: gss_init_sec_context last returned GSS_S_CONTINUE), the 805token field contains the output token from gss_accept_sec_context. If 806the client is not expecting a token and this field is not empty, an 807error has occurred. 808 809\item[signed_isn] If the client is not expecting another token (i.e.: 810the previous call to gss_init_sec_context yielded a token and returned 811GSS_S_COMPLETE) or the supplied token completes the context, the 812signed_isn field contains the signed initial sequence number. The 813server expects the first RPC call to have a sequence number one 814greater than the initial sequence number (so that the signed_isn block 815cannot be replayed). If the client is expecting another token and the 816signed_isn field is not empty, an error has occurred. 817\end{description} 818 819\subsubsection{AUTH_GSSAPI_DESTROY} 820 821Context tear-down is performed via AUTH_GSSAPI_DESTROY. This 822procedure takes no arguments and returns no results; it merely informs 823the server that the client wishes to destroy the established context. 824 825When a client wishes to tear down an established context between 826itself and a server, auth_gssapi_destroy first calls the 827AUTH_GSSAPI_DESTROY procedure. The server authenticates the message 828and immediately sends a ``success'' response with no results. The 829client and server then both independently call gss_delete_sec_context 830and discard the context-destruction token that is generated. 831 832No RPC error checking is performed by either the client or the server. 833The client waits a brief time for a success response from the server, 834but if none arrives it destroys the context anyway since presumably 835the user is waiting for the application to exit. The server similar 836ignores any RPC errors since it knows that the client will ignore any 837errors that are reported. 838 839\subsection{RPC Call Authentication Implementation} 840 841Once the context has been established, all subsequent RPC calls are 842authenticated via the verifier described in section 843\ref{sec:algorithms}. 844 845auth_gssapi_marshall, invoked via AUTH_MARSHALL while the RPC call is 846being created on the client side, serializes the client_handle 847obtained during context initiation {\it in plaintext} as the 848credentials and serializes the current sequence number, sealed with 849gss_seal, as the verifier. 850 851auth_gssapi_wrap, invoked next via AUTH_WRAP, serializes a sealed 852token containing both the sequence number of the current call and the 853serialized arguments. 854 855_svcauth_gssapi, invoked on the server side by _authenticate, uses the 856client_handle contained in the credentials to look up the correct 857context and verifies the sequence number provided in the verifier; if 858the sequence number is not correct, it declares a potential replay 859attack.\footnote{Retransmitted packets will appear as replay attacks, 860of course.} The response verifier is set to the serialized sealed 861incremented sequence number. 862 863svc_auth_gssapi_unwrap, invoked when either the application server or 864_svcauth_gssapi (in response to an AUTH_GSSAPI authentication flavor 865message) attempts to read its arguments, deserialzes and unseals the 866block containing the current sequence number and serialized arguments. 867If the sequence number is incorrect, it declares a splicing attack; 868otherwise, it unserializes the arguments into the original structure. 869 870svc_auth_gssapi_wrap, invoked when either the application server or 871_svcauth_gssapi attempts to write its response, performs the same 872operation as auth_gssapi_wrap. 873 874auth_gssapi_validate, invoked by the client-side RPC mechanism when 875an RPC_SUCCESS response is received, verifies that the returned sequence 876number is one greater than the previous value sent by 877auth_gssapi_marshall. 878 879Finally, auth_gssapi_unwrap, invoked by the client-side RPC mechanism 880after auth_gssapi_validate succeeds, performs the same operation as 881svc_auth_gssapi_unwrap. 882 883If an RPC request generates an error message (a status of other than 884RPC_SUCCESS), auth_gssapi_refresh is called. If the error status is 885AUTH_REJECTEDVERF, then the server rejected the sequence number as 886invalid or replayed. The client guesses that, on some previous call, 887the server received a message but the server's response did not make 888it back to the client; this could happen if the packet got lost or if 889the server was being debugged and the client timed out waiting for it. 890As a result, the server is expected a higher sequence number than the 891client sent. auth_gssapi_refresh increments the sequence number and 892returns true so that the call will be tried again. The transport 893mechanism will only call auth_gssapi_refresh twice for each RPC 894request, so if some other error occurred an infinite loop will not 895result; however, it is unlikely the the client and server will be able 896to resynchronize after such an event. 897 898\subsection{Client State Information} 899 900The client-side GSS-API authentication flavor maintains an 901auth_gssapi_data structure for each authentication instance: 902 903\begin{verbatim} 904struct auth_gssapi_data { 905 bool_t established; 906 CLIENT *clnt; 907 gss_ctx_id_t context; 908 gss_buffer_desc client_handle; 909 u_long seq_num; 910 int def_cred; 911 912 /* pre-serialized ah_cred */ 913 u_char cred_buf[MAX_AUTH_BYTES]; 914 u_long cred_len; 915}; 916\end{verbatim} 917 918The established field indicates whether the authentication context 919between the client and server has been established. It is set to true 920when gss_init_sec_context returns GSS_S_COM\-PLETE. When this field is 921false, the auth_gssapi functions marshall, validate, wrap, and unwrap 922mimic the ``no authentication'' flavor since there is no context with 923which to perform authentication functions.\footnote{This field is 924necessary because, when auth_gssapi_create calls clnt_call to make an 925RPC call, it has to have set the client's authentication flavor to 926AUTH_GSSAPI; otherwise, the service-side RPC mechanism will not know 927to dispatch the call to _svcauth_gssapi. However, with the client's 928authentication flavor set, all of the authentication flavor's 929functions will be automatically invoked, even though they are not 930ready to operate.} 931 932The clnt field contains the RPC client structure that can be used to 933communicate with the GSS-API authentication flavor on the server. 934 935The context field contains the context structure created by 936gss_init_sec_context. 937 938The client_handle field contains the client handle used on all RPC 939calls except the first one; the handle is obtained as the result of 940the first call. 941 942The sequence_number field contains the sequence number that will be 943used when transmitting RPC calls to the server and verifying the 944server's responses after the context is initialized. 945 946The def_cred field is true if gss_init_sec_context created a default 947credential, in which case the authentication mechanism is responsible 948for releasing the default credential that gets automatically 949allocated. 950 951The cred_buf and cred_len fields contain the pre-serialized 952credentials structure used in each call. This provides a small 953performance enhancement since the credentials structure does not 954change very often; the same pre-serialized version can be used on 955virtually every call. 956 957\subsection{Server State Information} 958\label{sec:server-state} 959 960The server-side GSS-API authentication flavor maintains an 961svcauth_gssapi_data structure for each established or partially 962established context: 963 964\begin{verbatim} 965typedef struct _svc_auth_gssapi_data { 966 bool_t established; 967 gss_ctx_id_t context; 968 gss_name_t client_name, server_name; 969 gss_cred_id_t server_creds; 970 971 u_long expiration; 972 u_long seq_num; 973 u_long key; 974 975 SVCAUTH svcauth; 976} svc_auth_gssapi_data; 977\end{verbatim} 978 979The established field indicates whether the context is fully 980established. 981 982The context field contains the context created by 983gss_accept_sec_context. 984 985The client_name field contains the client's authenticated name, as 986returned by gss_accept_sec_context. _svcauth_gssapi sets the ``cooked 987credentials'' field of the RPC call structure to this value after the 988call is authenticated; the application server can use it to perform 989authorization. 990 991The server_name field contains the service name that the client 992established a context with. This is useful if the application server 993registered more than one service name with the library; it allows the 994server to determine which service the client chose. 995 996The server_creds field contains the service credentials that the 997client established a context with. It is used to avoid having to scan 998through the server_creds_list multiple times in the case that context 999establishment requires more than one round-trip to the server. 1000 1001The expiration field contains the expiration time of the context, as a 1002Unix timestamp. If a context has no expiration (time_rec is 1003GSS_C_INDEFINITE), the expiration time is set to 24 hours in the 1004future. When the structure is created, before the context is 1005established, the expiration time is initialized to small duration 1006(currently 5 minutes) so that partially created and abandoned contexts 1007will be expired quickly. 1008 1009The seq_num field is the current sequence number for the client. 1010 1011The key field is the client's key into the hash table (see below). 1012The client_handle field sent to the client is the key treated as an 1013arbitrary four-byte string. 1014 1015The svcauth field is a kludge that allows the svc_auth_gssapi 1016functions to access the per-client data structure while processing a 1017call. One SVCAUTH structure is allocated for each client structure, 1018and the svc_ah_private field is set to the corresponding client. The 1019client's svcauth field is then set to the new SVCAUTH structure, so 1020that client_data->svcauth->svc_ah_private == client_data. As each 1021request is processed, the transport mechanism's xp_auth field is set 1022to the client's svcauth field; thus, the server-side functions that 1023dispatch to server-side authentication flavors can access an 1024appropriate SVCAUTH structure, and the server-side authentication 1025function that is called can determine the appropriate per-client 1026structure from the SVCAUTH structure. 1027 1028The per-client structures are all stored both in a BSD 4.4 db library 1029hash table and b-tree. The hash table maps client handles (key 1030fields) the client structures, and is used to look up client 1031structures based on the client_handle field of a call's credentials 1032structure. The b-tree stores the client structures as keys, sorted by 1033their expiration time. Each time _svcauth_gssapi is activated, it 1034traverses the tree and destroys all client structures that have 1035expired. 1036 1037\end{document} 1038