February 5, 2010

SSH / SFTP - Too much time between connect and authentication

Filed under: SFTP, SSH, error messages — Tags: , , , , — admin @ 6:28 am

The Solution:

Issue solved.   The problem was, that we stepped through the code and because of that too much time elapsed between connect and authentication.  As we ran the program without breakpoints it worked.

The Problem:

The AuthenticatePw method failed and the LastErrorText contained this information:

ChilkatLog:
   AuthenticatePw:
     DllDate: Jan 31 2010
     UnlockPrefix: ***
     Username: ***
     Component: .NET 2.0
     SshVersion: SSH-2.0-XFB.Gateway Windows
     SftpVersion: 0
     login: ***
     sendMessage:
       msgName: SERVICE_REQUEST
       unpaddedLength: 22
       remainder: 6
       paddingLen: 10
       totalSize: 32
     SentServiceReq: ssh-userauth
     numBytesRequested: 16
     Connection closed by server.
     Failed to read data on SSH connection.
     Failed to read packet from SSH server.
     Error reading service accept.
     Socket connection lost.
     Failed.

February 3, 2010

Getting the Root CA Certificate SHA1 Thumbprint

Filed under: certificate — Tags: , , — admin @ 3:00 pm

Question:

(In VB6) One thing we would like to do is to read out the SHA1
fingerprint of the root ca. For example, the programm should read the user
certificate. The user certificate has a certification path. Is it possible
to read out the fingerprint of the top-level root certificate?

Answer:

Here is a sample program. The user certificate is loaded from the current-user registry-based certificate store by common name. Once you have the cert object, you can build the chain of authority and step through it. The root cert is the last in the list.

    Dim cert As New ChilkatCert

    success = cert.LoadByCommonName("Chilkat Software, Inc.")

    Dim certChain As New ChilkatCertChain

    ' Leave the certCollection object empty..
    Dim certCollection As New ChilkatCertColl

    success = certChain.BuildChain(cert, certCollection)

    NumCerts = certChain.NumCerts
    Dim certN As ChilkatCert
    For i = 0 To NumCerts - 1
        Set certN = certChain.GetCert(i)
        MsgBox certN.SubjectDN
    Next

    ' The certificate at index NumCerts - 1 is the root.
    ' get the fingerprint:
    MsgBox "Root Thumbprint: " & certChain.GetCert(NumCerts - 1).Sha1Thumbprint

January 22, 2010

REGSVR32 0×80070005 Error on x64 Windows 7

Filed under: ActiveX, regsvr32 — Tags: — admin @ 3:13 pm

The download for the Chilkat x64 ActiveX components includes a register.bat batch file for registering each of the Chilkat ActiveX DLLs.  If some or all of these fail with an error code of 0×80070005, it is because of a permissions problem.  Do the following to successfully register the ActiveX DLL’s on the system:

  1. Copy the DLL’s to c:\Windows\System32
  2. Right-click on the “register.bat” file and select “Run as administrator”.
  3. The DLL’s should register.

December 15, 2009

SSL/TLS Error - SEC_E_INTERNAL_ERROR

Filed under: SSL, TLS — Tags: , , — admin @ 2:13 pm

Problem:
An SSL/TLS connection failed and the LastErrorText contains “SEC_E_INTERNAL_ERROR”, such as in the error text below:

(See cause solution below)

ChilkatLog:
  Connect:
    DllDate: Dec  4 2009
    UnlockPrefix: ****
    Username: ****
    Component: .NET 2.0
    objectId: 1
    hostname: *.*.*.*
    port: 443
    ssl: 1
    maxWaitMs: 20000
    windowsAccount: ****
    ClientCertDN: ****
    protocol: default
    An existing connection was forcibly closed by the remote host.
    Failed to receive on the TCP socket
    connectionClosed: 0
    timedOut: 0
    Error reading data from server in handshake loop
    Setting scRet = SEC_E_INTERNAL_ERROR
    Error performing handshake
    Failed.

