singrdk/base/Libraries/CredentialsManager/CredentialsManager.sg

500 lines
19 KiB
Plaintext

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Libraries/CredentialsManager/CredentialsManager.sg
//
// Note:
//
// This library is mostly a wrapper for the CredentialsManagerContract.
// It simplifies connecting to and using the Credentials Manager service.
// Most of the request/response messages of the CredentialsManagerContract
// are exposed as static methods on the CredentialsManager class.
//
// For each request, two static methods are provided; one that borrows a
// reference to CredentialsManagerContract.Imp, and one that does not.
// The methods that do not take a reference will create and connect a
// channel to the Credentials Manager service, perform the request (by
// calling the other method overload) and then delete the channel.
// Applications that need issue only a small number of requests can use the
// no-reference variations; apps that will issue many requests can call the
// ConnectService() method, and call the variations that do take an endpoint,
// then delete the endpoint when necessary.
//
using System;
using Microsoft.Contracts;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using Microsoft.SingSharp;
namespace Microsoft.Singularity.Security
{
public sealed /* static */ class CredentialsManager
{
private CredentialsManager() {}
public static CredentialsManagerContract.Imp! ConnectService()
{
CredentialsManagerContract.Imp! manager;
CredentialsManagerContract.Exp! manager_exp;
CredentialsManagerContract.NewChannel(out manager, out manager_exp);
DirectoryServiceContract.Imp! rootds = DirectoryService.NewClientEndpoint();
ErrorCode error;
if (SdsUtils.Bind(CredentialsManagerContract.ChannelPath, rootds, manager_exp, out error)) {
manager.RecvSuccess();
delete rootds;
return manager;
}
else {
delete manager;
delete rootds;
throw new Exception(String.Format("Failed to bind to control channel '{0}': error {1}", CredentialsManagerContract.ChannelPath, error));
}
}
public static string! CredErrorToString(CredError error)
{
switch (error) {
case CredError.NoError: return "No error";
case CredError.InternalError: return "Internal error";
case CredError.NoMatchingCredentials: return "No matching credentials";
case CredError.MatchingEntryExists: return "A matching entry already exists";
case CredError.NoMatchingAuthenticationProtocol: return "No authentication protocol exists with that name.";
case CredError.NoEntryFound: return "No matching entry was found.";
case CredError.ContractNotSupported: return "The channel provided does not implement any supported contract.";
case CredError.InvalidArguments: return "Invalid arguments were provided.";
case CredError.EvidenceTypeNotSupported: return "The authentication protocol that was selected does not support the type of evidence used by the credentials.";
default: return "(" + ((int)error) + ")";
}
}
public static string! GssErrorCodeToString(GssErrorCode error)
{
switch (error) {
case GssErrorCode.InternalError: return "Internal error";
case GssErrorCode.ServerRefusedAuthentication: return "The server refused authentication.";
default:
return ((int)error).ToString();
}
}
public static void CreateSupplicant(
CredentialsManagerContract.Imp! manager,
string! authenticationProtocol,
string! credentialsName,
string! tag,
[Claims]ServiceContract.Exp! exp)
{
CredentialsId id = new CredentialsId();
id.CredentialsName = Bitter.FromString2(credentialsName);
id.Tag = Bitter.FromString2(tag);
manager.SendCreateSupplicant(Bitter.FromString2(authenticationProtocol), id, exp);
switch receive {
case manager.Ok():
break;
case manager.RequestFailed(error):
throw new CredentialsManagerException("The supplicant could not be created.", error);
}
}
public static void CreateSupplicant(
string! authenticationProtocol,
string! credentialsName,
string! tag,
[Claims]ServiceContract.Exp! exp)
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
CreateSupplicant(
manager,
authenticationProtocol,
credentialsName,
tag,
exp);
}
finally {
delete manager;
}
}
public static void CreateSupplicantForProtocol(
CredentialsManagerContract.Imp! manager,
string! applicationProtocol,
string! serviceAddress,
string! authenticationProtocol,
string! realm,
[Claims]ServiceContract.Exp:Start! exp,
out string! credentialsName,
out string! tag)
{
ProtocolTuple tuple = new ProtocolTuple();
tuple.ApplicationProtocol = Bitter.FromString2(applicationProtocol);
tuple.ServiceAddress = Bitter.FromString2(serviceAddress);
tuple.AuthenticationProtocol = Bitter.FromString2(authenticationProtocol);
tuple.Realm = Bitter.FromString2(realm);
manager.SendCreateSupplicantForProtocol(tuple, exp);
switch receive {
case manager.AckCreateSupplicantForProtocol(credentialsSelected):
credentialsName = Bitter.ToString2(credentialsSelected.CredentialsName);
tag = Bitter.ToString2(credentialsSelected.Tag);
credentialsSelected.Dispose();
break;
case manager.RequestFailed(error):
throw new CredentialsManagerException("The authentication supplicant could not be created.", error);
}
}
public static void CreateSupplicantForProtocol(
string! applicationProtocol,
string! serviceAddress,
string! authenticationProtocol,
string! realm,
[Claims]ServiceContract.Exp:Start! exp,
out string! credentialsName,
out string! tag)
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
CreateSupplicantForProtocol(
manager,
applicationProtocol,
serviceAddress,
authenticationProtocol,
realm,
exp,
out credentialsName,
out tag);
}
finally {
delete manager;
}
}
public static void AddCredentials(
CredentialsManagerContract.Imp! manager,
string! credentialsName,
string! tag,
string! password,
bool replace)
{
CredentialsId id = new CredentialsId();
id.CredentialsName = Bitter.FromString2(credentialsName);
id.Tag = Bitter.FromString2(tag);
manager.SendAddCredentials(id, Bitter.FromString2(password), replace);
switch receive {
case manager.Ok():
break;
case manager.RequestFailed(CredError error):
throw new CredentialsManagerException("The request to add credentials failed.", error);
case manager.ChannelClosed():
throw new CredentialsManagerException(ChannelClosedMsg);
}
}
public static void AddCredentials(
string! credentialsName,
string! tag,
string! password,
bool replace)
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
AddCredentials(manager, credentialsName, tag, password, replace);
}
finally {
delete manager;
}
}
public static void DeleteCredentials(
CredentialsManagerContract.Imp! manager,
string! credentialsName,
string! tag)
{
CredentialsId id = new CredentialsId();
id.CredentialsName = Bitter.FromString2(credentialsName);
id.Tag = Bitter.FromString2(tag);
manager.SendDeleteCredentials(id);
switch receive {
case manager.Ok():
break;
case manager.RequestFailed(CredError error):
throw new CredentialsManagerException("The request to delete credentials failed.", error);
case manager.ChannelClosed():
throw new CredentialsManagerException(ChannelClosedMsg);
}
}
public static void DeleteCredentials(
string! credentialsName,
string! tag)
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
DeleteCredentials(manager, credentialsName, tag);
}
finally {
delete manager;
}
}
public static void DeleteAllCredentials(CredentialsManagerContract.Imp! manager)
{
manager.SendDeleteAllCredentials();
switch receive {
case manager.Ok():
break;
case manager.RequestFailed(CredError error):
throw new CredentialsManagerException("The request to delete all credentials failed.", error);
case manager.ChannelClosed():
throw new CredentialsManagerException(ChannelClosedMsg);
}
}
public static void DeleteAllCredentials()
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
DeleteAllCredentials(manager);
}
finally {
delete manager;
}
}
public static void AddProtocolMapping(
CredentialsManagerContract.Imp! manager,
string! applicationProtocol,
string! serviceAddress,
string! authenticationProtocol,
string! realm,
string! credentialsName,
string! tag,
bool replace)
{
ProtocolTuple tuple = new ProtocolTuple();
tuple.ApplicationProtocol = Bitter.FromString2(applicationProtocol);
tuple.ServiceAddress = Bitter.FromString2(serviceAddress);
tuple.AuthenticationProtocol = Bitter.FromString2(authenticationProtocol);
tuple.Realm = Bitter.FromString2(realm);
CredentialsId id = new CredentialsId();
id.CredentialsName = Bitter.FromString2(credentialsName);
id.Tag = Bitter.FromString2(tag);
manager.SendAddProtocolMapping(tuple, id, replace);
switch receive {
case manager.Ok():
break;
case manager.RequestFailed(CredError error):
throw new CredentialsManagerException("The request to add a protocol mapping failed.", error);
}
}
public static void AddProtocolMapping(
string! applicationProtocol,
string! serviceAddress,
string! authenticationProtocol,
string! realm,
string! credentialsName,
string! tag,
bool replace)
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
AddProtocolMapping(
manager,
applicationProtocol,
serviceAddress,
authenticationProtocol,
realm,
credentialsName,
tag,
replace);
}
finally {
delete manager;
}
}
public static void DeleteProtocolMapping(
CredentialsManagerContract.Imp! manager,
string! applicationProtocol,
string! serviceAddress,
string! authenticationProtocol,
string! realm)
{
ProtocolTuple tuple = new ProtocolTuple();
tuple.ApplicationProtocol = Bitter.FromString2(applicationProtocol);
tuple.ServiceAddress = Bitter.FromString2(serviceAddress);
tuple.AuthenticationProtocol = Bitter.FromString2(authenticationProtocol);
tuple.Realm = Bitter.FromString2(realm);
manager.SendDeleteProtocolMapping(tuple);
switch receive {
case manager.Ok():
break;
case manager.RequestFailed(CredError error):
throw new CredentialsManagerException("The request to delete a protocol mapping failed.", error);
}
}
public static void DeleteProtocolMapping(
string! applicationProtocol,
string! serviceAddress,
string! authenticationProtocol,
string! realm)
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
DeleteProtocolMapping(
manager,
applicationProtocol,
serviceAddress,
authenticationProtocol,
realm);
}
finally {
delete manager;
}
}
public static void DeleteAllProtocolMappings(CredentialsManagerContract.Imp! manager)
{
manager.SendDeleteAllProtocolMappings();
switch receive {
case manager.Ok():
break;
case manager.RequestFailed(CredError error):
throw new CredentialsManagerException("The request to delete all protocol mappings failed.", error);
}
}
public static void DeleteAllProtocolMappings()
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
DeleteAllProtocolMappings(manager);
}
finally {
delete manager;
}
}
public static bool FindMatchingProtocolMapping(
CredentialsManagerContract.Imp! manager,
string! applicationProtocol,
string! serviceAddress,
string! authenticationProtocol,
string! realm,
bool useWildcard,
out string! credentialsName,
out string! tag)
{
ProtocolTuple tuple = new ProtocolTuple();
tuple.ApplicationProtocol = Bitter.FromString2(applicationProtocol);
tuple.ServiceAddress = Bitter.FromString2(serviceAddress);
tuple.AuthenticationProtocol = Bitter.FromString2(authenticationProtocol);
tuple.Realm = Bitter.FromString2(realm);
manager.SendFindMatchingProtocolMapping(tuple, useWildcard);
switch receive {
case manager.NoMatchingProtocolMapping():
credentialsName = "";
tag = "";
return false;
case manager.MatchingProtocolMapping(CredentialsId credentials):
credentialsName = Bitter.ToString2(credentials.CredentialsName);
tag = Bitter.ToString2(credentials.Tag);
credentials.Dispose();
return true;
case manager.RequestFailed(error):
throw new CredentialsManagerException("The request to find a protocol mapping failed.", error);
}
}
public static bool FindMatchingProtocolMapping(
string! applicationProtocol,
string! serviceAddress,
string! authenticationProtocol,
string! realm,
bool useWildcard,
out string! credentialsName,
out string! tag)
{
CredentialsManagerContract.Imp! manager = ConnectService();
try {
return FindMatchingProtocolMapping(
manager,
applicationProtocol,
serviceAddress,
authenticationProtocol,
realm,
useWildcard,
out credentialsName,
out tag);
}
finally {
delete manager;
}
}
const string! ChannelClosedMsg = "The request failed because the Credentials Manager service closed the control channel.";
}
public class CredentialsManagerException : Exception
{
public CredentialsManagerException(CredError error)
{
string! msg = CredentialsManager.CredErrorToString(error);
base(msg);
}
public CredentialsManagerException(string! msg, CredError error)
{
string! errorText = CredentialsManager.CredErrorToString(error);
base(msg + " Error: " + errorText);
}
public CredentialsManagerException(string! msg)
{
base(msg);
}
}
}