Authenticate with SSPI to vSphere using C# API - c#

I am using the C# library for connecting to vSphere (VimClient). I use this method to log in:
VimClient client = new VimClient();
client.Connect("https://vSphereMachine/sdk");
client.Login("userName", "password");
The user I'm logging in as is the current user used by the process. Is there a way I can use the current logged in user for authentication?
This thread seems to offer suggestions but nothing I tried there works: http://communities.vmware.com/message/1125103
That may be because I'm not familiar with the SSPI implementation in .NET.

As VMWare.Vim.dll just wraps the generated WCF Service client, I was ble to adapt this sample project to using the dll directly. This is my adaptation of his LoginBySspiPackage method.
private UserSession LoginBySspiPackage(SspiPackageType sspiPackage, string serviceSpn)
{
Log($"Logging in to VSphere instance {VimClient.ServiceUrl} using SSPI.");
var sspiClient = new SspiClient(serviceSpn, sspiPackage);
var sessionManager = new SessionManager(VimClient, VimClient.ServiceContent.SessionManager);
var serverNotReady = true;
UserSession session = null;
while (serverNotReady)
{
try
{
var base64String = Convert.ToBase64String(sspiClient.Token);
session = sessionManager.LoginBySSPI(base64String, "en");
serverNotReady = false; // Connected!
}
catch (VMware.Vim.VimException e)
{
if (e.MethodFault is SSPIChallenge)
{
var sspiChallenge = e.MethodFault as SSPIChallenge;
var base64String = Convert.FromBase64String(sspiChallenge.Base64Token);
sspiClient.Initialize(base64String);
}
else if (e.MethodFault is InvalidLogin)
{
throw new InvalidLoginException(e.Message);
}
else
{
throw;
}
}
}
return session;
}

Related

SharpSVN doesn't want to use credentials

I am trying to make SharpSVN log in to a repository with stored credentials, but according to access logs it never actually offers any. I have the following bit in my code:
internal static SvnClient SvnClient
{
get
{
if (_svnClient != null) return _svnClient;
_svnClient = new SvnClient();
_svnClient.Authentication.AddConsoleHandlers();
var user = Environment.GetEnvironmentVariable("svnuser");
var pass = Environment.GetEnvironmentVariable("svnpass");
if (user != null && pass != null)
{
_svnClient.Authentication.ForceCredentials(user, pass);
}
_svnClient.Authentication.SslServerTrustHandlers += (
(sender, e) =>
{
e.AcceptedFailures = SvnCertificateTrustFailures.UnknownCertificateAuthority;
e.Save = true;
});
return _svnClient;
}
}
private static SvnClient _svnClient;
What I find the most confusing is that this setup used to work. I know the correct credentials are being picked up, that they work with the repository, that the machine can see the repository, but investigating the access logs I just see the client trying once with no creds, getting a 401, and dying with an exception No more credentials or we tried too many times. What could be going wrong/how to get it to work?

Ho to take server offline / bring server online IIS web farm server programmatically

