Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A call to SSPI failed #32

Open
zharris6 opened this issue Oct 26, 2016 · 24 comments
Open

A call to SSPI failed #32

zharris6 opened this issue Oct 26, 2016 · 24 comments

Comments

@zharris6
Copy link

Hello -

I am experiencing an issue when trying to connect to a client via the FtpProtocol.FtpES protocol.

I believe it has something to do with the SSL certificate signing.

Can you point me in the right direction to try and fix this?

I will be happy to commit my fix, once its completed.

Exception Message:

A call to SSPI failed, see inner exception.

Here is the stack trace:

at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation) at ArxOne.Ftp.FtpSession.UpgradeToSsl(Stream stream) at ArxOne.Ftp.FtpSession.EnterSslProtocol() at ArxOne.Ftp.FtpSession.InitializeProtocol() at ArxOne.Ftp.FtpSession.ProcessConnect(TimeSpan connectTimeout, TimeSpan readWriteTimeout) at ArxOne.Ftp.FtpSession.<>c__DisplayClass15_0.b__0() at ArxOne.Ftp.FtpSession.Process[TResult](Func1 func, String commandDescription, String requestCommand, String[] requestParameters) at ArxOne.Ftp.FtpSession.Connect(TimeSpan connectTimeout, TimeSpan readWriteTimeout) at ArxOne.Ftp.FtpSession.get_ProtocolStream() at ArxOne.Ftp.FtpClient.<>c__DisplayClass123_0.b__0(FtpSession session) at ArxOne.Ftp.FtpClient.Process[TResult](Func2 action, FtpSession session) at ArxOne.Ftp.FtpClient.SendSingleCommand(String command, String[] parameters).

@picrap
Copy link
Member

picrap commented Oct 26, 2016

Hi,

I had a lot of problems like this one, and for some unknown reason. I think it has something to do with the SSL protocol chosen, so the only way to fix this was to provide a property named SslProtocols in the FtpClientParameters class.
Maybe (I'm thinking of it just right now) it could help to try some other protocols when the tested one fails, so catching the exception in UpgradeToSsl() method and then retry with different options.
I'm not sure this helps, but this is my best.

@picrap picrap added the bug label Oct 26, 2016
@zharris6
Copy link
Author

Implicit SSL will not even authenticate and the server is setup to require SSL: so no SSL is not an option.

Explicit SSL is the only option that will work, for this particular server.

I will try to play around with it and let you know how it goes :)

Thanks for the quick response.

@picrap
Copy link
Member

picrap commented Oct 26, 2016

No it's not about explicit or implicit, it's about SslProtocols that you can force to have the values you need:

namespace System.Security.Authentication
{
  [Flags]
  public enum SslProtocols
  {
    None,
    Ssl2,
    Ssl3,
    Tls,
    Tls11,
    Tls12,
    Default = Tls | Ssl3,
  }
}

And you can set specific values in the FtpClientParameters class in order to use only the specified SSL protocols.

@zharris6
Copy link
Author

Sorry I should of been more specific. I have tried all of them with no luck. I either receive a connection error (due to target server limitations) or the SSPI error.

@picrap
Copy link
Member

picrap commented Oct 26, 2016

I'm sorry to read that, I think there is something I misunderstood in FTPES protocol, because I had the same error on some servers (and had to disable tests for them).

@zharris6
Copy link
Author

I am almost positive it has to do with the way you are handling certificates. Right now the CheckCertificateHandler isn't doing anything. and your passing in a null certificate to the AuthenticateAsClient method.

That is what is causing the SSPI errors we are seeing.

I am going to try and generate a cert and apply it with this method and see if it fixes it.

If it does, ill clean it up and get it committed.

@picrap picrap mentioned this issue Oct 27, 2016
@picrap
Copy link
Member

picrap commented Nov 1, 2016

Any progress on this?

@zharris6
Copy link
Author

zharris6 commented Nov 2, 2016

Nope - I Tried tons of things, including add a cert to the request and no luck.

@zharris6
Copy link
Author

zharris6 commented Nov 8, 2016

