2008-03-05 09:52:00 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Microsoft Research Singularity
|
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
|
|
|
// File: Services/CredentialsManager/CredentialsManagerService.sg
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
// Note: Contains the entry point and main I/O loop for the service.
|
2008-03-05 09:52:00 -05:00
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
// All clients that connect using the CredentialsManagerContract are
|
|
|
|
// serviced on the "main" thread of the CM. All of the requests of
|
|
|
|
// that contract can be satisfied synchronously (without waiting for
|
|
|
|
// any external I/O or blocking).
|
2008-03-05 09:52:00 -05:00
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
// Supplicant channels are serviced on separate threads. Although it
|
|
|
|
// would be possible to service some of them on the main thread,
|
|
|
|
// separate threads make the code simpler, and allow for later protocols
|
|
|
|
// which might require more serious work be done to service requests.
|
2008-03-05 09:52:00 -05:00
|
|
|
//
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using Microsoft.Contracts;
|
|
|
|
using Microsoft.Singularity;
|
2008-11-17 18:29:00 -05:00
|
|
|
using Microsoft.Singularity.Configuration;
|
2008-03-05 09:52:00 -05:00
|
|
|
using Microsoft.Singularity.Channels;
|
|
|
|
using Microsoft.Singularity.Directory;
|
|
|
|
using Microsoft.Singularity.Io;
|
2008-11-17 18:29:00 -05:00
|
|
|
using Microsoft.Singularity.ServiceManager;
|
2008-03-05 09:52:00 -05:00
|
|
|
using Microsoft.SingSharp;
|
|
|
|
|
|
|
|
using Ex = Microsoft.Singularity.Security;
|
|
|
|
|
|
|
|
namespace Microsoft.Singularity.Security.CredentialsManager
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
[Category("Service")]
|
|
|
|
internal class ServiceParameters
|
|
|
|
{
|
|
|
|
[CustomEndpoint]
|
|
|
|
public readonly TRef<ServiceProcessContract.Exp:Starting> ControlEndpointRef;
|
|
|
|
|
|
|
|
[CustomEndpoint]
|
|
|
|
public readonly TRef<ServiceEventContract.Imp:Ready> EventEndpointRef;
|
|
|
|
|
|
|
|
reflective private ServiceParameters();
|
|
|
|
}
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
internal class CredentialsManagerService : ITracked
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
internal static int AppMain(ServiceParameters! parameters)
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
assert parameters.ControlEndpointRef != null;
|
|
|
|
assert parameters.EventEndpointRef != null;
|
|
|
|
|
|
|
|
ServiceProcessContract.Exp:Starting! svcontrol = parameters.ControlEndpointRef.Acquire();
|
|
|
|
ServiceEventContract.Imp:Ready! svevent = parameters.EventEndpointRef.Acquire();
|
|
|
|
|
|
|
|
CredentialsManagerService service = new CredentialsManagerService(svcontrol, svevent);
|
2008-03-05 09:52:00 -05:00
|
|
|
try {
|
|
|
|
service.Run();
|
|
|
|
return 0;
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
finally {
|
2008-03-05 09:52:00 -05:00
|
|
|
service.Dispose();
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
#region Instance Fields
|
|
|
|
|
|
|
|
readonly ServiceProcessContract.Exp! svmanager;
|
|
|
|
|
|
|
|
readonly ServiceEventContract.Imp! svevent;
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
readonly CredentialsCollection! _credentials = new CredentialsCollection();
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
readonly ProtocolMappingCollection! _protocolMappings = new ProtocolMappingCollection();
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
readonly ESet<CredentialsManagerContract.Exp:Ready>! clients = new ESet<CredentialsManagerContract.Exp:Ready>();
|
|
|
|
|
|
|
|
readonly Hashtable/*<string,AuthenticationProtocol>*/! _authenticationProtocols = new Hashtable();
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
CredentialsManagerService(
|
|
|
|
[Claims]ServiceProcessContract.Exp:Starting! svcontrol,
|
|
|
|
[Claims]ServiceEventContract.Imp:Ready! svevent)
|
|
|
|
{
|
|
|
|
this.svmanager = svcontrol;
|
|
|
|
this.svevent = svevent;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
delete svmanager;
|
|
|
|
delete svevent;
|
|
|
|
clients.Dispose();
|
|
|
|
}
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
void Run()
|
|
|
|
{
|
|
|
|
_authenticationProtocols[AuthenticationProtocolNames.Ntlm] = new NtlmAuthenticationProtocol();
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
expose(this) {
|
|
|
|
|
|
|
|
svmanager.SendStartSucceeded();
|
|
|
|
|
|
|
|
for (;;) {
|
2008-03-05 09:52:00 -05:00
|
|
|
try {
|
2008-11-17 18:29:00 -05:00
|
|
|
switch receive {
|
|
|
|
case svmanager.Connect(char[] in ExHeap expath, ServiceContract.Exp:Start! exp):
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
if (expath != null) {
|
|
|
|
string! path = Bitter.ToString2(expath);
|
|
|
|
DebugLine("Received 'Connect' from Service Manager, for subpath '{0}'.", path);
|
|
|
|
DebugLine("This service does not support subpaths, so the connect request will be rejected.");
|
|
|
|
delete expath;
|
|
|
|
delete exp;
|
|
|
|
svmanager.SendNakConnect(ErrorCode.NotFound, null);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
CredentialsManagerContract.Exp:Start client = exp as CredentialsManagerContract.Exp:Start;
|
|
|
|
if (client != null) {
|
|
|
|
DebugLine("Received 'Connect' from Service Manager, using CredentialsManagerContract.");
|
|
|
|
client.SendSuccess();
|
|
|
|
clients.Add(client);
|
|
|
|
svmanager.SendAckConnect();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DebugLine("Received 'Connect' from Service Manager, but the contract is not recognized.");
|
|
|
|
delete exp;
|
|
|
|
svmanager.SendNakConnect(ErrorCode.ContractNotSupported, null);
|
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
case svmanager.ChannelClosed():
|
|
|
|
DebugLine("Service manager has closed the managed service channel. Not good. Terminating.");
|
|
|
|
return;
|
|
|
|
|
|
|
|
case svmanager.Knock():
|
|
|
|
DebugLine("Received Knock from Service Manager. Answering with Alive.");
|
|
|
|
svmanager.SendAlive();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case svmanager.Stop():
|
|
|
|
DebugLine("Received 'Stop' from Service Manager. Stopping.");
|
|
|
|
svmanager.SendAckStop();
|
|
|
|
return;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
case client.ChannelClosed() in clients:
|
|
|
|
// DebugLine("Client has disconnected.");
|
|
|
|
delete client;
|
|
|
|
break;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.AddCredentials(Ex.CredentialsId excredentials, char[]! in ExHeap expassword, bool replace) in clients:
|
|
|
|
{
|
|
|
|
CredentialsId id = new CredentialsId(
|
|
|
|
Bitter.ToString2(excredentials.CredentialsName),
|
|
|
|
Bitter.ToString2(excredentials.Tag));
|
|
|
|
string! password = Bitter.ToString2(expassword);
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
excredentials.Dispose();
|
2008-03-05 09:52:00 -05:00
|
|
|
delete expassword;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages) {
|
|
|
|
DebugLine("Received AddCredentials: " + id + " [evidence not shown]");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_credentials.ContainsKey(id) && !replace) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Already have credentials matching that key.");
|
|
|
|
client.SendRequestFailed(CredError.MatchingEntryExists);
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Setting credentials.");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
PasswordEvidence evidence = new PasswordEvidence(password);
|
|
|
|
Credentials credentials = new Credentials(id, evidence);
|
|
|
|
_credentials[id] = credentials;
|
|
|
|
client.SendOk();
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.DeleteCredentials(excredentials) in clients:
|
|
|
|
{
|
|
|
|
CredentialsId id = new CredentialsId(
|
|
|
|
Bitter.ToString2(excredentials.CredentialsName),
|
|
|
|
Bitter.ToString2(excredentials.Tag));
|
|
|
|
excredentials.Dispose();
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received DeleteCredentials: " + id.ToString());
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (_credentials.ContainsKey(id)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Removing credentials.");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
_credentials.Remove(id);
|
|
|
|
client.SendOk();
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" No such credentials registered.");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
client.SendRequestFailed(CredError.NoMatchingCredentials);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
clients.Add(client);
|
2008-03-05 09:52:00 -05:00
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.DeleteAllCredentials() in clients:
|
|
|
|
{
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received DeleteAllCredentials");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
_credentials.Clear();
|
|
|
|
client.SendOk();
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.EnumerateCredentials() in clients:
|
|
|
|
{
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received EnumerateCredentials");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
ICollection! keys = (!)_credentials.Keys;
|
|
|
|
int count = keys.Count;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Sending " + count + " entries");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
Ex.CredentialsId[]! in ExHeap list = new[ExHeap] Ex.CredentialsId[count];
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
IEnumerator enumerator = keys.GetEnumerator();
|
|
|
|
for (int i = 0; i < count; i++) {
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (!enumerator.MoveNext()) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Enumerator lied to us!");
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
CredentialsId! id = (!)(CredentialsId)enumerator.Current;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Entry: " + id.ToString());
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
expose(list[i]) {
|
|
|
|
// these will be null, but we have to keep the type checker happy
|
|
|
|
delete list[i].CredentialsName;
|
|
|
|
delete list[i].Tag;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
list[i].CredentialsName = Bitter.FromString2(id.CredentialsName);
|
2008-11-17 18:29:00 -05:00
|
|
|
list[i].Tag = Bitter.FromString2(id.Tag);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
client.SendCredentialsList(list);
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.AddProtocolMapping(Ex.ProtocolTuple extuple, Ex.CredentialsId excredentials, bool replace) in clients:
|
|
|
|
{
|
|
|
|
ProtocolTuple tuple = new ProtocolTuple(extuple);
|
|
|
|
CredentialsId credentials = new CredentialsId(excredentials);
|
|
|
|
extuple.Dispose();
|
|
|
|
excredentials.Dispose();
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received AddProtocolMapping: {0} -> {1}", tuple.ToString(), credentials.ToString());
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (!replace && _protocolMappings.ContainsKey(tuple)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("A protocol mapping with the same key already exists.");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
client.SendRequestFailed(CredError.MatchingEntryExists);
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (!_credentials.ContainsKey(credentials)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("The specified credentials do not exist.");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
client.SendRequestFailed(CredError.NoMatchingCredentials);
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
_protocolMappings[tuple] = credentials;
|
|
|
|
client.SendOk();
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.DeleteProtocolMapping(Ex.ProtocolTuple extuple) in clients:
|
|
|
|
ProtocolTuple tuple = new ProtocolTuple(extuple);
|
|
|
|
extuple.Dispose();
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received DeleteProtocolMapping: tuple = " + tuple.ToString());
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (_protocolMappings.ContainsKey(tuple)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Protocol mapping removed.");
|
|
|
|
_protocolMappings.Remove(tuple);
|
|
|
|
client.SendOk();
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" No matching entry");
|
|
|
|
client.SendRequestFailed(CredError.NoMatchingCredentials);
|
|
|
|
}
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.DeleteAllProtocolMappings() in clients:
|
|
|
|
{
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received DeleteAllProtocolMappings");
|
|
|
|
_protocolMappings.Clear();
|
|
|
|
client.SendOk();
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.FindMatchingProtocolMapping(Ex.ProtocolTuple extuple, bool useWildcards) in clients:
|
|
|
|
{
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received FindMatchingProtocolMapping:");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
ProtocolTuple tuple = new ProtocolTuple(extuple);
|
|
|
|
extuple.Dispose();
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
CredentialsId match;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (FindMatchingProtocolMapping(tuple, out match, useWildcards)) {
|
|
|
|
assert match != null;
|
|
|
|
DebugLine(" Match found: " + match.ToString());
|
|
|
|
client.SendMatchingProtocolMapping(match.ToExchange());
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
DebugLine(" No matching entry found.");
|
|
|
|
client.SendRequestFailed(CredError.NoMatchingCredentials);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.EnumerateProtocolMappings() in clients:
|
|
|
|
{
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received EnumerateProtocolMappings");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
int count = _protocolMappings.Count;
|
|
|
|
Ex.ProtocolMapping[]! in ExHeap list = new[ExHeap] Ex.ProtocolMapping[count];
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
IEnumerator enumerator = _protocolMappings.GetEnumerator();
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
if (!enumerator.MoveNext()) {
|
|
|
|
DebugLine("Enumerator lied!!");
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
DictionaryEntry entry = (DictionaryEntry)(!)enumerator.Current;
|
|
|
|
ProtocolTuple! tuple = (ProtocolTuple)entry.Key;
|
|
|
|
CredentialsId! id = (!)(CredentialsId)entry.Value;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
expose (list[i]) {
|
|
|
|
list[i].Dispose();
|
|
|
|
list[i].ProtocolTuple.ApplicationProtocol = Bitter.FromString2(tuple.ApplicationProtocol);
|
|
|
|
list[i].ProtocolTuple.AuthenticationProtocol = Bitter.FromString2(tuple.AuthenticationProtocol);
|
|
|
|
list[i].ProtocolTuple.ServiceAddress = Bitter.FromString2(tuple.ServiceAddress);
|
|
|
|
list[i].ProtocolTuple.Realm = Bitter.FromString2(tuple.Realm);
|
|
|
|
list[i].CredentialsId.CredentialsName = Bitter.FromString2(id.CredentialsName);
|
2008-11-17 18:29:00 -05:00
|
|
|
list[i].CredentialsId.Tag = Bitter.FromString2(id.Tag);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
client.SendProtocolMappings(list);
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.CreateSupplicant(
|
|
|
|
char[]! in ExHeap exauthenticationProtocol,
|
|
|
|
Ex.CredentialsId excredentials,
|
|
|
|
ServiceContract.Exp:Start! exp) in clients:
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine("Received CreateSupplicant");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
string! authenticationProtocol = Util.ToStringDelete(exauthenticationProtocol);
|
|
|
|
CredentialsId! id = new CredentialsId(excredentials);
|
|
|
|
excredentials.Dispose();
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Credentials ID: " + id);
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
// First, find credentials.
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
Credentials credentials;
|
|
|
|
if (!_credentials.TryGetValue(id, out credentials)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Credentials not found.");
|
|
|
|
delete exp;
|
|
|
|
client.SendRequestFailed(CredError.NoMatchingCredentials);
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
assert credentials != null;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
// For now, we support only a hard-coded set of authentication protocols.
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
AuthenticationProtocol protocol = (AuthenticationProtocol)_authenticationProtocols[authenticationProtocol];
|
|
|
|
if (protocol == null) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Authentication protocol not recognized: " + authenticationProtocol);
|
|
|
|
client.SendRequestFailed(CredError.NoMatchingAuthenticationProtocol);
|
|
|
|
delete exp;
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
CredError error;
|
|
|
|
if (protocol.CreateSupplicant(exp, credentials, out error)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Authentication protocol accepted client");
|
|
|
|
client.SendOk();
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Authentication protocol refused client: " + error);
|
|
|
|
client.SendRequestFailed(error);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
case client.CreateSupplicantForProtocol(Ex.ProtocolTuple extuple, ServiceContract.Exp:Start! exp) in clients:
|
|
|
|
{
|
|
|
|
ProtocolTuple tuple = new ProtocolTuple(extuple);
|
|
|
|
extuple.Dispose();
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages) {
|
|
|
|
DebugLine("Received CreateSupplicantForProtocol");
|
|
|
|
DebugLine(" Tuple = " + tuple);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
// First, find credentials.
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
CredentialsId id;
|
|
|
|
if (!FindMatchingProtocolMapping(tuple, out id, true)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" No matching credentials found.");
|
|
|
|
delete exp;
|
|
|
|
client.SendRequestFailed(CredError.NoMatchingCredentials);
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
assert id != null;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Selected credentials: " + id);
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
Credentials credentials;
|
|
|
|
if (!_credentials.TryGetValue(id, out credentials)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Credentials not found.");
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
delete exp;
|
|
|
|
client.SendRequestFailed(CredError.NoMatchingCredentials);
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
assert credentials != null;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
AuthenticationProtocol protocol = (AuthenticationProtocol)_authenticationProtocols[tuple.AuthenticationProtocol];
|
|
|
|
if (protocol == null) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Authentication protocol not recognized: " + tuple.AuthenticationProtocol);
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
client.SendRequestFailed(CredError.NoMatchingAuthenticationProtocol);
|
|
|
|
delete exp;
|
|
|
|
clients.Add(client);
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
CredError error;
|
|
|
|
if (protocol.CreateSupplicant(exp, credentials, out error)) {
|
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Authentication protocol accepted client");
|
|
|
|
client.SendAckCreateSupplicantForProtocol(id.ToExchange());
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowManagerMessages)
|
|
|
|
DebugLine(" Authentication protocol refused client: " + error);
|
|
|
|
client.SendRequestFailed(error);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
clients.Add(client);
|
2008-11-17 18:29:00 -05:00
|
|
|
break;
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
catch (Exception ex) {
|
2008-03-05 09:52:00 -05:00
|
|
|
DebugLine("Uncaught exception in switch-receive loop!");
|
|
|
|
Util.DumpException(ex);
|
|
|
|
DebugLine("Will soldier on...");
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
// This is a permutation on 4 bits, sorted in ascending order
|
|
|
|
// of the number of bits that are set to 1. We use this to order
|
|
|
|
// our search of the protocol mappings table. Each bit in the mask
|
|
|
|
// that is set to 1 indicates a field in ProtocolTuple to replace
|
|
|
|
// with a wildcard.
|
|
|
|
static readonly int[]! _WildcardMasks = {
|
2008-11-17 18:29:00 -05:00
|
|
|
0, // 0000 // 0 bits set
|
|
|
|
1, // 0001 // 1 bit set
|
|
|
|
2, // 0010
|
|
|
|
4, // 0100
|
|
|
|
8, // 1000
|
|
|
|
3, // 0011 // groups with 2 bits set
|
|
|
|
5, // 0101
|
|
|
|
6, // 0110
|
|
|
|
9, // 1001
|
|
|
|
10, // 1010
|
|
|
|
12, // 1100
|
|
|
|
7, // 0111 // 3 bits set
|
|
|
|
11, // 1011
|
|
|
|
13, // 1101
|
|
|
|
14, // 1110
|
|
|
|
15, // 1111 // 4 bits set
|
2008-03-05 09:52:00 -05:00
|
|
|
};
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This class searches the protocol mappings table for credentials that match a given
|
|
|
|
/// protocol tuple. If the useWildcard argument is false, then a single, exact match
|
|
|
|
/// is performed. If the useWildcard argument is true, then the method will search for
|
|
|
|
/// the most specific protocol mapping that matches the tuple provided. If an exact
|
|
|
|
/// search does not find a tuple, then the method will replace some of the fields with
|
|
|
|
/// the wildcard marker ("*") and try again, until it has tried all combinations of
|
|
|
|
/// fields, including the "all fields wild" tuple of < * * * * >. The _WildcardMasks
|
|
|
|
/// array controls the search order.
|
|
|
|
///</summary>
|
2008-03-05 09:52:00 -05:00
|
|
|
bool FindMatchingProtocolMapping(ProtocolTuple! tuple, out CredentialsId match, bool useWildcards)
|
|
|
|
{
|
|
|
|
if (useWildcards) {
|
|
|
|
if (TraceSwitches.ShowWildcardMatching) {
|
|
|
|
DebugLine(" Query is a wildcard query");
|
|
|
|
DebugLine("Generating variations of this tuple: " + tuple);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
match = null;
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
// bit 0:
|
|
|
|
for (int permutation_index = 0; permutation_index < _WildcardMasks.Length; permutation_index++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
int wildcard_mask = _WildcardMasks[permutation_index];
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
// If the tuple that we're using as our search key
|
2008-03-05 09:52:00 -05:00
|
|
|
// Each bit in 'wildcard_mask' corresponds to a field in ProtocolTuple.
|
|
|
|
// Generate a search tuple (variation) with some values replaced with the wildcard marker "*".
|
|
|
|
// Then query the table for the variation.
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
ProtocolTuple variation = new ProtocolTuple(
|
|
|
|
((wildcard_mask & (1 << ProtocolTuple.ApplicationProtocolMaskBit)) != 0) ? ProtocolTuple.WildcardValue : tuple.ApplicationProtocol,
|
|
|
|
((wildcard_mask & (1 << ProtocolTuple.ServiceAddressMaskBit)) != 0) ? ProtocolTuple.WildcardValue : tuple.ServiceAddress,
|
|
|
|
((wildcard_mask & (1 << ProtocolTuple.AuthenticationProtocolMaskBit)) != 0) ? ProtocolTuple.WildcardValue : tuple.AuthenticationProtocol,
|
|
|
|
((wildcard_mask & (1 << ProtocolTuple.RealmMaskBit)) != 0) ? ProtocolTuple.WildcardValue : tuple.Realm);
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
CredentialsId m;
|
|
|
|
if (_protocolMappings.TryGetValue(variation, out m)) {
|
|
|
|
assert m != null;
|
|
|
|
if (TraceSwitches.ShowWildcardMatching)
|
|
|
|
DebugLine(" Variation MATCHES: mask: {0:x1} {1} -> {2}", wildcard_mask, variation.ToString(), m);
|
|
|
|
if (match == null) {
|
|
|
|
if (TraceSwitches.ShowWildcardMatching)
|
|
|
|
DebugLine(" (using this match, showing future matches only for debugging)");
|
|
|
|
match = m;
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowWildcardMatching)
|
|
|
|
DebugLine(" Variation: no match, mask: {0:x1} {1}", wildcard_mask, variation.ToString());
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
if (match != null) {
|
|
|
|
if (TraceSwitches.ShowWildcardMatching)
|
|
|
|
DebugLine(" Final match: " + match);
|
|
|
|
return true;
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (TraceSwitches.ShowWildcardMatching)
|
|
|
|
DebugLine(" No matches.");
|
|
|
|
return false;
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
// The client wants to do a simple, exact match (no wildcards).
|
|
|
|
// This is easy.
|
|
|
|
if (TraceSwitches.ShowWildcardMatching)
|
|
|
|
DebugLine(" Query is an exact-match query (no wildcards)");
|
|
|
|
return _protocolMappings.TryGetValue(tuple, out match);
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
void DebugLine(string! format, params object[]! args)
|
|
|
|
{
|
|
|
|
DebugLine(String.Format(format, args));
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
void DebugLine(string! line)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
DebugStub.WriteLine(line);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
void ITracked.Acquire() {}
|
|
|
|
void ITracked.Release() {}
|
|
|
|
void ITracked.Expose() {}
|
|
|
|
void ITracked.UnExpose() {}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Represents an authentication protocol, but not an instance of such a protocol.
|
|
|
|
/// Derived classes override the CreateSupplicant method, which is used to create
|
|
|
|
/// instances of authentication protocols.
|
|
|
|
/// </summary>
|
|
|
|
abstract class AuthenticationProtocol
|
|
|
|
{
|
|
|
|
public abstract bool CreateSupplicant([Claims]ServiceContract.Exp! exp, Credentials! credentials, out CredError error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|