I am developing a C# application to automate process of deploying website to the server.The website is hosted in a web farm in WINDOWS SERVER 2012 R2. So the problem here is I am trying to take server offline or bring it online by means of some programming interface. but I couldn't find anything related inside Microsoft docs. How do I get the job done?
UPDATE:
As suggested by Timur I did as following, but it didn't work.
ServiceController p = new ServiceController("W3SVC","SERVER_IP");
p.Start();
p.WaitForStatus(ServiceControllerStatus.Running);
This is the sample that generated by configuration manager. It take server offline/online by change the Enabled property of server item in web farm collection.
using System;
using System.Text;
using Microsoft.Web.Administration;
internal static class Sample
{
private static void Main()
{
using (ServerManager serverManager = new ServerManager())
{
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection webFarmsSection = config.GetSection("webFarms");
ConfigurationElementCollection webFarmsCollection = webFarmsSection.GetCollection();
ConfigurationElement webFarmElement = FindElement(webFarmsCollection, "webFarm", "name", #"123213");
if (webFarmElement == null) throw new InvalidOperationException("Element not found!");
ConfigurationElementCollection webFarmCollection = webFarmElement.GetCollection();
ConfigurationElement serverElement = FindElement(webFarmCollection, "server", "address", #"11.1.1.1");
if (serverElement == null) throw new InvalidOperationException("Element not found!");
serverElement["enabled"] = false;
serverManager.CommitChanges();
}
}
private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues)
{
foreach (ConfigurationElement element in collection)
{
if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase))
{
bool matches = true;
for (int i = 0; i < keyValues.Length; i += 2)
{
object o = element.GetAttributeValue(keyValues[i]);
string value = null;
if (o != null)
{
value = o.ToString();
}
if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase))
{
matches = false;
break;
}
}
if (matches)
{
return element;
}
}
}
return null;
}
}
IIS is a Windows service. Therefore the easiest way to start/stop it will be to do something along the lines of this SO answer.
You'll be looking for service name, which likely depends on your version.
UPD see an artist's impression on how your management tool might look like
var hostNames = new List<string> { "appServer1", "webServer1", "webServer2" };
foreach (var host in hostNames)
{
var svc = new ServiceController("W3SVC", host);
svc.Stop();
svc.WaitForStatus(ServiceControllerStatus.Stopped);
Thread.Sleep(10000);// or your custom logic
svc.Start();
svc.WaitForStatus(ServiceControllerStatus.Running);
}
bear in mind, you'll need to run this as a user with sufficient privileges to successfully change service state: as in you need to run this as Admin.
You've got at least two options to do it:
Run your IDE as admin
Update your application manifest as described in this answer
UPD2 apparently you can interface with WFF controller like so

Exchange Web Service API really slow but only if called from WPF application