I fixed the SSPI call error, but now i am getting this exception "The handshake failed due to an unexpected packet format"

A wireshark says the server responded with:

421 Failed TLS negotiation on control channel, disconnected (SSL_accept():(1) error: 14076 OFC: SSL Routines: SSL23_Get_Client_Hello: unknown protocol)"

@picrap
Copy link
Member

picrap commented Nov 8, 2016

I guess that's a progress... How can I help?

@picrap
Copy link
Member

picrap commented Nov 10, 2016

Hi Zach,
What FTP server do you use?

@picrap
Copy link
Member

picrap commented Nov 11, 2016

This may be a great product, however I couldn't even getting it started (because the setup is a great piece of garbage, and yes, I'm pissed). So I won't be able to help.

@zharris6
Copy link
Author

I understand, any Unix based ftpd should be fine.

I will let you know when I get back home and can look at it

On Fri, Nov 11, 2016, 12:32 PM Pascal Craponne [email protected]
wrote:

This may be a great product, however I couldn't even getting it started
(because the setup is a great piece of garbage, and yes, I'm pissed). So I
won't be able to help.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
#32 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AGS2cVo5TIFHkBKWX0QcNXAMsURqVGN_ks5q9KKBgaJpZM4KhRpI
.

@picrap
Copy link
Member

picrap commented Dec 14, 2016

Version 1.11 (just released) uses lazy initialization on FtpStream, this means they can be used only if their Validated() method was invoked. Does this fix the problem (because it may be related)?

@ebarnard
Copy link

ebarnard commented Dec 15, 2016

I think this is caused by another issue I just encountered.

If you set ChannelProtection to contain FtpProtection.DataChannel the library never explicitly informs the server of this.

Some servers do not by default use SSL on the data channel even if it is being used on the command channel.

This can result in the server sending unencrypted data which is picked up by System.Net.Security.SslStream.AuthenticateAsClient and causes the exception seen above as the data is not a valid SSL handshake.

FtpSession.CheckProtection should, if State["PROT"] does not equal the desired protection level, issue a PROT command and fail on a non 2xx response code. State["PROT"] should not initially be set on a new connection.

I'm currently using the below as a temporary fix:

if (client.SendSingleCommand("PROT", "P").Code.Code != 200)
    throw new Exception("Could not enable data channel encryption.");

@ebarnard
Copy link

It appears the library also doesn't issue a PBSZ command which is apparently required by https://tools.ietf.org/html/rfc2228.

Other libraries seem to use PBSZ 0 successfully.

@zharris6
Copy link
Author

ebarnard - You are correct. Also, I ended up bypassing SSPI all together and using a OpenSSL C# implementation.

Even with your suggestions, I could not successfully handshake with a UNIX based ftpd.

Here is the package i used to successfully

https://github.com/openssl-net/openssl-net

@zharris6
Copy link
Author

Something also to add - I updated libssl32.dll and ssleay32.dll from that package with the new versions provided by OpenSSL. I believe the versions included in that package are open to the HeartBleed vulnerability.

@ebarnard
Copy link

Looks like mine is an unrelated issue then.

@zharris6
Copy link
Author

Ebernard - What exactly is your issue? your getting the SSPI exception?

Is your initial handshake successful? Do you see the USER command being sent?

Any logs you can provide would be helpful.

@ebarnard
Copy link

The issue is that a PROT command is not being sent when using ftps or ftpes. As a result the server sends unencrypted data on the data channel despite the control channel running over ssl.

As it's unrelated to this issue I opened #35.

@picrap
Copy link
Member

picrap commented Dec 16, 2016

Ahem... Let's get back to original problem here 😣
@zharris6 : is it fixed? Can we close this issue?

@zharris6
Copy link
Author

Nope, I only got it working by bypassing SSPI/SSLStream all together and using the OpenSSL fork i mentioned previously. It is a complete hack and a total butcher of your code, therefor it is not a acceptable solution.

I will try to fix this using SSPI, however, I think it is a problem with SSPI itself.

@picrap
Copy link
Member

picrap commented Dec 18, 2016

OK, let's keep this issue open, then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants