VMware

This Question is Answered

1 "helpful" answer available (6 pts)
16 Replies Last post: Nov 3, 2009 4:18 PM by CodeChief   1 2 Previous Next

C# Using Single SignOn (SSPI) for Virtual Center 2.5.0.119598 posted: Dec 15, 2008 7:39 AM

Click to view utarion's profile Novice 10 posts since
Dec 15, 2008
I am trying to use passthru authentication using SSPI to work in my c# application. Here is a snippet of the code I am trying to get to work.

returns a reference for VMware.Vim.SessionManager

VMware.Vim.VimClient vimClient = new VMware.Vim.VimClient();
vimClient.Connect("10.x.x.x", CommunicationProtocol.Https, 443);

ManagedObjectReference serviceInstance = new ManagedObjectReference();
serviceInstance.Type = "ServiceInstance";
serviceInstance.Value = "ServiceInstance";

SessionManager sm = new SessionManager(vimClient, serviceInstance);
sm.LoginBySSPI(ct_b64, null);

I get an exception when I try to call this method LoginBySSPI

I am not sure that this is the correct approach, but I really would like to be able to login using single signon in my c# code but not having much success.
This works fine using PowerShell but I want to be able to do this directly using c# without using PS Pipelines.

Any suggesstions welcome.

Thanks

Click to view Niket's profile Hot Shot 91 posts since
Jan 10, 2008
Hi,

You need to follow certain steps to use LoginBySSPI API. Below are the steps for that.
1) Create new Client Session
2) Get token
3) Call SessionManager.loginBySspi(token) (VI API)
4) While (Got a SSPIChallenge fault) {
clientSession.Initialize(fault.server Token)

It would be implemented as below code snippet.
Boolean flag = true;
ManagedObjectReference hostmor = _service.FindByIp(_sic.searchIndex, null,hostName,false);
while (flag)

try

_service.LoginBySSPI(_sic.sessionManager, Convert.ToBase64String(clientContext.Token), "en");
flag = false;

catch (Exception e)

SoapException se = (SoapException)e;
clientContext.Initialize(Convert.FromBase64String(se.Detail.InnerText));
try

Console.WriteLine("Time " + _service.CurrentTime(_svcRef));
flag = false;

catch (Exception ex)

flag = true;

You need to use Microsoft.Samples.Security.SSPI.dll to build a token to talk between cleint and server. I hope it helps you.

Thanks
Niket
Click to view ykalchev's profile Hot Shot 68 posts since
Mar 5, 2008
Hi,
In order to create instance of VMware.Vim view objects like SessionManager you need an instance of VimClient and a ManagedObjectReference to the object you are trying to create.
Because SessionManager MoRef is a property of the ServiceContent and vimClient.ServiceContent is populated on Connect() method you can just do:

VMware.Vim.VimClient vimClient = new VMware.Vim.VimClient();
vimClient.Connect("10.x.x.x", CommunicationProtocol.Https, 443);
SessionManager sm = new SessionManager(vimClient, vimClient.ServiceContent.SessionManager);


Regards,
Yasen
Click to view ykalchev's profile Hot Shot 68 posts since
Mar 5, 2008
Hi,
Getting this exception on the first run is normal. If you look at SDK documentation this exception means:Thrown during SSPI pass-through authentication if further negotiation is required.
As Niket wrote in his post you need to call again LoginBySSPI with the returned from the server token:

         SspiHelper ch = new SspiHelper();
         byte[] ct = null;
         byte[] st = null;
         bool cc = true;

         // Get the base64 token for the current Windows logon session.
         ch.InitializeClient(out ct, st, out cc);

         string ct_b64 = Convert.ToBase64String(ct);

         VMware.Vim.VimClient vimClient = new VMware.Vim.VimClient();
         vimClient.Connect("10.xx.xx.xx", CommunicationProtocol.Https, 443);
         SessionManager sm = new SessionManager(vimClient, vimClient.ServiceContent.SessionManager);

         bool serverNotReady = true;
         while (serverNotReady) {
            try {

               sm.LoginBySSPI(ct_b64, "en");
               serverNotReady = false;
            } catch (VMware.Vim.VimException ex) {
               if (ex.MethodFault is SSPIChallenge) {
                  ct_b64 = ((SSPIChallenge) ex.MethodFault).Base64Token;
               } else {
                  throw;
               }
            }
         }


Note that you can get the fault returned from the VI Server from the MethodFault property of the VimException

Regards,
Yasen
Click to view ykalchev's profile Hot Shot 68 posts since
Mar 5, 2008
Hi,
This exception is normal to be thrown if authentication fails. However I think I found the problem. The token retrieved from the server should be passes to the client to complete verification and then the result should be passed to the server again. Sorry for the mistake.
Here is the changed code:

         SspiHelper ch = new SspiHelper();
         byte[] ct = null;
         byte[] st = null;
         bool cc = true;

         VMware.Vim.VimClient vimClient = new VMware.Vim.VimClient();
         vimClient.Connect("10.xx.xx.xx", CommunicationProtocol.Https, 443);
         SessionManager sm = new SessionManager(vimClient, vimClient.ServiceContent.SessionManager);

         bool serverNotReady = true;
         while (cc || serverNotReady) {
            // Get the base64 token for the current Windows logon session.
            ch.InitializeClient(out ct, st, out cc);

            string ct_b64 = Convert.ToBase64String(ct);

            try {
               sm.LoginBySSPI(ct_b64, "en");
               serverNotReady = false;
            } catch (VMware.Vim.VimException ex) {
               if (ex.MethodFault is SSPIChallenge) {
                  st = Convert.FromBase64String(((SSPIChallenge) ex.MethodFault).Base64Token);
               } else {
                  throw;
               }
            }
         }

/Yasen

Click to view ykalchev's profile Hot Shot 68 posts since
Mar 5, 2008
Hi,
Did you get this error on the second call of InitializeClient method when you passed returned server token?
I got such error when I forgot to handle the VimException exception on the second server call. Make sure you break the loop if different from SSPIChallenge exception if caught.
catch ( VMware.Vim.VimException ex ){
   if (ex.MethodFault is SSPIChallenge) {
     ct_b64 = ((SSPIChallenge) ex.MethodFault).Base64Token;
   } else {
       MessageBox.Show(ex.Message);
       serverNotReady = false; // or just re throw the exception
   }
}


I suspect you got another "Login failed due to a bad username or password" exception :(

Regards,
Yasen
Click to view ykalchev's profile Hot Shot 68 posts since
Mar 5, 2008
The code looks OK.
I googled for the error code and it turns out that code 8009030C (-2146893044) is SEC_E_LOGON_DENIED, which means the username/password did not match.
Is the VC server and client machine in a domain?
I also noticed that you pass FR as locale parameter you can try with $null to use default VC locale.
These are just suggestions but you can try ...

/Yasen
Click to view Leafy's profile Novice 11 posts since
Jun 23, 2009

For the below snippet, what would be the equivalent code for the VSphere Web Services SDK??

<code>catch ( VMware.Vim.VimException ex ){
if (ex.MethodFault is SSPIChallenge) {
ct_b64 = ((SSPIChallenge) ex.MethodFault).Base64Token;
} else {
MessageBox.Show(ex.Message);
serverNotReady = false; // or just re throw the exception
}
}
</code>

<code> </code><code>Thanks!</code>

Developer Social Media

Communities