//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // Note: Command-line tool for controlling the Credentials Manager Service. // using System; using System.Collections; using System.Diagnostics; using Microsoft.Contracts; using Microsoft.Singularity; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; using Microsoft.Singularity.Applications; using Microsoft.Singularity.Io; using Microsoft.Singularity.Configuration; using Microsoft.SingSharp; using Microsoft.SingSharp.Reflection; using Microsoft.Singularity.Security; [assembly: Transform(typeof(ApplicationResourceTransform))] namespace Microsoft.Singularity.Applications { [ConsoleCategory(DefaultAction=true)] internal class DefaultCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal DefaultCommand(); internal int AppMain() { Console.WriteLine("Use -? for a list of commands."); return 0; } } [ConsoleCategory(Action="add", HelpMessage="Adds credentials (user id and password) to the credentials store.")] internal class AddCredentialsCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal AddCredentialsCommand(); [BoolParameter("replace", Mandatory=false, HelpMessage="If specified, will replace existing credentials with the same name.", Default=true)] public bool ReplaceExistingCredentials; [StringParameter("username", Mandatory=true, Position=0, HelpMessage="The [domain\\]username of the credentials.")] public string UserName; [StringParameter("password", Mandatory=true, Position=1, HelpMessage="The password for this account.")] public string Password; [StringParameter("tag", Mandatory=false, HelpMessage="A tag that can be used to distinguish different instances of the same account name.")] public string Tag; [BoolParameter("default", Mandatory=false, HelpMessage="If specified, then the credentials will be registered as the default credentials.", Default=true)] public bool AddDefaultProtocolMapping; internal int AppMain() { try { assert this.UserName != null; assert this.Password != null; if (this.Tag == null) this.Tag = ""; CredentialsManager.AddCredentials(this.UserName, this.Tag, this.Password, this.ReplaceExistingCredentials); Console.WriteLine("Credentials successfully added to credentials store."); const string Wildcard = "*"; if (this.AddDefaultProtocolMapping) { CredentialsManager.AddProtocolMapping( Wildcard, Wildcard, Wildcard, Wildcard, this.UserName, this.Tag, true); Console.WriteLine("Default protocol mapping added."); } return 0; } catch (Exception! ex) { Util.ShowException(ex); return -1; } } } [ConsoleCategory(Action="del", HelpMessage="Deletes credentials from the credentials store.")] internal class DeleteCredentialsCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal DeleteCredentialsCommand(); [StringParameter("username", Mandatory=true, Position=0, HelpMessage="The [domain\\]username of the credentials.")] public string UserName; [StringParameter("tag", Mandatory=false, HelpMessage="A tag that can be used to distinguish different instances of the same account name.")] public string Tag; internal int AppMain() { try { assert this.UserName != null; if (this.Tag == null) this.Tag = ""; CredentialsManager.DeleteCredentials(this.UserName, this.Tag); Console.WriteLine("Credentials deleted."); return 0; } catch (Exception ex) { Util.ShowException(ex); return -1; } } } [ConsoleCategory(Action="delall", HelpMessage="Deletes all credentials from the credentials store.")] internal class DeleteAllCredentialsCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal DeleteAllCredentialsCommand(); internal int AppMain() { try { CredentialsManager.DeleteAllCredentials(); Console.WriteLine("All credentials deleted."); return 0; } catch (Exception ex) { Util.ShowException(ex); return -1; } } } [ConsoleCategory(Action="list", HelpMessage="Shows a list of the credentials in the credentials store.")] internal class ListCredentialsCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal ListCredentialsCommand(); internal int AppMain() { try { CredentialsManagerContract.Imp! manager = CredentialsManager.ConnectService(); try { manager.SendEnumerateCredentials(); switch receive { case manager.CredentialsList(list): if (list.Length == 0) { Console.WriteLine("No entries in credentials store."); } else { const string format = "{0,-20} {1,-20}"; Console.WriteLine(format, "User name", "Tag"); Console.WriteLine(format, "=========", "==="); for (int i = 0; i < list.Length; i++) { expose(list[i]) { string! username = Bitter.ToString2(list[i].CredentialsName); string! tag = Bitter.ToString2(list[i].Tag); Console.WriteLine(format, username, tag); } } } delete list; return 0; case manager.RequestFailed(error): Util.ShowCredError(error); return 1; } } finally { delete manager; } } catch (Exception ex) { Util.ShowException(ex); return -1; } } } [ConsoleCategory(Action="addmap", HelpMessage="Add a mapping from a protocol tuple to credentials.")] internal class AddProtocolMappingCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal AddProtocolMappingCommand(); [StringParameter("app", HelpMessage="The application protocol, such as 'smb' or 'http'.", Mandatory=true, Position=0)] string ApplicationProtocol; [StringParameter("service", HelpMessage="The remote service name, such as 'fooserver.example.com' or '192.168.0.1',", Mandatory=false, Position=1)] string ServiceAddress; [StringParameter("authp", HelpMessage="The authentication protocol, such as 'ntlm'.", Mandatory=true, Position=2)] string AuthenticationProtocol; [StringParameter("realm", HelpMessage="The authentication realm, such as 'yourdomain'.", Mandatory=true, Position=3)] string Realm; [StringParameter("username", HelpMessage="The username (credentials name) to map to.", Mandatory=true, Position=4)] string CredentialsName; [StringParameter("tag", HelpMessage="The credentials tag, which can be used to disambiguate between credentials with the same name.", Mandatory=false, Position=5, Default="")] string Tag; [BoolParameter("replace", HelpMessage="If specified, then any existing entry will be replaced.", Default=true)] bool ReplaceExistingEntry; internal int AppMain() { try { CredentialsManager.AddProtocolMapping( Util.NullToEmpty(this.ApplicationProtocol), Util.NullToEmpty(this.ServiceAddress), Util.NullToEmpty(this.AuthenticationProtocol), Util.NullToEmpty(this.Realm), Util.NullToEmpty(this.CredentialsName), Util.NullToEmpty(this.Tag), this.ReplaceExistingEntry); Console.WriteLine("The protocol mapping has been added."); return 0; } catch (Exception ex) { Util.ShowException(ex); return -1; } } } [ConsoleCategory(Action="delmap", HelpMessage="Delete a mapping from a protocol tuple to credentials.")] internal class DeleteProtocolMappingCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal DeleteProtocolMappingCommand(); [StringParameter("app", HelpMessage="The application protocol, such as 'smb' or 'http'.", Mandatory=true, Position=0)] string ApplicationProtocol; [StringParameter("service", HelpMessage="The remote service name, such as 'fooserver.example.com' or '192.168.0.1',", Mandatory=false, Position=1)] string ServiceAddress; [StringParameter("authp", HelpMessage="The authentication protocol, such as 'ntlm'.", Mandatory=true, Position=2)] string AuthenticationProtocol; [StringParameter("realm", HelpMessage="The authentication realm, such as 'yourdomain'.", Mandatory=true, Position=3)] string Realm; internal int AppMain() { try { CredentialsManager.DeleteProtocolMapping( Util.NullToEmpty(this.ApplicationProtocol), Util.NullToEmpty(this.ServiceAddress), Util.NullToEmpty(this.AuthenticationProtocol), Util.NullToEmpty(this.Realm)); Console.WriteLine("The protocol mapping has been deleted."); return 0; } catch (Exception ex) { Util.ShowException(ex); return -1; } } } [ConsoleCategory(Action="delmapall", HelpMessage="Delete all protocol mappings.")] internal class DeleteAllProtocolMappingsCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal DeleteAllProtocolMappingsCommand(); internal int AppMain() { try { CredentialsManager.DeleteAllProtocolMappings(); Console.WriteLine("All protocol mappings have been deleted."); return 0; } catch (Exception ex) { Util.ShowException(ex); return -1; } } } [ConsoleCategory(Action="listmap", HelpMessage="Shows a list of all protocol mappings.")] internal class ListProtocolMappingsCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; reflective internal ListProtocolMappingsCommand(); internal int AppMain() { try { CredentialsManagerContract.Imp! manager = CredentialsManager.ConnectService(); try { manager.SendEnumerateProtocolMappings(); switch receive { case manager.ProtocolMappings(list): Console.WriteLine("Protocol mappings:"); const string format = "{0,-10} {1,-10} {2,-10} {3,-10} {4,-10} {5,-10}"; Console.WriteLine(format, "App Prot.", "Service", "Auth Prot.", "Realm", "Credentials", "Tag"); Console.WriteLine(format, "=========", "=======", "==========", "=====", "===========", "==="); for (int i = 0; i < list.Length; i++) { string! applicationProtocol; string! serviceName; string! authenticationProtocol; string! realm; string! credentialsName; string! tag; expose(list[i]) { // expose(list[i].ProtocolTuple) { applicationProtocol = Bitter.ToString2(list[i].ProtocolTuple.ApplicationProtocol); serviceName = Bitter.ToString2(list[i].ProtocolTuple.ServiceAddress); authenticationProtocol = Bitter.ToString2(list[i].ProtocolTuple.AuthenticationProtocol); realm = Bitter.ToString2(list[i].ProtocolTuple.Realm); // } // expose(list[i].CredentialsId) { credentialsName = Bitter.ToString2(list[i].CredentialsId.CredentialsName); tag = Bitter.ToString2(list[i].CredentialsId.Tag); // } } Console.WriteLine(format, applicationProtocol, serviceName, authenticationProtocol, realm, credentialsName, tag); } delete list; return 0; case manager.RequestFailed(error): Util.ShowCredError(error); return 1; } } finally { delete manager; } } catch (Exception ex) { Util.ShowException(ex); return -1; } } } [ConsoleCategory(Action="testmap", HelpMessage="Test a protocol mapping. Specify a protocol tuple, and the command will show you which credentials would be selected.")] internal class TestProtocolMappingCommand { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; [StringParameter("app", HelpMessage="The application protocol, such as 'smb' or 'http'.", Mandatory=true, Position=0)] string ApplicationProtocol; [StringParameter("service", HelpMessage="The remote service name, such as 'fooserver.example.com' or '192.168.0.1',", Mandatory=true, Position=1)] string ServiceAddress; [StringParameter("authp", HelpMessage="The authentication protocol, such as 'ntlm'.", Mandatory=true, Position=2)] string AuthenticationProtocol; [StringParameter("realm", HelpMessage="The authentication realm, such as 'yourdomain'.", Mandatory=true, Position=3)] string Realm; reflective internal TestProtocolMappingCommand(); internal int AppMain() { try { string! credentialsName; string! tag; Console.WriteLine("Checking:"); Console.WriteLine(" Application Protocol = " + this.ApplicationProtocol); Console.WriteLine(" Service Address = " + this.ServiceAddress); Console.WriteLine(" Authentication Protocol = " + this.AuthenticationProtocol); Console.WriteLine(" Authentication Realm = " + this.Realm); Console.WriteLine(""); if (CredentialsManager.FindMatchingProtocolMapping( Util.NullToEmpty(this.ApplicationProtocol), Util.NullToEmpty(this.ServiceAddress), Util.NullToEmpty(this.AuthenticationProtocol), Util.NullToEmpty(this.Realm), true, out credentialsName, out tag)) { Console.WriteLine("Credentials selected: {0} {1}", credentialsName, tag); return 0; } else { Console.WriteLine("No mappings found that match the specified protocol tuple."); return 1; } } catch (Exception ex) { Util.ShowException(ex); return -1; } } } class Util { public static void ShowException(Exception! chain) { for (Exception ex = chain; ex != null; ex = ex.InnerException) { Console.WriteLine(ex.GetType().FullName + ": " + ex.Message); } } public static void ShowCredError(CredError error) { Console.WriteLine("Error: " + CredentialsManager.CredErrorToString(error)); } public static string! NullToEmpty(string s) { if (s == null) return ""; else return s; } } }