//////////////////////////////////////////////////////////////////////////////// // // 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. } }