Cause #1:
This is caused when the server-side expect an SSL 3.0 initial packet and cannot handle an SSL 2.0 initial packet. Normally, when a client and server connect and begin the SSL/TLS handshake, the SSL 2.0 packet is the first one sent. It allows the client and server to negotiate and agree upon protocols starting from SSL 2.0 and up (SSL 2.0, SSL 3.0, TLS 1.0, etc.) Normally, the most secure protocol is used and SSL 2.0 is never actually used (unless there is some very very old legacy server that only supports SSL 2.0).

In some cases, the server does not expect the 1st packet to be SSL 2.0 formatted. One such case is the following OpenSSL command:

OpenSSL> s_server -accept 443 -Verify 5 -ssl3 -cert c:\certs\server.pem


Solution #1:

Set the SslProtocol property equal to the string “SSL 3.0″. For example:

socket.SslProtocol = "SSL 3.0";

This applies to all components capable of using SSL/TLS connections: FTP2, HTTP, Socket, IMAP, MailMan, etc.

Cause #2
The server requires the client to provide a certificate for authentication, but none was provided.

Solution #2
Load a Chilkat certificate object with the appropriate client-side certificate (there are many ways of doing this..) and then set the clients-side certificate by calling the SetSslClientCert method. This method exists on all Chilkat objects that use SSL/TLS connections (FTP2, HTTP, Socket, IMAP, MailMan, etc.)

Important: It’s entirely possible that your application might need to apply both solutions.

December 14, 2009

Very simple C# SSH Shell Console Terminal

Filed under: SSH — Tags: , , , , — admin @ 2:48 pm

Here’s an example that demonstrates a rough start to creating a C# console SSH shell terminal (where the user can type commands and output from the remote command echos to the console:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace SshTerminalConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Chilkat.Ssh ssh = new Chilkat.Ssh();
            ssh.UnlockComponent(”Test”);

            //  Hostname may be an IP address or hostname:
            string hostname = “192.168.1.117″;
            int port = 22;

            Console.WriteLine(”Connecting…”);

            //ssh.KeepSessionLog = true;
            bool success = ssh.Connect(hostname, port);
            if (success != true)
            {
                Console.WriteLine(ssh.LastErrorText + “\r\n”);
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            //  When reading, if no additional data arrives for more than
            //  5 seconds, then abort:
            ssh.IdleTimeoutMs = 5000;

            Console.WriteLine(”Authenticating…”);

            //  SSH Server Authentication
            //  If there is no login/password required, you must still call
            //  AuthenticatePw and use any values for login/password.
            success = ssh.AuthenticatePw(”chilkat”, “***”);
            if (success != true)
            {
                Console.WriteLine(ssh.LastErrorText + “\r\n”);
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            Console.WriteLine(”Opening Channel…”);

            //  Open a session channel.
            int channelNum = ssh.OpenSessionChannel();
            if (channelNum < 0)
            {
                Console.WriteLine(ssh.LastErrorText + “\r\n”);
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            //  Request a pseudo-terminal
            string termType;
            termType = “dumb”;
            int widthInChars;
            widthInChars = 120;
            int heightInChars;
            heightInChars = 40;
            int pixWidth;
            pixWidth = 0;
            int pixHeight;
            pixHeight = 0;
            success = ssh.SendReqPty(channelNum, termType, widthInChars, heightInChars, pixWidth, pixHeight);
            if (success != true)
            {
                Console.WriteLine(ssh.LastErrorText + “\r\n”);
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            Console.WriteLine(”Starting a shell…”);

            //  Start a shell on the channel:
            success = ssh.SendReqShell(channelNum);
            if (success != true)
            {
                Console.WriteLine(ssh.LastErrorText + “\r\n”);
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            // Loop to read from the SSH channel, output to the console, and read keyboard input from the console.
            StringBuilder sb = new StringBuilder();
            while (true)
            {
                if (Console.KeyAvailable)
                {
                    ConsoleKeyInfo key = Console.ReadKey(true);
                    Console.Write(key.KeyChar);

                    switch (key.Key)
                    {
                        case ConsoleKey.Enter:
                            Console.WriteLine(”");

                            sb.Append(”\n”);
                            success = ssh.ChannelSendString(channelNum, sb.ToString(), “ansi”);
                            if (success != true)
                            {
                                Console.WriteLine(ssh.LastErrorText + “\r\n”);
                                // Read so we can see the error before the console closes.
                                string x = Console.ReadLine();
                                return;
                            }

                            sb.Length = 0;
                            break;
                        default:
                            //Console.Write(key.KeyChar);
                            sb.Append(key.KeyChar);
                            break;
                    }

                }

                // Now check for incoming data from the SSH channel.
                int retval = ssh.ChannelPoll(channelNum, 10);
                if (retval == -1)
                {
                    Console.Write(ssh.LastErrorText);
                    Console.WriteLine(”");
                    // Read so we can see the error before the console closes.
                    string x = Console.ReadLine();
                    return;
                }
                if (retval > 0)
                {
                    Console.Write(ssh.GetReceivedText(channelNum, “ansi”));
                }
                else
                {
                    // If data arrived, loop around and get more immediately.
                    // Otherwise wait 20ms.
                    System.Threading.Thread.Sleep(20);
                }

            }  

        }
    }
}

December 10, 2009

Background Enabled Methods - Using Chilkat Asynchronously

Filed under: HTTP, asynchronous — Tags: , , , — admin @ 4:38 pm

The latest version of the Chilkat HTTP component introduces a set of methods and properties that allow already-existing methods to be called asynchronously. For example, by setting the UseBgThread property equal to True, any background-enabled method, such as Download, will run in a background thread. Normally, when called synchronously, the method returns control to the caller only after the HTTP operation has completed. However, when UseBgThread = True, the method returns immediately and the HTTP operation is started in a background thread. (For a given HTTP object instance, only one background method may be ongoing at a time. It is possible to use multiple HTTP object instances, each of which might be processing a backgrounded method call.)

The set of background-enabling methods and properties are:

  • (property) UseBgThread - If True, then background-enabled methods will run in a background thread. Normally, a method will return after its work is completed. However, when UseBgThread is true, the method will return immediately and a background thread is started to carry out the method’s task.
  • (property) BgTaskRunning - If True then the object instance already has a backgrounded method running. Another backgrounded method cannot be started until the 1st completes. (Multiple simultaneous background methods may run by using multiple object instances.)
  • (property) BgTaskFinished - Becomes True when the background method completes. Your application would periodically check for this condition.
  • (property) BgTaskSuccess - Only meaningful (True/False) after a background method completes.
  • (property) BgLastErrorText - Last-error information is saved here and not in the LastErrorText property. If the background method fails, this will contain information about what transpired. (This property also contains information when the background method succeeds.)
  • (method) BgTaskAbort - Call this to force the currently running backgrounded method to abort.
  • (property) BgResultString - If the backgrounded method returns a string, the return value is found here.
  • (property) BgResultInt - If the backgrounded method returns an integer, the return value is found here.
  • (property) BgResultData - If the backgrounded method returns a byte array, the returned data is found here.
  • (method) BgResponseObject - If the backgrounded method returns an HttpResponse object, it may be retrieved by calling this method.


Example

An example of backgrounding the Download method may be found here.

Background Enabling other Chilkat Components
The HTTP component is the first Chilkat component to become background-enabled. The current development plan is to add the identical set of properties and methods to other Chilkat components to background-enable its functionality (such as for POP3, SMTP, IMAP, SSH, SFTP, Zip, MHT, etc.)

Asynchronous HTTP

Filed under: HTTP — Tags: , , — admin @ 2:37 pm

The following example demonstrates the new asynchronous HTTP functionality (in the latest version of Chilkat) that allows for any HTTP method to be run asynchronously in a background thread:

ASP: HTTP in a Background Thread (Asynchronous HTTP)
SQL Server: HTTP in a Background Thread (Asynchronous HTTP)
C#: HTTP in a Background Thread (Asynchronous HTTP)
C++: HTTP in a Background Thread (Asynchronous HTTP)
MFC: HTTP in a Background Thread (Asynchronous HTTP)
C: HTTP in a Background Thread (Asynchronous HTTP)
Delphi: HTTP in a Background Thread (Asynchronous HTTP)
Visual FoxPro: HTTP in a Background Thread (Asynchronous HTTP)
Java: HTTP in a Background Thread (Asynchronous HTTP)
Perl: HTTP in a Background Thread (Asynchronous HTTP)
PHP: HTTP in a Background Thread (Asynchronous HTTP)
Python: HTTP in a Background Thread (Asynchronous HTTP)
Ruby: HTTP in a Background Thread (Asynchronous HTTP)
VB.NET: HTTP in a Background Thread (Asynchronous HTTP)
Visual Basic: HTTP in a Background Thread (Asynchronous HTTP)
VBScript: HTTP in a Background Thread (Asynchronous HTTP)

Debugging an HTTP Form Login

Filed under: HTTP — Tags: — admin @ 7:55 am

This is a summary of the steps I’m taking to debug the following problem:

	I am trying to login using Chilkat HTTP to this site:
	http://www.mister-wong.com
	and after the login, there is a 302 redirect. After the redirect, the
	session is lost.
	I believe it could be another cookie related issue.

1. Make sure I’m using the very latest version of the Chilkat HTTP component/library.

2. Set the SessionLogFilename property equal to the name of a log file the component will create. The exact HTTP requests and responses will be logged here. I’ll check them for cookies received and sent.

3. Call http.QuickGetStr(”http://www.mister-wong.com/”). Examine the session log and look for the Set-Cookie header in the response header. I see this:

	Set-Cookie: wongsess=d6f97305c1cacd528948f6ba6d41816c; expires=Sun, 10 Dec 2034 19:56:30 GMT; path=/

Look at the LastErrorText which contains information even when the method succeeded. Make sure it’s saving the cookie. It does because I see this:

    Saving cookies...
    Cookie:
      Domain: .mister-wong.com
      Path: /
      Expire: Sun, 10 Dec 2034 19:56:30 GMT
      CookieName: wongsess
      CookieValue: d6f97305c1cacd528948f6ba6d41816c
    SaveCookie:
      CookieDir: memory
      Domain: www.mister-wong.com
      HashKey: mister-wong_com.xml

4. OK, so far so good. Taking the next step — fetch the URL containing the login form: http://www.mister-wong.com/users/login/ The HTTP component *should* send the cookie previously received (if the cookie jar is “memory”, it must be the same instance of the HTTP object). The test code will now look like this:

            Chilkat.Http http = new Chilkat.Http();
            bool success = http.UnlockComponent("test");
            if (!success)
            {
                textBox1.Text = http.LastErrorText;
            }

            http.CookieDir = "memory";
            http.SaveCookies = true;
            http.SendCookies = true;

            http.SessionLogFilename = "httpSessionLog.txt";

            string html1 = http.QuickGetStr("http://www.mister-wong.com");
            textBox1.Text = http.LastErrorText;

            string html2 = http.QuickGetStr("http://www.mister-wong.com/users/login/");
            textBox1.Text += http.LastErrorText;
            textBox2.Text = html2;

Looking at the LastErrorText for the 2nd QuickGetStr, I see this:

    AddingCookie: wongsess=a693f8b733aa146a235cd5edfa755da1

The cookie is re-sent as it should be.
Looking at the session log file, I see this for the 2nd GET request:

	---- Sending ----
	GET /users/login/ HTTP/1.1
	Accept: */*
	Accept-Encoding: gzip
	Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
	Accept-Language: en-us,en;q=0.5
	User-Agent: Chilkat/1.0.0 (+http://www.chilkatsoft.com/ChilkatHttpUA.asp)
	Cookie: wongsess=a693f8b733aa146a235cd5edfa755da1
	Host: www.mister-wong.com
	Connection: Keep-Alive

All looks OK.

5. Examine the HTML returned by the 2nd GET request. This should contain a login FORM. It does. Here it is:

<form id="UserLoginForm" method="post" action="/login">
<fieldset style="display:none;">
<input type="hidden" name="_method" value="POST" />
</fieldset>
<div class="input text required">
<label for="UserName">Username:</label>
<input name="data[User][name]” type=”text” maxlength=”40″ value=”" id=”UserName” /></div>
<div class=”input password”>
<label for=”UserPassword”>Password:</label>
<input type=”password” name=”data[User][password]” value=”" id=”UserPassword” />
</div><div class=”submit”>
<input type=”submit” value=”Login” />
</div></form>

A POST must be sent to http://www.mister-wong.com/login, the values to be sent are: _method, data[User][name], data[User][password]. (The POST params are the “name” attributes of the “input” tags within the form. The type=”submit” input may be ignored — this is the submit button.

6. Add code to send the POST (actual username and password has been removed):

*** The customer’s mistake was the Path. The Path specified in the FORM is not “/users/login/”, it is “/login”. This is the Path that should be used for the POST:

            ....
            Chilkat.HttpRequest http_request = new Chilkat.HttpRequest();
            http_request.AddParam("data[User][name]“, “***”);
            http_request.AddParam(”data[User][password]“, “***”);
            http_request.AddParam(”_method”, “POST”);
            http_request.UsePost();
            http_request.Path = “/login”;

            Chilkat.HttpResponse http_response = http.SynchronousRequest(”www.mister-wong.com”, 80, false, http_request);
            textBox1.Text += http.LastErrorText;
            textBox2.Text = html2;

7. Examine the session log. I see this for the POST:

	---- Sending ----
	POST /login HTTP/1.1
	Host: www.mister-wong.com
	Content-Type: application/x-www-form-urlencoded
	Content-Length: 67
	Cookie: wongsess=2423f07ab5b543145f800717361ee8d9

	data[User][name]=***&data[User][password]=***&_method=POST

The actual username/password values have been replaced with “***”. I see the cookie was properly sent.

8. The response to the POST (in this case) is a 302 redirect:

	---- Received ----
	HTTP/1.1 302 Found
	Date: Thu, 10 Dec 2009 14:35:53 GMT
	Server: Apache
	P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
	Set-Cookie: WongCookie[Auth][User]=6d914d1612a372e523; expires=Fri, 10-Dec-2010 14:35:54 GMT; path=/
	Location: http://www.mister-wong.com/
	Content-Length: 0
	Content-Type: text/html; charset=UTF-8

9. A new cookie is set in the 302 response, and the Chilkat HTTP component redirects to the new URL. The proper action is to send an HTTP GET to the “Location” specified in the 302 response. The new cookie should be included in the GET. This is exactly what Chilkat HTTP does:

	GET / HTTP/1.1
	Accept: */*
	Accept-Encoding: gzip
	Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
	Accept-Language: en-us,en;q=0.5
	User-Agent: Chilkat/1.0.0 (+http://www.chilkatsoft.com/ChilkatHttpUA.asp)
	Cookie: wongsess=2423f07ab5b543145f800717361ee8d9; WongCookieAuthUser=6d914d1612a372e523
	Host: www.mister-wong.com
	Connection: Keep-Alive

10. The response is a “200 OK”:

	---- Received ----
	HTTP/1.1 200 OK
	Date: Thu, 10 Dec 2009 14:35:55 GMT
	Server: Apache
	P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
	Keep-Alive: timeout=5, max=97
	Connection: Keep-Alive
	Transfer-Encoding: chunked
	Content-Type: text/html; charset=UTF-8

All looks to be in order…

December 9, 2009

HTTP Session Logging

Filed under: HTTP — Tags: , — admin @ 8:24 am

This example demonstrates how to use the new Chilkat HTTP SessionLogFilename property to log exact HTTP requests and responses to a file.  This can help in debugging…

ASP: HTTP Session Logging
SQL Server: HTTP Session Logging
C#: HTTP Session Logging
C++: HTTP Session Logging
MFC: HTTP Session Logging
C: HTTP Session Logging
Delphi: HTTP Session Logging
Visual FoxPro: HTTP Session Logging
Java: HTTP Session Logging
Perl: HTTP Session Logging
PHP: HTTP Session Logging
Python: HTTP Session Logging
Ruby: HTTP Session Logging
VB.NET: HTTP Session Logging
Visual Basic: HTTP Session Logging
VBScript: HTTP Session Logging

December 8, 2009

Socket “Not ready for writing” when trying to Connect?

Filed under: socket — Tags: , — admin @ 12:01 pm

Question:

Can you tell from this log why it would say “socket is not ready for writing”?

  OpenSmtpConnection:
     DllDate: Jun  9 2009
     UnlockPrefix: ****
     Username: Administrator
     Component: ActiveX
     Need new SMTP connection
     SMTP_Connect:
       Connecting to SMTP server mail.****.com:25
       smtp_host: mail.****.com
       smtp_port: 25
       domain: mail.****.com
       smtp_user: ****
       socket is not ready for writing
       Connect function failed.
       SocketError: WSAEWOULDBLOCK The socket would block.
       For more information see http://www.chilkatsoft.com/p/p_172.asp
       Failed to connect to SMTP server.
     Failed to connect to SMTP server

Answer:

All programs running on Windows, Linux, Unix, etc. that communicate using TCP/IP sockets ultimately use (directly or indirectly) the socket system calls (WinSock for Windows, but the functions are virtually the same). These include the following system-level functions: bind, listen, accept, connect, recv, send, select, etc. (see Guide to Network Programming) Even if your coding in Java or .NET, internal to the Java Runtime or the .NET Framework, it is these same socket-level functions that are ultimately called to carry out the work of connecting, reading, and writing TCP/IP sockets. It’s been that way for 30 years…

Naturally, the Chilkat libs call the WinSock functions to implement all of the TCP/IP based protocols — SMTP, IMAP, POP3, FTP, HTTP, SSH, etc. Internally, Chilkat uses non-blocking sockets — meaning that we never want to “hang” the calling thread. This is accomplished internally by using the “select” system call. Chilkat never reads, writes, connects, or tries to accept a connection without first knowing that the socket has data waiting, or that the socket function call will complete without delay. If you examine the description of the “select” WinSock function, you’ll see that there are arguments for both read and write file descriptors. Here’s an excerpt:

...
"The parameter writefds identifies the sockets that are to be checked for writability. If a socket is
processing a connect call (nonblocking), a socket is writeable if the connection establishment
successfully completes. If the socket is not processing a connect call, writability means a send,
sendto, or WSASendto are guaranteed to succeed."
...

The amount of time your application is willing to wait for the Connect to complete is controlled by
setting the Chilkat ConnectTimeout property. If no connection is possible in this amount of time,
(internally) the “select” function times out — i.e. the socket is not “writeable”. We get the
WSAEWOULDBLOCK error because technically, if we called the socket “connect” system call — it
would block (i.e. your program would hang).

A failure to connect is caused by one of the following:
1) There is no server listening at the remote hostname:port.
2) A firewall at either the client or server side is blocking the connection.
3) Something else is blocking the connection — perhaps TCP/IP port filtering or anti-virus.
4) The server is too slow to respond — perhaps your ConnectTimeout is too short and the server is far too busy…

Newer Posts »