//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: Contracts/CredentialsManager.Contracts/GssSupplicantContract.sg // // Note: Defines a contract for use with authentication protocols that // use the GSSAPI model for exchanging tokens between clients and // servers. // using System; using Microsoft.Contracts; using Microsoft.Singularity; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; using Microsoft.SingSharp; namespace Microsoft.Singularity.Security { /** This contract represents an active authentication session. It is modeled after the GSS API, which is a standard API for performing authentication exchanges. (See RFC 2078.) However, this contract models only the behavior of a supplicant (a client who wishes to prove its identity), not that of an authenticator. This contract is analogous to an SSPI session in Win32. See InitializeSecurityContext and friends. In general, applications hold the import endpoint of this contract, while implementations of authentication protocols, implemented in the Credentials Manager Service, hold the export side. The channel is bound using the CreateSupplicant or CreateSupplicantForProtocol requests of the CredentialsManagerContract. Applications ferry opaque authentication tokens between the local supplicant and the remote network service until both sides decide that authentication has succeeded, or one side decides that authentication has failed. Applications should not interpret or modify the contents of the tokens. Authentication protocols vary in the number of messages sent, in which side sends the first message, and in which side sends the last message. This contract supports all message patterns. The supplicant sends the first message to the client application, and that first message indicates whether the supplicant sends the first token, (supplicant sends FirstToken to application), or expects the network service to send the first token (supplicant sends NeedFirstToken). Currently, the only implementor of this contract is the NTLM authentication protocol. However, it is intended that SPNEGO, Kerberos, etc. will eventually implement this contract as well. This contract should be expanded to allow applications to negotiate standard GSS options, such as integrity / confidentiality services, etc. For now, it models only authentication (identification). */ public contract GssSupplicantContract : ServiceContract { /// /// If the supplicant sends this as the first message out of the Start state, /// then the supplicant expects the remote network service to be the first to /// send an authentication token. /// out message NeedFirstToken(); out message FirstToken(byte[]! in ExHeap token); override state Start : one { NeedFirstToken! -> WaitingForToken; FirstToken! -> WaitingForToken; } state WaitingForToken : one { AcceptToken? -> ProcessingToken; } // The application sends this message to the supplicant when it has received // an authentication token from the remote network service. The supplicant // will process the token, and will either decide that authentication has // succeeded, or failed, or that another token must be sent to the network // service (ContinueNeeded). in message AcceptToken(byte[]! in ExHeap token); // The supplicant sends this message in response to AcceptToken when the // supplicant needs to send a message to the remote network service. // The application should send the message, using whatever network transport // is appropriate. Then the application should receive the next authentication // token from the network service, and should forward the token to this // supplicant. out message ContinueNeeded(byte[]! in ExHeap token); // The supplicant sends this message in response to AcceptToken when the // supplicant has processed the last message in the authentication exchange, // and has decided that authentication has succeeded, and has a token it // needs to transmit to the remote network service. The application should // transmit the token to the remote network service, and should consider // authentication to be complete. out message CompleteWithToken(byte[]! in ExHeap token); // The supplicant sends this message in response to AcceptToken when the // supplicant has processed the last message in the authentication exchange, // and has decided that authentication has succeeded, and there is no need // to send another token to the remote network service. The application // should consider authentication to be complete. out message Complete(); // The supplicant sends this message in response to AcceptToken when the // supplicant has decided that authentication has failed. out message AuthenticationFailed(GssErrorCode error); state ProcessingToken : one { AuthenticationFailed! -> Failed; ContinueNeeded! -> WaitingForToken; Complete! -> Succeeded; CompleteWithToken! -> Succeeded; } state Succeeded : one { } state Failed : one { } } public enum GssErrorCode { None = 0, /// The server refused the request, for some unspecified reason. ServerRefusedAuthentication, InternalError, // Add more error codes here, as appropriate, once GSS support is fleshed out more. } }