1
2
3
4
5
6
7Network Working Group                                          M. Eisler
8Request for Comments: 2203                                       A. Chiu
9Category: Standards Track                                        L. Ling
10                                                          September 1997
11
12
13                   RPCSEC_GSS Protocol Specification
14
15Status of this Memo
16
17   This document specifies an Internet standards track protocol for the
18   Internet community, and requests discussion and suggestions for
19   improvements.  Please refer to the current edition of the "Internet
20   Official Protocol Standards" (STD 1) for the standardization state
21   and status of this protocol.  Distribution of this memo is unlimited.
22
23Abstract
24
25   This memo describes an ONC/RPC security flavor that allows RPC
26   protocols to access the Generic Security Services Application
27   Programming Interface (referred to henceforth as GSS-API).
28
29Table of Contents
30
31   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
32   2.  The ONC RPC Message Protocol . . . . . . . . . . . . . . . . . 2
33   3.  Flavor Number Assignment . . . . . . . . . . . . . . . . . . . 3
34   4.  New auth_stat Values . . . . . . . . . . . . . . . . . . . . . 3
35   5.  Elements of the RPCSEC_GSS Security Protocol . . . . . . . . . 3
36   5.1.  Version Selection  . . . . . . . . . . . . . . . . . . . . . 5
37   5.2.  Context Creation . . . . . . . . . . . . . . . . . . . . . . 5
38   5.2.1.  Mechanism and QOP Selection  . . . . . . . . . . . . . . . 5
39   5.2.2.  Context Creation Requests  . . . . . . . . . . . . . . . . 6
40   5.2.3.  Context Creation Responses . . . . . . . . . . . . . . . . 8
41   5.2.3.1.  Context Creation Response - Successful Acceptance  . . . 8
42   5.2.3.1.1.  Client Processing of Successful Context Creation
43               Responses  . . . . . . . . . . . . . . . . . . . . . . 9
44   5.2.3.2.  Context Creation Response - Unsuccessful Cases . . . . . 9
45   5.3.  RPC Data Exchange  . . . . . . . . . . . . . . . . . . . .  10
46   5.3.1.  RPC Request Header . . . . . . . . . . . . . . . . . . .  10
47   5.3.2.  RPC Request Data . . . . . . . . . . . . . . . . . . . .  11
48   5.3.2.1.  RPC Request Data - No Data Integrity . . . . . . . . .  11
49   5.3.2.2.  RPC Request Data - With Data Integrity . . . . . . . .  11
50   5.3.2.3.  RPC Request Data - With Data Privacy . . . . . . . . .  12
51   5.3.3.  Server Processing of RPC Data Requests . . . . . . . . .  12
52   5.3.3.1.  Context Management . . . . . . . . . . . . . . . . . .  12
53   5.3.3.2.  Server Reply - Request Accepted  . . . . . . . . . . .  14
54   5.3.3.3.  Server Reply - Request Denied  . . . . . . . . . . . .  15
55
56
57
58Eisler, et. al.             Standards Track                     [Page 1]
59
60RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
61
62
63   5.3.3.4.  Mapping of GSS-API Errors to Server Responses  . . . .  16
64   5.3.3.4.1.  GSS_GetMIC() Failure . . . . . . . . . . . . . . . .  16
65   5.3.3.4.2.  GSS_VerifyMIC() Failure  . . . . . . . . . . . . . .  16
66   5.3.3.4.3.  GSS_Unwrap() Failure . . . . . . . . . . . . . . . .  16
67   5.3.3.4.4.  GSS_Wrap() Failure . . . . . . . . . . . . . . . . .  16
68   5.4.  Context Destruction  . . . . . . . . . . . . . . . . . . .  17
69   6.  Set of GSS-API Mechanisms  . . . . . . . . . . . . . . . . .  17
70   7.  Security Considerations  . . . . . . . . . . . . . . . . . .  18
71   7.1.  Privacy of Call Header . . . . . . . . . . . . . . . . . .  18
72   7.2.  Sequence Number Attacks  . . . . . . . . . . . . . . . . .  18
73   7.2.1.  Sequence Numbers Above the Window  . . . . . . . . . . .  18
74   7.2.2.  Sequence Numbers Within or Below the Window  . . . . . .  18
75   7.3.  Message Stealing Attacks . . . . . . . . . . . . . . . . .  19
76   Appendix A. GSS-API Major Status Codes . . . . . . . . . . . . .  20
77   Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . .  22
78   Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . .  23
79
801.  Introduction
81
82   This document describes the protocol used by the RPCSEC_GSS security
83   flavor.  Security flavors have been called authentication flavors for
84   historical reasons. This memo recognizes that there are two other
85   security services besides authentication, integrity, and privacy, and
86   so defines a new RPCSEC_GSS security flavor.
87
88   The protocol is described using the XDR language [Srinivasan-xdr].
89   The reader is assumed to be familiar with ONC RPC and the security
90   flavor mechanism [Srinivasan-rpc].  The reader is also assumed to be
91   familiar with the GSS-API framework [Linn].  The RPCSEC_GSS security
92   flavor uses GSS-API interfaces to provide security services that are
93   independent of the underlying security mechanism.
94
952.  The ONC RPC Message Protocol
96
97   This memo refers to the following XDR types of the ONC RPC protocol,
98   which are described in the document entitled Remote Procedure Call
99   Protocol Specification Version 2 [Srinivasan-rpc]:
100
101      msg_type
102      reply_stat
103      auth_flavor
104      accept_stat
105      reject_stat
106      auth_stat
107      opaque_auth
108      rpc_msg
109      call_body
110      reply_body
111
112
113
114Eisler, et. al.             Standards Track                     [Page 2]
115
116RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
117
118
119      accepted_reply
120      rejected_reply
121
1223.  Flavor Number Assignment
123
124   The RPCSEC_GSS security flavor has been assigned the value of 6:
125
126      enum auth_flavor {
127          ...
128          RPCSEC_GSS = 6      /* RPCSEC_GSS security flavor */
129      };
130
1314.  New auth_stat Values
132
133   RPCSEC_GSS requires the addition of two new values to the auth_stat
134   enumerated type definition:
135
136      enum auth_stat {
137              ...
138              /*
139               * RPCSEC_GSS errors
140               */
141              RPCSEC_GSS_CREDPROBLEM = 13,
142              RPCSEC_GSS_CTXPROBLEM = 14
143      };
144
145   The descriptions of these two new values are defined later in this
146   memo.
147
1485.  Elements of the RPCSEC_GSS Security Protocol
149
150   An RPC session based on the RPCSEC_GSS security flavor consists of
151   three phases: context creation, RPC data exchange, and context
152   destruction.  In the following discussion, protocol elements for
153   these three phases are described.
154
155   The following description of the RPCSEC_GSS protocol uses some of the
156   definitions within XDR language description of the RPC protocol.
157
158   Context creation and destruction use control messages that are not
159   dispatched to service procedures registered by an RPC server.  The
160   program and version numbers used in these control messages are the
161   same as the RPC service's program and version numbers.  The procedure
162   number used is NULLPROC (zero).  A field in the credential
163   information (the gss_proc field which is defined in the
164   rpc_gss_cred_t structure below) specifies whether a message is to be
165   interpreted as a control message or a regular RPC message.  If this
166   field is set to RPCSEC_GSS_DATA, no control action is implied; in
167
168
169
170Eisler, et. al.             Standards Track                     [Page 3]
171
172RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
173
174
175   this case, it is a regular data message.  If this field is set to any
176   other value, a control action is implied.  This is described in the
177   following sections.
178
179   Just as with normal RPC data exchange messages, the transaction
180   identifier (the xid field in struct rpc_msg), should be set to unique
181   values on each call for context creation and context destruction.
182
183   The following definitions are used for describing the protocol.
184
185      /* RPCSEC_GSS control procedures */
186
187
188      enum rpc_gss_proc_t {
189              RPCSEC_GSS_DATA = 0,
190              RPCSEC_GSS_INIT = 1,
191              RPCSEC_GSS_CONTINUE_INIT = 2,
192              RPCSEC_GSS_DESTROY = 3
193      };
194
195      /* RPCSEC_GSS services */
196
197      enum rpc_gss_service_t {
198          /* Note: the enumerated value for 0 is reserved. */
199          rpc_gss_svc_none = 1,
200          rpc_gss_svc_integrity = 2,
201          rpc_gss_svc_privacy = 3
202      };
203
204      /* Credential */
205
206      /*
207       * Note: version 0 is reserved for possible future
208       * definition of a version negotiation protocol
209       *
210       */
211      #define RPCSEC_GSS_VERS_1 1
212
213      struct rpc_gss_cred_t {
214          union switch (unsigned int version) { /* version of
215                                                      RPCSEC_GSS */
216          case RPCSEC_GSS_VERS_1:
217              struct {
218                  rpc_gss_proc_t gss_proc;  /* control procedure */
219                  unsigned int seq_num;   /* sequence number */
220                  rpc_gss_service_t service; /* service used */
221                  opaque handle<>;       /* context handle */
222              } rpc_gss_cred_vers_1_t;
223
224
225
226Eisler, et. al.             Standards Track                     [Page 4]
227
228RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
229
230
231          }
232      };
233
234      /* Maximum sequence number value */
235
236      #define MAXSEQ 0x80000000
237
2385.1.  Version Selection
239
240   This document defines just one protocol version (RPCSEC_GSS_VERS_1).
241   The client should assume that the server supports RPCSEC_GSS_VERS_1
242   and issue a Context Creation message (as described in the section
243   RPCSEC_GSS_VERS_1, the RPC response will have a reply_stat of
244   MSG_DENIED, a rejection status of AUTH_ERROR, and an auth_stat of
245   AUTH_REJECTED_CRED.
246
2475.2.  Context Creation
248
249   Before RPC data is exchanged on a session using the RPCSEC_GSS
250   flavor, a context must be set up between the client and the server.
251   Context creation may involve zero or more RPC exchanges.  The number
252   of exchanges depends on the security mechanism.
253
2545.2.1.  Mechanism and QOP Selection
255
256   There is no facility in the RPCSEC_GSS protocol to negotiate GSS-API
257   mechanism identifiers or QOP values. At minimum, it is expected that
258   implementations of the RPCSEC_GSS protocol provide a means to:
259
260   *    specify mechanism identifiers, QOP values, and RPCSEC_GSS
261        service values on the client side, and to
262
263   *    enforce mechanism identifiers, QOP values, and RPCSEC_GSS
264        service values on a per-request basis on the server side.
265
266   It is necessary that above capabilities exist so that applications
267   have the means to conform the required set of required set of
268   <mechanism, QOP, service> tuples (See the section entitled Set of
269   GSS-API Mechanisms).  An application may negotiate <mechanism, QOP,
270   service> selection within its protocol or via an out of band
271   protocol. Hence it may be necessary for RPCSEC_GSS implementations to
272   provide programming interfaces for the specification and enforcement
273   of <mechanism, QOP, service>.
274
275   Additionally, implementations may depend on negotiation schemes
276   constructed as pseudo-mechanisms under the GSS-API.  Because such
277   schemes are below the GSS-API layer, the RPCSEC_GSS protocol, as
278   specified in this document, can make use of them.
279
280
281
282Eisler, et. al.             Standards Track                     [Page 5]
283
284RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
285
286
2875.2.2.  Context Creation Requests
288
289   The first RPC request from the client to the server initiates context
290   creation.  Within the RPC message protocol's call_body structure,
291   rpcvers is set to 2. prog and vers are always those for the service
292   being accessed.  The proc is always set to NULLPROC (zero).
293
294   Within the RPC message protocol's cred structure, flavor is set to
295   RPCSEC_GSS (6).  The opaque data of the cred structure (the body
296   field) constituting the credential encodes the rpc_gss_cred_t
297   structure defined previously.
298
299   The values of the fields contained in the rpc_gss_cred_t structure
300   are set as follows.  The version field is set to the version of the
301   RPCSEC_GSS protocol the client wants to use.  The remainder of this
302   memo documents version RPCSEC_GSS_VERS_1 of RPCSEC_GSS, and so the
303   version field would be set to RPCSEC_GSS_VERS_1.  The gss_proc field
304   must be set to RPCSEC_GSS_INIT for the first creation request.  In
305   subsequent creation requests, the gss_proc field must be set to
306   RPCSEC_GSS_CONTINUE_INIT.  In a creation request, the seq_num and
307   service fields are undefined and both must be ignored by the server.
308   In the first creation request, the handle field is NULL (opaque data
309   of zero length).  In subsequent creation requests, handle must be
310   equal to the value returned by the server.  The handle field serves
311   as the identifier for the context, and will not change for the
312   duration of the context, including responses to
313   RPCSEC_GSS_CONTINUE_INIT.
314
315   The verifier field in the RPC message header is also described by the
316   opaque_auth structure.  All creation requests have the NULL verifier
317   (AUTH_NONE flavor with zero length opaque data).
318
319   Following the verifier are the call data (procedure specific
320   parameters).  Note that the proc field of the call_body structure is
321   set to NULLPROC, and thus normally there would be zero octets
322   following the verifier.  However, since there is no RPC data exchange
323   during a context creation, it is safe to transfer information
324   following the verifier.  It is necessary to "overload" the call data
325   in this way, rather than pack the GSS-API token into the RPC header,
326   because RPC Version 2 restricts the amount of data that can be sent
327   in the header.  The opaque body of the credential and verifier fields
328   can be each at most 400 octets long, and GSS tokens can be longer
329   than 800 octets.
330
331
332
333
334
335
336
337
338Eisler, et. al.             Standards Track                     [Page 6]
339
340RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
341
342
343   The call data for a context creation request is described by the
344   following structure for all creation requests:
345
346      struct rpc_gss_init_arg {
347          opaque gss_token<>;
348      };
349
350   Here, gss_token is the token returned by the call to  GSS-API's
351   GSS_Init_sec_context() routine, opaquely encoded.  The value of this
352   field will likely be different in each creation request, if there is
353   more than one creation request.  If no token is returned by the call
354   to GSS_Init_sec_context(), the context must have been created
355   (assuming no errors), and there will not be any more creation
356   requests.
357
358   When GSS_Init_sec_context() is called, the parameters
359   replay_det_req_flag and sequence_req_flag must be turned off. The
360   reasons for this are:
361
362   *    ONC RPC can be used over unreliable transports and provides no
363        layer to reliably re-assemble messages. Thus it is possible for
364        gaps in message sequencing to occur, as well as out of order
365        messages.
366
367   *    RPC servers can be multi-threaded, and thus the order in which
368        GSS-API messages are signed or wrapped can be different from the
369        order in which the messages are verified or unwrapped, even if
370        the requests are sent on reliable transports.
371
372   *    To maximize convenience of implementation, the order in which an
373        ONC RPC entity will verify the header and verify/unwrap the body
374        of an RPC call or reply is left unspecified.
375
376   The RPCSEC_GSS protocol provides for protection from replay attack,
377   yet tolerates out-of-order delivery or processing of messages and
378   tolerates dropped requests.
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394Eisler, et. al.             Standards Track                     [Page 7]
395
396RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
397
398
3995.2.3.  Context Creation Responses
400
4015.2.3.1.  Context Creation Response - Successful Acceptance
402
403   The response to a successful creation request has an MSG_ACCEPTED
404   response with a status of SUCCESS.  The results field encodes a
405   response with the following structure:
406
407      struct rpc_gss_init_res {
408              opaque handle<>;
409              unsigned int gss_major;
410              unsigned int gss_minor;
411              unsigned int seq_window;
412              opaque gss_token<>;
413      };
414
415   Here, handle is non-NULL opaque data that serves as the context
416   identifier. The client must use this value in all subsequent requests
417   whether control messages or otherwise).  The gss_major and gss_minor
418   fields contain the results of the call to GSS_Accept_sec_context()
419   executed by the server.  The values for the gss_major field are
420   defined in Appendix A of this document.  The values for the gss_minor
421   field are GSS-API mechanism specific and are defined in the
422   mechanism's specification.  If gss_major is not one of GSS_S_COMPLETE
423   or GSS_S_CONTINUE_NEEDED, the context setup has failed; in this case
424   handle and gss_token must be set to NULL by the server.  The value of
425   gss_minor is dependent on the value of gss_major and the security
426   mechanism used.  The gss_token field contains any token returned by
427   the GSS_Accept_sec_context() call executed by the server.  A token
428   may be returned for both successful values of gss_major.  If the
429   value is GSS_S_COMPLETE, it indicates that the server is not
430   expecting any more tokens, and the RPC Data Exchange phase must begin
431   on the subsequent request from the client. If the value is
432   GSS_S_CONTINUE_NEEDED, the server is expecting another token.  Hence
433   the client must send at least one more creation request (with
434   gss_proc set to RPCSEC_GSS_CONTINUE_INIT in the request's credential)
435   carrying the required token.
436
437   In a successful response, the seq_window field is set to the sequence
438   window length supported by the server for this context.  This window
439   specifies the maximum number of client requests that may be
440   outstanding for this context. The server will accept "seq_window"
441   requests at a time, and these may be out of order.  The client may
442   use this number to determine the number of threads that can
443   simultaneously send requests on this context.
444
445
446
447
448
449
450Eisler, et. al.             Standards Track                     [Page 8]
451
452RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
453
454
455   If gss_major is GSS_S_COMPLETE, the verifier's (the verf element in
456   the response) flavor field is set to RPCSEC_GSS, and the body field
457   set to the checksum of the seq_window (in network order). The QOP
458   used for this checksum is 0 (zero), which is the default QOP.  For
459   all other values of gss_major, a NULL verifier (AUTH_NONE flavor with
460   zero-length opaque data) is used.
461
4625.2.3.1.1.  Client Processing of Successful Context Creation Responses
463
464   If the value of gss_major in the response is GSS_S_CONTINUE_NEEDED,
465   then the client, per the GSS-API specification, must invoke
466   GSS_Init_sec_context() using the token returned in gss_token in the
467   context creation response. The client must then generate a context
468   creation request, with gss_proc set to RPCSEC_GSS_CONTINUE_INIT.
469
470   If the value of gss_major in the response is GSS_S_COMPLETE, and if
471   the client's previous invocation of GSS_Init_sec_context() returned a
472   gss_major value of GSS_S_CONTINUE_NEEDED, then the client, per the
473   GSS-API specification, must invoke GSS_Init_sec_context() using the
474   token returned in gss_token in the context creation response. If
475   GSS_Init_sec_context() returns GSS_S_COMPLETE, the context is
476   successfully set up, and the RPC data exchange phase must begin on
477   the subsequent request from the client.
478
4795.2.3.2.  Context Creation Response - Unsuccessful Cases
480
481   An MSG_ACCEPTED reply (to a creation request) with an acceptance
482   status of other than SUCCESS has a NULL verifier (flavor set to
483   AUTH_NONE, and zero length opaque data in the body field), and is
484   formulated as usual for different status values.
485
486   An MSG_DENIED reply (to a creation request) is also formulated as
487   usual.  Note that MSG_DENIED could be returned because the server's
488   RPC implementation does not recognize the RPCSEC_GSS security flavor.
489   RFC 1831 does not specify the appropriate reply status in this
490   instance, but common implementation practice appears to be to return
491   a rejection status of AUTH_ERROR with an auth_stat of
492   AUTH_REJECTEDCRED. Even though two new values (RPCSEC_GSS_CREDPROBLEM
493   and RPCSEC_GSS_CTXPROBLEM) have been defined for the auth_stat type,
494   neither of these two can be returned in responses to context creation
495   requests.  The auth_stat new values can be used for responses to
496   normal (data) requests.  This is described later.
497
498   MSG_DENIED might also be returned if the RPCSEC_GSS version number in
499   the credential is not supported on the server. In that case, the
500   server returns a rejection status of AUTH_ERROR, with an auth_stat of
501
502   AUTH_REJECTED_CRED.
503
504
505
506Eisler, et. al.             Standards Track                     [Page 9]
507
508RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
509
510
5115.3.  RPC Data Exchange
512
513   The data exchange phase is entered after a context has been
514   successfully set up. The format of the data exchanged depends on the
515   security service used for the request.  Although clients can change
516   the security service and QOP used on a per-request basis, this may
517   not be acceptable to all RPC services; some RPC services may "lock"
518   the data exchange phase into using the QOP and service used on the
519   first data exchange message.  For all three modes of service (no data
520   integrity, data integrity, data privacy), the RPC request header has
521   the same format.
522
5235.3.1.  RPC Request Header
524
525   The credential has the opaque_auth structure described earlier.  The
526   flavor field is set to RPCSEC_GSS.  The credential body is created by
527   XDR encoding the rpc_gss_cred_t structure listed earlier into an
528   octet stream, and then opaquely encoding this octet stream as the
529   body field.
530
531   Values of the fields contained in the rpc_gss_cred_t structure are
532   set as follows.  The version field is set to same version value that
533   was used to create the context, which within the scope of this memo
534   will always be RPCSEC_GSS_VERS_1.  The gss_proc field is set to
535   RPCSEC_GSS_DATA.  The service field is set to indicate the desired
536   service (one of rpc_gss_svc_none, rpc_gss_svc_integrity, or
537   rpc_gss_svc_privacy).  The handle field is set to the context handle
538   value received from the RPC server during context creation.  The
539   seq_num field can start at any value below MAXSEQ, and must be
540   incremented (by one or more) for successive requests.  Use of
541   sequence numbers is described in detail when server processing of the
542   request is discussed.
543
544   The verifier has the opaque_auth structure described earlier.  The
545   flavor field is set to RPCSEC_GSS.  The body field is set as follows.
546   The checksum of the RPC header (up to and including the credential)
547   is computed using the GSS_GetMIC() call with the desired QOP.  This
548   returns the checksum as an opaque octet stream and its length.  This
549   is encoded into the body field.  Note that the QOP is not explicitly
550   specified anywhere in the request.  It is implicit in the checksum or
551   encrypted data.  The same QOP value as is used for the header
552   checksum must also be used for the data (for checksumming or
553   encrypting), unless the service used for the request is
554   rpc_gss_svc_none.
555
556
557
558
559
560
561
562Eisler, et. al.             Standards Track                    [Page 10]
563
564RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
565
566
5675.3.2.  RPC Request Data
568
5695.3.2.1.  RPC Request Data - No Data Integrity
570
571   If the service specified is rpc_gss_svc_none, the data (procedure
572   arguments) are not integrity or privacy protected.  They are sent in
573   exactly the same way as they would be if the AUTH_NONE flavor were
574   used (following the verifier).  Note, however, that since the RPC
575   header is integrity protected, the sender will still be authenticated
576   in this case.
577
5785.3.2.2.  RPC Request Data - With Data Integrity
579
580   When data integrity is used, the request data is represented as
581   follows:
582
583      struct rpc_gss_integ_data {
584          opaque databody_integ<>;
585          opaque checksum<>;
586      };
587
588   The databody_integ field is created as follows.  A structure
589   consisting of a sequence number followed by the procedure arguments
590   is constructed. This is shown below as the type rpc_gss_data_t:
591
592      struct rpc_gss_data_t {
593          unsigned int seq_num;
594          proc_req_arg_t arg;
595      };
596
597   Here, seq_num must have the same value as in the credential.  The
598   type proc_req_arg_t is the procedure specific XDR type describing the
599   procedure arguments (and so is not specified here).  The octet stream
600   corresponding to the XDR encoded rpc_gss_data_t structure and its
601   length are placed in the databody_integ field. Note that because the
602   XDR type of databody_integ is opaque, the XDR encoding of
603   databody_integ will include an initial four octet length field,
604   followed by the XDR encoded octet stream of rpc_gss_data_t.
605
606   The checksum field represents the checksum of the XDR encoded octet
607   stream corresponding to the XDR encoded rpc_gss_data_t structure
608   (note, this is not the checksum of the databody_integ field).  This
609   is obtained using the GSS_GetMIC() call, with the same QOP as was
610   used to compute the header checksum (in the verifier). The
611
612
613
614
615
616
617
618Eisler, et. al.             Standards Track                    [Page 11]
619
620RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
621
622
623   GSS_GetMIC() call returns the checksum as an opaque octet stream and
624   its length. The checksum field of struct rpc_gss_integ_data has an
625   XDR type of opaque. Thus the checksum length from GSS_GetMIC() is
626   encoded as a four octet  length field, followed by the checksum,
627   padded to a multiple of four octets.
628
6295.3.2.3.  RPC Request Data - With Data Privacy
630
631   When data privacy is used, the request data is represented as
632   follows:
633
634      struct rpc_gss_priv_data {
635          opaque databody_priv<>
636      };
637
638   The databody_priv field is created as follows.  The rpc_gss_data_t
639   structure described earlier is constructed again in the same way as
640   for the case of data integrity.  Next, the GSS_Wrap() call is invoked
641   to encrypt the octet stream corresponding to the rpc_gss_data_t
642   structure, using the same value for QOP (argument qop_req to
643   GSS_Wrap()) as was used for the header checksum (in the verifier) and
644   conf_req_flag (an argument to GSS_Wrap()) of TRUE.  The GSS_Wrap()
645   call returns an opaque octet stream (representing the encrypted
646   rpc_gss_data_t structure) and its length, and this is encoded as the
647   databody_priv field. Since databody_priv has an XDR type of opaque,
648   the length returned by GSS_Wrap() is encoded as the four octet
649   length, followed by the encrypted octet stream (padded to a multiple
650   of four octets).
651
6525.3.3.  Server Processing of RPC Data Requests
653
6545.3.3.1.  Context Management
655
656   When a request is received by the server, the following are verified
657   to be acceptable:
658
659   *    the version number in the credential
660
661   *    the service specified in the credential
662
663   *    the context handle specified in the credential
664
665   *    the header checksum in the verifier (via GSS_VerifyMIC())
666
667   *    the sequence number (seq_num) specified in the credential (more
668        on this follows)
669
670
671
672
673
674Eisler, et. al.             Standards Track                    [Page 12]
675
676RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
677
678
679   The gss_proc field in the credential must be set to RPCSEC_GSS_DATA
680   for data requests (otherwise, the message will be interpreted as a
681   control message).
682
683   The server maintains a window of "seq_window" sequence numbers,
684   starting with the last sequence number seen and extending backwards.
685   If a sequence number higher than the last number seen is received
686   (AND if GSS_VerifyMIC() on the header checksum from the verifier
687   returns GSS_S_COMPLETE), the window is moved forward to the new
688   sequence number.  If the last sequence number seen is N, the server
689   is prepared to receive requests with sequence numbers in the range N
690   through (N - seq_window + 1), both inclusive.  If the sequence number
691   received falls below this range, it is silently discarded.  If the
692   sequence number is within this range, and the server has not seen it,
693   the request is accepted, and the server turns on a bit to "remember"
694   that this sequence number has been seen.  If the server determines
695   that it has already seen a sequence number within the window, the
696   request is silently discarded. The server should select a seq_window
697   value based on the number requests it expects to process
698   simultaneously. For example, in a threaded implementation seq_window
699   might be equal to the number of server threads. There are no known
700   security issues with selecting a large window. The primary issue is
701   how much space the server is willing to allocate to keep track of
702   requests received within the window.
703
704   The reason for discarding requests silently is that the server is
705   unable to determine if the duplicate or out of range request was due
706   to a sequencing problem in the client, network, or the operating
707   system, or due to some quirk in routing, or a replay attack by an
708   intruder.  Discarding the request allows the client to recover after
709   timing out, if indeed the duplication was unintentional or well
710   intended.  Note that a consequence of the silent discard is that
711   clients may increment the seq_num by more than one. The effect of
712   this is that the window will move forward more quickly. It is not
713   believed that there is any benefit to doing this.
714
715   Note that the sequence number algorithm requires that the client
716   increment the sequence number even if it is retrying a request with
717   the same RPC transaction identifier.  It is not infrequent for
718   clients to get into a situation where they send two or more attempts
719   and a slow server sends the reply for the first attempt. With
720   RPCSEC_GSS, each request and reply will have a unique sequence
721   number. If the client wishes to improve turn around time on the RPC
722   call, it can cache the RPCSEC_GSS sequence number of each request it
723   sends. Then when it receives a response with a matching RPC
724   transaction identifier, it can compute the checksum of each sequence
725   number in the cache to try to match the checksum in the reply's
726   verifier.
727
728
729
730Eisler, et. al.             Standards Track                    [Page 13]
731
732RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
733
734
735   The data is decoded according to the service specified in the
736   credential.  In the case of integrity or privacy, the server ensures
737   that the QOP value is acceptable, and that it is the same as that
738   used for the header checksum in the verifier.  Also, in the case of
739   integrity or privacy, the server will reject the message (with a
740   reply status of MSG_ACCEPTED, and an acceptance status of
741   GARBAGE_ARGS) if the sequence number embedded in the request body is
742   different from the sequence number in the credential.
743
7445.3.3.2.  Server Reply - Request Accepted
745
746   An MSG_ACCEPTED reply to a request in the data exchange phase will
747   have the verifier's (the verf element in the response) flavor field
748   set to RPCSEC_GSS, and the body field set to the checksum (the output
749   of GSS_GetMIC()) of the sequence number (in network order) of the
750   corresponding request.  The QOP used is the same as the QOP used for
751   the corresponding request.
752
753   If the status of the reply is not SUCCESS, the rest of the message is
754   formatted as usual.
755
756   If the status of the message is SUCCESS, the format of the rest of
757   the message depends on the service specified in the corresponding
758   request message. Basically, what follows the verifier in this case
759   are the procedure results, formatted in different ways depending on
760   the requested service.
761
762   If no data integrity was requested, the procedure results are
763   formatted as for the AUTH_NONE security flavor.
764
765   If data integrity was requested, the results are encoded in exactly
766   the same way as the procedure arguments were in the corresponding
767   request.  See the section 'RPC Request Data - With Data Integrity.'
768   The only difference is that the structure representing the
769   procedure's result - proc_res_arg_t - must be substituted in place of
770   the request argument structure proc_req_arg_t.  The QOP used for the
771   checksum must be the same as that used for constructing the reply
772   verifier.
773
774   If data privacy was requested, the results are encoded in exactly the
775   same way as the procedure arguments were in the corresponding
776   request.  See the section 'RPC Request Data - With Data Privacy.' The
777   QOP used for  encryption must be the same as that used for
778   constructing the reply verifier.
779
780
781
782
783
784
785
786Eisler, et. al.             Standards Track                    [Page 14]
787
788RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
789
790
7915.3.3.3.  Server Reply - Request Denied
792
793   An MSG_DENIED reply (to a data request) is formulated as usual.  Two
794   new values (RPCSEC_GSS_CREDPROBLEM and RPCSEC_GSS_CTXPROBLEM) have
795   been defined for the auth_stat type.  When the reason for denial of
796   the request is a reject_stat of AUTH_ERROR, one of the two new
797   auth_stat values could be returned in addition to the existing
798   values.  These two new values have special significance from the
799   existing reasons for denial of a request.
800
801   The server maintains a list of contexts for the clients that are
802   currently in session with it.  Normally, a context is destroyed when
803   the client ends the session corresponding to it.  However, due to
804   resource constraints, the server may destroy a context prematurely
805   (on an LRU basis, or if the server machine is rebooted, for example).
806   In this case, when a client request comes in, there may not be a
807   context corresponding to its handle. The server rejects the request,
808   with the reason RPCSEC_GSS_CREDPROBLEM in this case.  Upon receiving
809   this error, the client must refresh the context - that is,
810   reestablish it after destroying the old one - and try the request
811   again.  This error is also returned if the context handle matches
812   that of a different context that was allocated after the client's
813   context was destroyed (this will be detected by a failure in
814   verifying the header checksum).
815
816   If the GSS_VerifyMIC() call on the header checksum (contained in the
817   verifier) fails to return GSS_S_COMPLETE, the server rejects the
818   request and returns an auth_stat of RPCSEC_GSS_CREDPROBLEM.
819
820   When the client's sequence number exceeds the maximum the server will
821   allow, the server will reject the request with the reason
822   RPCSEC_GSS_CTXPROBLEM.  Also, if security credentials become stale
823   while in use (due to ticket expiry in the case of the Kerberos V5
824   mechanism, for example), the failures which result cause the
825   RPCSEC_GSS_CTXPROBLEM reason to be returned.  In these cases also,
826   the client must refresh the context, and retry the request.
827
828   For other errors, retrying will not rectify the problem and the
829   client must not refresh the context until the problem causing the
830   client request to be denied is rectified.
831
832   If the version field in the credential does not match the version of
833   RPCSEC_GSS that was used when the context was created, the
834   AUTH_BADCRED value is returned.
835
836   If there is a problem with the credential, such a bad length, illegal
837   control procedure, or an illegal service, the appropriate auth_stat
838   status is AUTH_BADCRED.
839
840
841
842Eisler, et. al.             Standards Track                    [Page 15]
843
844RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
845
846
847   Other errors can be returned as appropriate.
848
8495.3.3.4.  Mapping of GSS-API Errors to Server Responses
850
851   During the data exchange phase, the server may invoke GSS_GetMIC(),
852   GSS_VerifyMIC(), GSS_Unwrap(), and GSS_Wrap(). If any of these
853   routines fail to return GSS_S_COMPLETE, then various unsuccessful
854   responses can be returned. The are described as follows for each of
855   the aforementioned four interfaces.
856
8575.3.3.4.1.  GSS_GetMIC() Failure
858
859   When GSS_GetMIC() is called to generate the verifier in the response,
860   a failure results in an RPC response with a reply status of
861   MSG_DENIED, reject status of AUTH_ERROR and an auth status of
862   RPCSEC_GSS_CTXPROBLEM.
863
864   When GSS_GetMIC() is called to sign the call results (service is
865   rpc_gss_svc_integrity), a failure results in no RPC response being
866   sent. Since ONC RPC server applications will typically control when a
867   response is sent, the failure indication will be returned to the
868   server application and it can take appropriate action (such as
869   logging the error).
870
8715.3.3.4.2.  GSS_VerifyMIC() Failure
872
873   When GSS_VerifyMIC() is called to verify the verifier in request, a
874   failure results in an RPC response with a reply status of MSG_DENIED,
875   reject status of AUTH_ERROR and an auth status of
876   RPCSEC_GSS_CREDPROBLEM.
877
878   When GSS_VerifyMIC() is called to verify the call arguments (service
879   is rpc_gss_svc_integrity), a failure results in an RPC response with
880   a reply status of MSG_ACCEPTED, and an acceptance status of
881   GARBAGE_ARGS.
882
8835.3.3.4.3.  GSS_Unwrap() Failure
884
885   When GSS_Unwrap() is called to decrypt the call arguments (service is
886   rpc_gss_svc_privacy), a failure results in an RPC response with a
887   reply status of MSG_ACCEPTED, and an acceptance status of
888   GARBAGE_ARGS.
889
8905.3.3.4.4.  GSS_Wrap() Failure
891
892   When GSS_Wrap() is called to encrypt the call results (service is
893   rpc_gss_svc_privacy), a failure results in no RPC response being
894   sent. Since ONC RPC server applications will typically control when a
895
896
897
898Eisler, et. al.             Standards Track                    [Page 16]
899
900RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
901
902
903   response is sent, the failure indication will be returned to the
904   application and it can take appropriate action (such as logging the
905   error).
906
9075.4.  Context Destruction
908
909   When the client is done using the session, it must send a control
910   message informing the server that it no longer requires the context.
911   This message is formulated just like a data request packet, with the
912   following differences:  the credential has gss_proc set to
913   RPCSEC_GSS_DESTROY, the procedure specified in the header is
914   NULLPROC, and there are no procedure arguments.  The sequence number
915   in the request must be valid, and the header checksum in the verifier
916   must be valid, for the server to accept the message.  The server
917   sends a response as it would to a data request.  The client and
918   server must then destroy the context for the session.
919
920   If the request to destroy the context fails for some reason, the
921   client need not take any special action.  The server must be prepared
922   to deal with situations where clients never inform the server that
923   they no longer are in session and so don't need the server to
924   maintain a context.  An LRU mechanism or an aging mechanism should be
925   employed by the server to clean up in such cases.
926
9276.  Set of GSS-API Mechanisms
928
929   RPCSEC_GSS is effectively a "pass-through" to the GSS-API layer, and
930   as such it is inappropriate for the RPCSEC_GSS specification to
931   enumerate a minimum set of required security mechanisms and/or
932   quality of protections.
933
934   If an application protocol specification references RPCSEC_GSS, the
935   protocol specification must list a mandatory set of { mechanism, QOP,
936   service } triples, such that an implementation cannot claim
937   conformance to the protocol specification unless it implements the
938   set of triples. Within each triple, mechanism is a GSS-API security
939   mechanism, QOP is a valid quality-of-protection within the mechanism,
940   and service is either rpc_gss_svc_integrity or rpc_gss_svc_privacy.
941
942   For example, a network filing protocol built on RPC that depends on
943   RPCSEC_GSS for security, might require that Kerberos V5 with the
944   default QOP using the rpc_gss_svc_integrity service be supported by
945   implementations conforming to the network filing protocol
946   specification.
947
948
949
950
951
952
953
954Eisler, et. al.             Standards Track                    [Page 17]
955
956RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
957
958
9597.  Security Considerations
960
9617.1.  Privacy of Call Header
962
963   The reader will note that for the privacy option, only the call
964   arguments and results are encrypted. Information about the
965   application in the form of RPC program number, program version
966   number, and program procedure number is transmitted in the clear.
967   Encrypting these fields in the RPC call header would have changed the
968   size and format of the call header. This would have required revising
969   the RPC protocol which was beyond the scope of this proposal. Storing
970   the encrypted numbers in the credential would have obviated a
971   protocol change, but would have introduced more overloading of fields
972   and would have made implementations of RPC more complex. Even if the
973   fields were encrypted somehow, in most cases an attacker can
974   determine the program number and version number by examining the
975   destination address of the request and querying the rpcbind service
976   on the destination host [Srinivasan-bind].  In any case, even by not
977   encrypting the three numbers, RPCSEC_GSS still improves the state of
978   security over what existing RPC services have had available
979   previously. Implementors of new RPC services that are concerned about
980   this risk may opt to design in a "sub-procedure" field that is
981   included in the service specific call arguments.
982
9837.2.  Sequence Number Attacks
984
9857.2.1.  Sequence Numbers Above the Window
986
987   An attacker cannot coax the server into raising the sequence number
988   beyond the range the legitimate client is aware of (and thus engineer
989   a denial of server attack) without constructing an RPC request that
990   will pass the header checksum. If the cost of verifying the header
991   checksum is sufficiently large (depending on the speed of the
992   processor doing the checksum and the cost of checksum algorithm), it
993   is possible to envision a denial of service attack (vandalism, in the
994   form of wasting processing resources) whereby the attacker sends
995   requests that are above the window. The simplest method might be for
996   the attacker to monitor the network traffic and then choose a
997   sequence number that is far above the current sequence number. Then
998   the attacker can send bogus requests using the above window sequence
999   number.
1000
10017.2.2.  Sequence Numbers Within or Below the Window
1002
1003   If the attacker sends requests that are within or below the window,
1004   then even if the header checksum is successfully verified, the server
1005   will silently discard the requests because the server assumes it has
1006   already processed the request. In this case, a server can optimize by
1007
1008
1009
1010Eisler, et. al.             Standards Track                    [Page 18]
1011
1012RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
1013
1014
1015   skipping the header checksum verification if the sequence number is
1016   below the window, or if it is within the window, not attempt the
1017   checksum verification if the sequence number has already been seen.
1018
10197.3.  Message Stealing Attacks
1020
1021   This proposal does not address attacks where an attacker can block or
1022   steal messages without being detected by the server. To implement
1023   such protection would be tantamount to assuming a state in the RPC
1024   service. RPCSEC_GSS does not worsen this situation.
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066Eisler, et. al.             Standards Track                    [Page 19]
1067
1068RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
1069
1070
1071Appendix A. GSS-API Major Status Codes
1072
1073   The GSS-API definition [Linn] does not include numerical values for
1074   the various GSS-API major status codes. It is expected that this will
1075   be addressed in future RFC. Until then, this appendix defines the
1076   values for each GSS-API major status code listed in the GSS-API
1077   definition.  If in the future, the GSS-API definition defines values
1078   for the codes that are different than what follows, then implementors
1079   of RPCSEC_GSS will be obliged to map them into the values defined
1080   below. If in the future, the GSS-API definition defines additional
1081   status codes not defined below, then the RPCSEC_GSS definition will
1082   subsume those additional values.
1083
1084   Here are the definitions of each GSS_S_* major status that the
1085   implementor of RPCSEC_GSS can expect in the gss_major major field of
1086   rpc_gss_init_res.  These definitions are not in RPC description
1087   language form.  The numbers are in base 16 (hexadecimal):
1088
1089      GSS_S_COMPLETE                  0x00000000
1090      GSS_S_CONTINUE_NEEDED           0x00000001
1091      GSS_S_DUPLICATE_TOKEN           0x00000002
1092      GSS_S_OLD_TOKEN                 0x00000004
1093      GSS_S_UNSEQ_TOKEN               0x00000008
1094      GSS_S_GAP_TOKEN                 0x00000010
1095      GSS_S_BAD_MECH                  0x00010000
1096      GSS_S_BAD_NAME                  0x00020000
1097      GSS_S_BAD_NAMETYPE              0x00030000
1098      GSS_S_BAD_BINDINGS              0x00040000
1099      GSS_S_BAD_STATUS                0x00050000
1100      GSS_S_BAD_MIC                   0x00060000
1101      GSS_S_BAD_SIG                   0x00060000
1102      GSS_S_NO_CRED                   0x00070000
1103      GSS_S_NO_CONTEXT                0x00080000
1104      GSS_S_DEFECTIVE_TOKEN           0x00090000
1105      GSS_S_DEFECTIVE_CREDENTIAL      0x000a0000
1106      GSS_S_CREDENTIALS_EXPIRED       0x000b0000
1107      GSS_S_CONTEXT_EXPIRED           0x000c0000
1108      GSS_S_FAILURE                   0x000d0000
1109      GSS_S_BAD_QOP                   0x000e0000
1110      GSS_S_UNAUTHORIZED              0x000f0000
1111      GSS_S_UNAVAILABLE               0x00100000
1112      GSS_S_DUPLICATE_ELEMENT         0x00110000
1113      GSS_S_NAME_NOT_MN               0x00120000
1114      GSS_S_CALL_INACCESSIBLE_READ    0x01000000
1115      GSS_S_CALL_INACCESSIBLE_WRITE   0x02000000
1116      GSS_S_CALL_BAD_STRUCTURE        0x03000000
1117
1118
1119
1120
1121
1122Eisler, et. al.             Standards Track                    [Page 20]
1123
1124RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
1125
1126
1127   Note that the GSS-API major status is split into three fields as
1128   follows:
1129
1130        Most Significant Bit                     Least Significant Bit
1131        |------------------------------------------------------------|
1132        | Calling Error | Routine Error  |    Supplementary Info     |
1133        |------------------------------------------------------------|
1134      Bit 31           24 23            16 15                        0
1135
1136   Up to one status in the Calling Error field can be logically ORed
1137   with up to one status in the Routine Error field which in turn can be
1138   logically ORed with zero or more statuses in the Supplementary Info
1139   field. If the resulting major status has a non-zero Calling Error
1140   and/or a non-zero Routine Error, then the applicable GSS-API
1141   operation has failed.  For purposes of RPCSEC_GSS, this means that
1142   the GSS_Accept_sec_context() call executed by the server has failed.
1143
1144   If the major status is equal GSS_S_COMPLETE, then this indicates the
1145   absence of any Errors or Supplementary Info.
1146
1147   The meanings of most of the GSS_S_* status are defined in the GSS-API
1148   definition, which the exceptions of:
1149
1150   GSS_S_BAD_MIC       This code has the same meaning as GSS_S_BAD_SIG.
1151
1152   GSS_S_CALL_INACCESSIBLE_READ
1153                        A required input parameter could not be read.
1154
1155   GSS_S_CALL_INACCESSIBLE_WRITE
1156                        A required input parameter could not be written.
1157
1158   GSS_S_CALL_BAD_STRUCTURE
1159                       A parameter was malformed.
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178Eisler, et. al.             Standards Track                    [Page 21]
1179
1180RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
1181
1182
1183Acknowledgements
1184
1185   Much of the protocol was based on the AUTH_GSSAPI security flavor
1186   developed by Open Vision Technologies [Jaspan].  In particular, we
1187   acknowledge Barry Jaspan, Marc Horowitz, John Linn, and Ellen
1188   McDermott.
1189
1190   Raj Srinivasan designed RPCSEC_GSS [Eisler] with input from Mike
1191   Eisler.  Raj, Roland Schemers, Lin Ling, and Alex Chiu contributed to
1192   Sun Microsystems' implementation of RPCSEC_GSS.
1193
1194   Brent Callaghan, Marc Horowitz, Barry Jaspan, John Linn, Hilarie
1195   Orman, Martin Rex, Ted Ts'o, and John Wroclawski analyzed the
1196   specification and gave valuable feedback.
1197
1198   Steve Nahm and Kathy Slattery reviewed various drafts of this
1199   specification.
1200
1201   Much of content of Appendix A was excerpted from John Wray's Work in
1202   Progress on GSS-API Version 2 C-bindings.
1203
1204References
1205
1206   [Eisler]            Eisler, M., Schemers, R., and Srinivasan, R.
1207                       (1996).  "Security Mechanism Independence in ONC
1208                       RPC," Proceedings of the Sixth Annual USENIX
1209                       Security Symposium, pp. 51-65.
1210
1211   [Jaspan]            Jaspan, B. (1995). "GSS-API Security for ONC
1212                       RPC," `95 Proceedings of The Internet Society
1213                       Symposium on Network and Distributed System
1214                       Security, pp. 144- 151.
1215
1216   [Linn]              Linn, J., "Generic Security Service Application
1217                       Program Interface, Version 2", RFC 2078, January
1218                       1997.
1219
1220   [Srinivasan-bind]   Srinivasan, R., "Binding Protocols for
1221                       ONC RPC Version 2", RFC 1833, August 1995.
1222
1223   [Srinivasan-rpc]    Srinivasan, R., "RPC: Remote Procedure Call
1224                       Protocol Specification Version 2", RFC 1831,
1225                       August 1995.
1226
1227   [Srinivasan-xdr]    Srinivasan, R., "XDR: External Data
1228                       Representation Standard", RFC 1832, August 1995.
1229
1230
1231
1232
1233
1234Eisler, et. al.             Standards Track                    [Page 22]
1235
1236RFC 2203           RPCSEC_GSS Protocol Specification      September 1997
1237
1238
1239Authors' Addresses
1240
1241   Michael Eisler
1242   Sun Microsystems, Inc.
1243   M/S UCOS03
1244   2550 Garcia Avenue
1245   Mountain View, CA 94043
1246
1247   Phone: +1 (719) 599-9026
1248   EMail: mre@eng.sun.com
1249
1250
1251   Alex Chiu
1252   Sun Microsystems, Inc.
1253   M/S UMPK17-203
1254   2550 Garcia Avenue
1255   Mountain View, CA 94043
1256
1257   Phone: +1 (415) 786-6465
1258   EMail: hacker@eng.sun.com
1259
1260
1261   Lin Ling
1262   Sun Microsystems, Inc.
1263   M/S UMPK17-201
1264   2550 Garcia Avenue
1265   Mountain View, CA 94043
1266
1267   Phone: +1 (415) 786-5084
1268   EMail: lling@eng.sun.com
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290Eisler, et. al.             Standards Track                    [Page 23]
1291
1292