GSS and IDUP
Graham Bland <gbland@zergo.com> Wed, 14 January 1998 14:12 UTC
From: Graham Bland <gbland@zergo.com>
Date: Wed, 14 Jan 1998 14:12:58 +0000
To: cat-ietf@mit.edu
Subject: GSS and IDUP
X-Mime-Autoconverted: from quoted-printable to 8bit by pad-thai.cam.ov.com id JAA09985
X-Mime-Autoconverted: from 8bit to quoted-printable by pad-thai.cam.ov.com id JAB09987
X-Message-ID:
Message-ID: <20140418005448.2560.59729.ARCHIVE@ietfa.amsl.com>
Firstly apology on two counts. The timing of these comments is poor following last call, however at that time I had no comments. Secondly the length, this is a collection of comments and issues rather than sending each as a seperate email I have collated them together. The background from most of these has come from looking at an environment which will support both GSS and GSS-IDUP. All are based on the latest documents. IDUP_Get_token_details ------------------------------------ When Data encapsulation has been requested the application must pass sufficient data from the start of the P_IDU to include the token to the call. The application has no way of determining how much data this is. A return code of IDUP_S_MORE_PIDU_NEEDED should be allowed to enable the application to pass more data to the call. The other option would be to require a minimum data size of for example 4kb or the entire token to be passed. This would constrain the mechanism implementors to include all the required data within the first 4kb of a token. The call returns the idu_size, however where data encapsulation and multiple buffers are used a mechanism cannot determine this from the start of the P_IDU as the mechanism does not know the IDU length until the IDU has been fully processed (see later comment on IDU Length on multi buffer calls) as indicated by the end protect call by which time the token at the start of the P_IDU has already been emitted and cannot be changed. Suggested behaviour here would be to return UNKNOWN as the idu_size with a status of GSS_S_COMPLETE for encapsulated data. IDUP Multibuffer processing -------------------------------- While examining some of the SE Start/Process/End sequences of calls We have noted the following; A mechanism (directly or indirectly via the environment) will need to preserve state information from one call to the next in a sequence of (SE/EV/GP) Start/Process/End calls. This state information will almost certainly involve dynamic memory allocation. If for some reason (e.g. an I/O error or user abort) an application calls a Start followed by zero or more Process calls but fails to call End, that memory will not be released in the normal way (i.e. on the End call). Currently we have assumed, that, for a single instance of an environment, it is only valid to be performing a single multi-step operation at one time (e.g. a sequence such as SEStart, EVStart, SEProcess, EVProcess, SEEnd, EVEnd is not allowed). We have further specified that an environment should only be used in the thread that created it. As a mechanism implementation detail, under the current scheme, it should be noted that if a mechanism receives a request to start any operation while a previous operation is still in progress, it should cancel the previous operation, releasing its state storage. It should also release state storage when the environment is abolished. Note however that this may mean that the state information may remain for some significant time after an operation fails or is cancelled at the application level. At a specification level, it may be appropriate to suggest a 'cancel' function for each of the multi-step operations (for example IDUP_SE_MultiBuffer_Cancel), which would allow the application to indicate to IDUP that it was unable to make the additional Process calls due to some application level difficulty. A further point is the possibility of including an 'operation' handle within the multi-step calls (i.e. an handle that is returned from the Start operation and must be passed to each subsequent matching process/end or cancel call). This would allow state information to be associated with a series of calls and not bound to the environment. This would remove the sequence and thread restrictions above. At the moment any multi-thread/fibre application will have to establish an environment for each operation it will perform (and this may be expensive). An alternative would be to provide a 'duplicate environment' function which should be able to avoid some aspects of environment establishment (e.g. certificate validation) and thus be less expensive that establishing a new environment. On a side note, I dislike this start/process/end method of performing an operation over a large data source. The application developer has to include complex loops of calls, IDUP and the mechanism have to preserve state across calls, including the fact the buffer may terminate in the middle of some atomic unit of data at the token level (e.g. in the middle of an integer or OID) making restarting complex. A far better solution would be to allow language specific bindings (where supported) to pass 'get more data' and 'put more data' functions (or abstract base class) into the API, then at any point that the mechanism required more data, it simply calls back to retrieve that data. This method also reduces the number of times data is copied from one buffer to another, as, for example, these functions could just be file system i/o functions where the data resides on disk. The start/process/end method was used extensively under Windows 3.1, as to prevent the system freezing during a lengthy operation the application had to invoke the message pump frequently. The call-back method still allows this, but may require more stack space. IDUP_ev_singlebuffer_verify ------------------------------------------ The idu_buffer is described in the API spec as an input and an output, in the C bindings this is implemented as two parameters one input buffer and one output buffer. Both however have the same name of idu_buffer. I suggest renaming these to external_idu_buffer for the input buffer and encapsulated_idu_buffer for the output. IDUP_establish_env ------------------------------ The ret_services parameter is defined as a gss_OID_set, I believe this should be a gss_OID_set * to be consistent with the rest of the IDUP and GSS calls. While it is technically possible to pass the OID set by value (since it is a pointer) and for IDUP to add elements to a previously allocated set (via the application calling gss_create_empty_oid_set), everywhere else the allocation of the empty OID set is the responsibility of GSS/IDUP and it returns this by double pointer. Status Codes -------------------- The GSS C-Bindings introduced two new status codes, defining error status codes up to 18 (GSS_NAME_NOT_MN), however the May 97 IDUP C-Bindings starts the IDUP extended error status codes from 17 (IDUP_S_BAD_TARG_INFO). Thus error codes 17 and 18 are defined in both GSS and IDUP as different status returns. I propose as change to IDUP C-bindings whereby the IDUP return codes start at 255 and work down to avoid conflicts with GSS Credential Usage Type ----------------------------------- GSS C-Bindings Defines credential usage as an INT. Latest IDUP draft defines it as a BIT-STRING. The spec states "The calls given in Section 2.1 of GSS-API (including all associated parameters) are unchanged, although the interpretation of the cred_usage parameter in the GSS_API calls for IDUP purposes is as follows. ..." However the determination of the usage of the credential (i.e. for GSS usage - context establishment, or for IDUP usage - environment establishment) does not occur until later - possibly after credential elements have been instantiated. While it is possible to overload the use of the parameter, it would ease matters if the parameter was defined as a bit string in both cases. For example GSS_C_INITIATE 1 GSS_C_ACCEPT 2 IDUP_C_ENCRYPT_ONLY 8 IDUP_C_DECRYPT_ONLY 16 IDUP_C_SIGN_ONLY 32 IDUP_C_VERIFY_ONLY 64 GSS_C_BOTH (GSS_C_INITIATE | GSS_C_ACCEPT) IDUP_C_NO_RESTRICTION (IDUP_C_ENCRYPT_ONLY | IDUP_C_DECRYPT_ONLY | IDP_C_SIGN_ONLY | IDUP_C_VERIFY_ONLY) it is unclear as to what is intended in an environment with a mechanism which implements both GSS and IDUP. This is proposed as a change to both IDUP and GSS C-bindings. Parameter Types -------------------------- A number of GSS and GSS/IDUP structures define ordinality or size, below is a table summarising them. Struct field type ===== ==== ==== gss_buffer_t length size_t gss_OID length OM_uint32 gss_OID_set count size_t IDUP_Target_Info bad_count int IDUP_Services_To_Perform no_of_services OM_uint32 IDUP_Services_To_Receive no_of_services OM_uint32 IDUP_Service_Descriptor_Set count int IDUP_Mechanism_Descriptor_Set count int idup_name_set count int As you can see, they lack consistency. Over time it appears that the GSS C-Bindings have shifted from int to size_t for some items (e.g. gss_OID_set.count) - in particular the IDUP C-Bindings still refer to the old 'int' usage for GSS. For consistency both IDUP should adopt size_t for count fields and OM_uint32 for length fields. Case usage ------------------ The GSS C bindings specifies function calls and structure members as lower case names, for consistency the IDUP C bindings should follow suit. Idup_name_set ----------------------- idup_name_set is defined as: typedef struct idup_name_set_desc_struct { int count ; gss_name_t elements ; } idup_name_set_desc, *idup_name_set; Where gss_name_t is an implementation defined type. This definition does not work for all definitions of gss_name_t. In particular it will not work for any which are either not pointer types or where the sizeof() operator does not evaluate to a constant. For binary compatibility only, GSS imposes the restriction that it should be a pointer type (Section B.4) and discourages, but does not preclude the use of void*. For source compatibility, GSS does not impose any restriction on the implementation of gss_name_t. With a rather simplistic view of the implementation of gss_name_t (e.g. precluding opaque types, non-pointers, void *, derived classes and extensible structures), the above would work. However I don't believe that this restriction is intentional, nor acceptable. In our case gss_name_t is defined as a pointer to an opaque type and thus you cannot apply the sizeof() operator to it. In particular, expressions such as elements[1] cannot correctly be evaluated since the sizeof(elements[0]) would depend on the actual implementation the type. Additionally we cannot expose the implementation as it is C++ specific and would not compile in C. We have thus re-defined idup_name_set as; typedef struct idup_name_set_desc_struct { int count ; gss_name_t* elements ; } idup_name_set_desc, *idup_name_set; This should not have a significant impact on source level compatibility, since most of the manipulation of name sets is via API functions (idup_add_name_set_member etc.). Another choice would be to implement gss_name_t as a double pointer, but this would impose an, otherwise unnecessary, overhead in development, execution, and maintenance. idup_acquire_cred_with_auth ------------------------------------------- We have defined idup_acquire_cred_with_auth as follows; OM_uint32 GSS_ENTRY idup_acquire_cred_with_auth( gss_name_t desired_name, gss_buffer_t authenticator, OM_uint32 time_req, gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, OM_uint32* minor_status, gss_cred_id_t* output_cred_handle, gss_OID_set* actual_mechs, OM_uint32* time_rec) ; This differs from the last C-Bindings where cred_usage is defined as gss_buffer_t and actual_mechs is defined as gss_OID_set. It makes no sense whatsoever for cred_usage to be a gss_buffer_t, since functions like inquire_cred return gss_cred_usage_t. I can only assume that this is some oddity from the fact that the parameter definition was noted as changing from INT to BITSTRING in the language independent API - however we have assumed that the intention here is to re-use the INT with bitmasks. Actual_mechs is another place where there appears to be a wrong (or at least inconsistent) level of pointer. Appendix IDUP-GSS-API example --------------------------------------------------- Would it not make sense to include the GSS header file rather than replicate all the information. Error codes - IDUP_C_ROUTINE_ERROR_OFFSET is not defined, how does this differ from GSS_C_ROUTINE_ERROR_OFFSET or is it the same. The struct definition for IDUP_Prot_Service_desc, last parameter is missing a space between int and service_verification_info_id IDU Length on multi buffer calls --------------------------------------------- The IDUP calls IDUP_SE_MultiBuffer_StartProtect, IDUP_EV_MultiBuffer_Generate (with include_data_in_token TRUE) and IDUP_Protect all create a PIDU which contains an encapsulated IDU. The total length of the IDU is not available at any point prior to the matching IDUP_xxxEndxxx call. Thus the beginning of the PIDU cannot contain the length of the IDU (or related length) without the mechanism buffering the entire IDU. This may be impractical due to the potential size of the IDU. IDUP mechanisms are therefore constrained to use either - chaining (where the data is broken into blocks and the length of each block prefixes the block and the last block is marked - this requires buffering up to one block length or more at the receiver), or, - an 'end of data' marker (this marker must be guarantee never to occur in either the IDU or encrypted IDU - this requires buffering up to the length of the EOD marker at the receiver). To resolve this issue, and allow mechanisms to store the size of the IDU at the start of the PIDU, the three calls listed above should have an additional parameter 'idu_size' which is required when encapsulation is required. The idu_size should have a value 'UNKNOWN' (for example where encapsulating data from a pipe, or compressing on the fly) - some mechanisms may not support encapsulation if this value is UNKNOWN. Is it possible or desirable for mechanisms to implement a restriction whereby encapsulation is not provided on the multi-buffer calls unless they naturally use one of the above solutions (chaining or EOD). Return Codes -------------------- I suggest that an additional return code be added both to GSS and IDUP specifications to cover a case of inconsistent parameters, for example in idup_start_unprotect where only one of single_idu_buffer and final_pidu_buffer may have a zero length and the caller has passed both. Currently GSS_S_FAILURE must be returned which is not particularly informative to the application developer. Idup_establish_env ----------------------------- Passing GSS_C_NO_OID_SET as the req_services parameter to idup_establish_env should be defined as requesting the full set of available services for that mechanism. There is no point in establishing an environment with no services (hence GSS_C_NO_OID_SET is not really a valid input parameter), and given that the services are mechanism specific and may grow over time, there is no way for an application to discover which services are available without pre-knowledge (OK - how it then uses these services is another matter...). It also simplifies the application developers job as they do not have to create an OID set to start with. Credentials and Usage ---------------------------------- 1. The GSS C Bindings define 'cred_usage' as input only for both gss_acquire_cred and gss_add_cred. It does not comment on what should happen if only a subset of the usage is available (e.g, if BOTH is requested and only INITIATE is available, should that generate a GSS_C_NO_CRED?). 2. The language API Specification (rfc2078bis-01) state that for gss_acquire_cred, that it should fail if the requested usage is not available, but gss_add_cred has an additional output parameter (with the same name as an input parameter) which suggests that add cred should return the set of usages available and succeed if any requested usage was available. I say 'suggests' since the interpretation depends entirely on which 'cred_usage' the paragraph is referring to (i.e. the input or output). The reason that I question this is that in the case of gss_acquire_cred, this would mean that the application programmer would basically have to acquire separate credentials for each operation type, since they could not be guaranteed that any combination would succeed (without making installation specific assumptions) and they would thus have to perform an exhaustive call search to find the best available. Note that this is compounded by IDUPs 4 additional 'cred_usage' values. For the above reason I believe that we should take the approach used by GSS everywhere else - i.e. request a set of features, but the onus is on application programmer to ensure that a sufficient subset was provided. Thus, both acquire_cred and add_cred should have 'actual_cred_usage' output parameters. The latter is a change to the c-bindings only, bringing it in line with the GSS spec, the former deviates from both. However without some sort of resolution in this area, any application that wishes use GSS and IDUP would have to maintain separate credentials for each, negating much of the value of a core set of credential management functions. Note that I am currently making the assumption that in a multi-mechanism environment, credential acquisition succeeds if any combination of mechanisms satisfies the cred_usage. 3. For credential acquisition within IDUP, you are allowed to define a restricted use for the credential (e.g. ENCRYPT_ONLY, DECRYPT_ONLY, SIGN_ONLY, VERIFY_ONLY and combinations thereof). Additionally, when establishing the environment you can request an OID set of services to request (e.g PER_CONF, REC_CONF, PER_POO, REC_POO, ... and combinations thereof). Can you see any value in having both? Any of the IDUP 'cred_usage' bits appears to indicate that we require an IDUP credential element and thus I see no reason why service requirements are duplicated at both levels. Can we suggest that the credential usage should therefore be IDUP_C_ENVIRONMENT (in addition to GSS_C_INITIATE and GSS_C_ACCEPT) and that restricted service requirements are only made at the environment establishment phase. This is more in line with the GSS model - as per the service flags (deleg_req_flag, mutual_req_flag, ...) given at gss_init_sec_context call. This does not negate the previous comments, but would rather simplify the credential usage concept - i.e. a credential can be used for initiating contexts, accepting contexts or creating environments or combinations thereof (all lying in the same dimension). The application programmer should request the desired features and check to see if the required subset is available. Graham Bland Zergo -- Zergo Limited, The Square, Basing View, Basingstoke, Hants. RG21 4EG, UK Tel: + 44 (0) 1442 342 600 Fax: +44 (0) 1256 812 901 Website: http://www.zergo.com To: IETF-Announce@ns.ietf.org Cc: cat-ietf@MIT.EDU From: Internet-Drafts@ns.ietf.org Reply-To: Internet-Drafts@ns.ietf.org Subject: I-D ACTION:draft-ietf-cat-mpaker-00.txt Date: Wed, 14 Jan 1998 09:53:45 -0500 A New Internet-Draft is available from the on-line Internet-Drafts directories. This draft is a work item of the Common Authentication Technology Working Group of the IETF. Title : The Multiple-Path Authentication of Kerberos (MPAKER) Author(s) : L. Harn, Y. Xu Filename : draft-ietf-cat-mpaker-00.txt Pages : 9 Date : 13-Jan-98 This draft proposes an authentication scheme that improves the efficiency and security without losing features of the standard Kerberos and other extension schemes. Instead of completely replacing those schemes, the new scheme can be integrated with them to provide multiple-path authentication for Kerberos. Internet-Drafts are available by anonymous FTP. Login with the username "anonymous" and a password of your e-mail address. After logging in, type "cd internet-drafts" and then "get draft-ietf-cat-mpaker-00.txt". A URL for the Internet-Draft is: ftp://ds.internic.net/internet-drafts/draft-ietf-cat-mpaker-00.txt Internet-Drafts directories are located at: Africa: ftp.is.co.za Europe: ftp.nordu.net ftp.nis.garr.it Pacific Rim: munnari.oz.au US East Coast: ds.internic.net US West Coast: ftp.isi.edu Internet-Drafts are also available by mail. Send a message to: mailserv@ds.internic.net. In the body type: "FILE /internet-drafts/draft-ietf-cat-mpaker-00.txt". NOTE: The mail server at ds.internic.net can return the document in MIME-encoded form by using the "mpack" utility. To use this feature, insert the command "ENCODING mime" before the "FILE" command. To decode the response(s), you will need "munpack" or a MIME-compliant mail reader. Different MIME-compliant mail readers exhibit different behavior, especially when dealing with "multipart" MIME messages (i.e. documents which have been split up into multiple messages), so check your local documentation on how to manipulate these messages. Below is the data which will enable a MIME compliant mail reader implementation to automatically retrieve the ASCII version of the Internet-Draft. <ftp://ds.internic.net/internet-drafts/draft-ietf-cat-mpaker-00.txt> From: Graham Bland <gbland@zergo.com> Date: Thu, 15 Jan 1998 10:31:04 +0000 To: cat-ietf@mit.edu Subject: IDUP Compatibility of call sets X-Mime-Autoconverted: from quoted-printable to 8bit by pad-thai.cam.ov.com id FAA02854 Another question or change: When generating evidence by the EV call subset evidence_check is returned as an octet string (implemented as a gss_buffer_t) which will be opaque to the caller. When the EV calls are used for the verification of the evidence this is passed to idup_ev_xxbuffer_startverify() in the same format. However if the GP calls are used for the verify I cannot see how the evidence_check contents can be mapped onto the parameters of the idup_start_unprotect call. Can anybody help or is this a change to the specification ? Graham Bland Zergo. -- Zergo Limited, The Square, Basing View, Basingstoke, Hants. RG21 4EG, UK Tel: + 44 (0) 1442 342 600 Fax: +44 (0) 1256 812 901 Website: http://www.zergo.com Date: Thu, 15 Jan 1998 07:39:46 EST From: "Martin Carpenter" <mjc@uk.ibm.com> To: cat-ietf@mit.edu Cc: housley@spyrus.com, yee@spyrus.com, WANace@missi.ncsc.mil Subject: re: CAT-WG Last-Call: draft-ietf-cat-ftpdsaauth-00.txt John Linn wrote: > Per discussion at the DC IETF, this message is to open a CAT-WG > Last-Call on draft-ietf-cat-ftpdsaauth-00.txt, "FTP Authentication using > DSA", which profiles the use of FTP Security Extensions (RFC-2228) with > DSA and SHA-1 algorithms. Please send any discussion or comments on > this draft and its prospective recommendation for advancement to > Proposed Standard to the CAT-WG list NLT Tuesday, 3 February 1998. Okay, here are mine. My concerns are listed below in the order that I found them as I read the draft. Apologies, as ever, for my slow response. 1. "* server authentication -- normally done in conjunction with user authentication;". I object to the clause after "--" (and pick nits for England). Anonymous FTP, anyone? 2. "PROT commands may be sent on a transfer-by-transfer basis, however, the session parameters may not be changed within a session.". What about successive AUTH commands within one session? From RFC 2228: Some servers will allow the AUTH command to be reissued in order to establish new authentication. The AUTH command, if accepted, removes any state associated with prior FTP Security commands. The server must also require that the user reauthorize (that is, reissue some or all of the USER, PASS, and ACCT commands) in this case (see section 4 for an explanation of "authorize" in this context). Or is the draft meant to say something like "the session parameters may not be altered during an existent data interchange such as to effect the mechanism being employed for that interchange."? (I'm thinking of a server happily accepting new AUTH commands on the control connection whilst it's still sending/receiving stuff on the data connection; perhaps I'm just not clear about the definition of the word "session"). 3. The example exchange: MIC Base64(Sign("PBSZ 65535")) --> <-- 200 PBSZ=32767 MIC Base64(Sign("USER yee")) --> <-- 331 and the accompanying text: "Specifically, the file is broken up into blocks of data of less than the negotiated protection buffer size (32768 bytes in the example exchanges).". Unless I've missed something subtle in the RFC, shouldn't this latter paragraph read "... (32767 bytes in the example exchanges)."? Yes, I am aware that number of bytes of file data sent per block will be "less than" the negotiated PBSZ value, but won't the number of bytes in any buffer that is sent in a block be "less than or equal" to the negotiated PBSZ value (of 32767 in the example above)? I *think* that the author wanted to link the "32768 bytes" with the "less than" (to get "less than or equal to 32767"), but I think that what it *actually* says is that 32768 bytes was the negotiated buffer size, which it wasn't. And I'm not entirely happy with "... the file is broken up...". Perhaps: "... the *encrypted* file" is broken up..." maybe, or "... the file is broken up into blocks of data such that when encrypted, the encrypted block size is less than or equal to the negotiated protection buffer size". *Phew* that took much longer to say than I thought it would :-) Regards, Martin. Martin Carpenter Tie 7-664834 IBM Global Network NOSS CARPEMJ@NHBVM9 EDI Dev & Spt, Warwick, UK Notes CARPEMJ@IBMGB Tel +44 (0)1926 464834 email mjc@uk.ibm.com
- GSS and IDUP Graham Bland