500 lines
19 KiB
Plaintext
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|