I am trying to build a WPF application that queries our Exchange 2010 SP2 using the Exchange Web Services API.
However, I'm finding that if I use the Exchange API from a WPF application, the calls to the API are really, really slow. In fact they are two orders of magnitude slower than running the exact same code from a command-line application (some calls to the API takes 15 seconds when done from a WPF app and only 0.15 seconds when done from a command-line app).
I'm using Visual Studio 2015 with Exchange Web Services Managed API 2.2.
This is the code for WPF. In particular, what runs extremely slow is the call to folder.FindFolders in GetPathFolder:
using System;
using System.Windows;
using Microsoft.Exchange.WebServices.Data;
namespace esw_testwpf
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.UseDefaultCredentials = true;
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.AutodiscoverUrl("myemail#company.com", RedirectionUrlValidationCallback);
Folder baseFolder = FindFolderIdByPath(service, #"\Path\To\A\Known\PublicFolder", WellKnownFolderName.PublicFoldersRoot);
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
public static Folder FindFolderIdByPath(ExchangeService service, string path, WellKnownFolderName root)
{
// Specify the root folder to be searched.
Folder rootFolder = Folder.Bind(service, root);
return GetPathFolder(rootFolder.FindFolders(new FolderView(100)), path, "");
}
public static Folder GetPathFolder(FindFoldersResults results, string lookupPath, string currentPath)
{
foreach (Folder folder in results)
{
string path = currentPath + #"\" + folder.DisplayName;
if (lookupPath.Equals(path))
{
return folder;
}
if (lookupPath.StartsWith(path))
{
return GetPathFolder(folder.FindFolders(new FolderView(100)), lookupPath, path);
}
else
{
continue;
}
}
return null;
}
}
}
And this exactly the same code for command-line, which consistently runs very fast.
using System;
using Microsoft.Exchange.WebServices.Data;
namespace ewstestcmd
{
class Program
{
static void Main(string[] args)
{
var service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.UseDefaultCredentials = true;
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.AutodiscoverUrl("myemail#company.com", RedirectionUrlValidationCallback);
Folder baseFolder = FindFolderIdByPath(service, #"\Path\To\A\Known\PublicFolder", WellKnownFolderName.PublicFoldersRoot);
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
public static Folder FindFolderIdByPath(ExchangeService service, string path, WellKnownFolderName root)
{
// Specify the root folder to be searched.
Folder rootFolder = Folder.Bind(service, root);
return GetPathFolder(rootFolder.FindFolders(new FolderView(100)), path, "");
}
public static Folder GetPathFolder(FindFoldersResults results, string lookupPath, string currentPath)
{
foreach (Folder folder in results)
{
string path = currentPath + #"\" + folder.DisplayName;
if (lookupPath.Equals(path))
{
return folder;
}
if (lookupPath.StartsWith(path))
{
return GetPathFolder(folder.FindFolders(new FolderView(100)), lookupPath, path);
}
else
{
continue;
}
}
return null;
}
}
}
Why do I get such a different behavior in Exchange API response time if the code is essentially the same?
I first thought it was some kind of server-side throttling, but it does not make sense to me that the WPF variant is always very slow and the command-line variant is always very fast.
When I changed:
service.TraceEnabled = true;
to
service.TraceEnabled = false;
all extra delay in WPF disappeared. So it seems that, for some reason, enabling tracing for EWS in a WPF takes a huge performance hit.

Hybrid Mobile Application (C# & Bootstrap)

I developed a Hybrid Mobile Application using C# and Bootstrap, I published it on Google Play and it is working fine, but when the user tries to open the application when there is no internet connection, a message appears "Webpage not available" The webpage at HTTP://... might be temporarily down or ...
The question is: how to avoid this message or how to customize it with my message or my web form?
Try this Code. First Check internet connection using WebClient & then return custom page if connection is not available.
public void MyMethod()
{
if (CheckInternetConnection() == false)
{
Response.Redirect("custompage.aspx");
}
else
{
//your application method
}
}
public bool CheckInternetConnection()
{
try
{
using (var obj = new WebClient())
{
using (var stream = obj.OpenRead("http://www.google.co.in"))
{
return true;
}
}
}
catch
{
return false;
}
}

Dynamics CRM code popping up dialog in service

Given the following connection code:
var serviceUri = "http://machine.co.za/CRM/XRMServices/2011/Organization.svc";
var clientCredentials = new ClientCredentials
{
Windows =
{
ClientCredential = new System.Net.NetworkCredential("SOMEUSER", "SOMEPASS", "DOMAIN")
}
};
var organizationServiceProxy = new OrganizationServiceProxy(new Uri(serviceUri), null, clientCredentials, null);
// This line of code pops up a dialog?
var user = (WhoAmIResponse)organizationServiceProxy.Execute(new WhoAmIRequest());
if (user.UserId == Guid.Empty)
throw new InvalidOperationException(string.Format(#"connection to {0} cannot be established.", crmConnection.ServiceUri));
user.Dump();
If the supplied password is incorrect, the code pops up a credentials dialog.
Since the service does not have rights to interact with the desktop, the service halts as it cannot actually show a dialog.
How do I suppress the dialog, and have an exception get thrown instead. I am using dynamics 2011.
I am going to take it as a given that the CRM dynamics OrganizationServiceProxy is hardwired to pop up a dialog.
There are no configuration options or flags that turn this behavior off.
You may be mixing up usage of CrmConnection. It boils down to:
var conn = new ConnectionStringSettings("CRM", "Url=http://machine.co.za/CRM; Username=SOMEUSER; Password=SOMEPASS; Domain=SOMEDOMAIN")
var crmConnection = new CrmConnection(conn);
var crmService = new OrganizationService(crmConnection);
try
{
// connection will actually happen here. anything goes wrong, exceptions will be thrown
var user = crmService.Execute<WhoAmIResponse>(new WhoAmIRequest());
user.Dump();
}
catch (Exception ex)
{
// just a proof of concept
// ex is of type MessageSecurityException if credentials are invalid
throw new InvalidOperationException(string.Format(#"connection to {0} cannot be established.", crmConnection.ServiceUri), ex);
}

Categories

Resources