[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: help needed compiling libssh with msvc


So after a lot of hair pulling out and irc chat with libssh gurus then
I eventually came up with the following recipe to not only build
libssh (gave up on trying to run the unit tests on Windows... too much
voodoo involved) on Windows with MSVC 10 Prof. or Express, but also to
get the example samplesshd compiling and working on windows. It uses
the Linux 'argp' to pass the command line arguments and then uses some
funky gcc syntax to statically populate structs which I couldn't
figure out quickly how to do with cl.exe so I just hacked in the code
equivalent as you'll see below. I even offer command lines for running
some of the freshly built apps. I now have the following open
questions:

* What is the difference between libssh examples samplesshd-kbdint.c,
samplesshd-tty.c, samplesshd.c ? I'm guessing the following:
** Guessing that samplesshd.c establishes a connection and client ssh
sends terminal characters which just accumulate at the server end.
** Guessing that samplesshd-tty.c establishes a connection and client
ssh sends terminal characters which get passed on to a shell at the
server end.
*** Can we compile samplesshd-tty.c on Windows?
*** Are there any example applications which allow access to the
windows command prompt (or similar) via ssh?
** No idea what samplesshd-kbdint.c does :-(
* samplesshd doesn't seem to want to start without keys, so why does
it insist on password authentication if the client offers a key?
* samplesshd just exits when the connection ends and very quickly
times out and exits e.g. at password input. Why exit? Why does it
behave so differently than regular sshd by default?

My build recipe for other Windows libssh users to enjoy:

h1. Spike to build and understand libssh on Windows

h2. Building libssh on Windows

* (!) Assumes you have MSVC & git tool chain installed and in the path
* (!) The packaged instructions for building are horrible so these
instructions were found by trial and error
** mkdir C:\source-simon

h3. Download & install prerequisite: openssl

* (!) Tried to build openssl from scratch and it worked and tests
passed but libssh didn't like it so finally temporarily gave up to go
with openssl binary:
* Download and install latest openssl developer release from
http://www.slproweb.com/products/Win32OpenSSL.html
* E.g. http://www.slproweb.com/download/Win32OpenSSL-1_0_0g.exe
* If you get the message "... missing: Microsoft Visual C++ 2008
Redistributables", download & install
http://www.microsoft.com/downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF
* Accept the defaults, e.g. Copy OpenSSL DLLs to: [x] The Windows
system directory

h3. Download libssh source code

* cd C:\source-simon
* git clone http://git.libssh.org/projects/libssh.git libssh

h3. Create build folder & makefile for building libssh

* cd C:\source-simon
* mkdir libssh-build
* cd libssh-build
* cmake -DWITH_SERVER=ON -DWITH_ZLIB=OFF -G"NMake Makefiles"
c:/source-simon/libssh
* (!) Without -G builds libssh.sln for MSVC gui but seems to ignore
build folder then; we go with nmake on the command line
* (!) For testing we also avoid having to link with zlib; hence WITH_ZLIB=OFF

h3. Build libssh & example windows applications

* cd C:\source-simon\libssh-build
* nmake
* [100%] Built target senddata
* (!) At this point on Windows there should be 4 .exe files in examples:
{noformat}
c:\source-simon\libssh-build>dir examples\*.exe /b
exec.exe
libsshpp.exe
libsshpp_noexcept.exe
senddata.exe
{noformat}
* (!) Unfortunately the juicy ssh server examples are Linux only:
{noformat}
c:\source-simon\libssh-build>type ..\libssh\examples\CMakeLists.txt
...
if (LINUX)
...
    if (WITH_SERVER)
        add_executable(samplesshd samplesshd.c)
        target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})

        add_executable(samplesshd-kbdint samplesshd-kbdint.c)
        target_link_libraries(samplesshd-kbdint ${LIBSSH_SHARED_LIBRARY})

        if (HAVE_LIBUTIL)
            add_executable(samplesshd-tty samplesshd-tty.c)
            target_link_libraries(samplesshd-tty ${LIBSSH_SHARED_LIBRARY} util)
        endif (HAVE_LIBUTIL)

    endif (WITH_SERVER)
endif (LINUX)
...
{noformat}

h3. Doctor Linux samplesshd so that it will compile on Windows

* First add these lines to ..\libssh\examples\CMakeLists.txt
{noformat}
if (WITH_SERVER)
    add_executable(samplesshd samplesshd.c)
    target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
endif (WITH_SERVER)
{noformat}
* cd C:\source-simon\libssh-build
* cmake -DWITH_SERVER=ON -DWITH_ZLIB=OFF -G"NMake Makefiles"
/source-simon/libssh
* Grab Windows version of argp from
http://code.google.com/p/madp-win/source/browse/#hg%2Fsrc%2Fargp-standalone-1.3:
** mkdir ..\argp
** Download the following files so:
** http://madp-win.googlecode.com/hg/src/argp-standalone-1.3/argp.h
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/argp-parse.c
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/argp-namefrob.h
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/argp-pvh.c
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/argp-help.c
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/argp-fmtstream.h
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/argp-fmtstream.c
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/argp-eexst.c
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/strcasecmp.c
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/mempcpy.c
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/strchrnul.c
** http://code.google.com/p/madp-win/source/browse/src/argp-standalone-1.3/strndup.c
** So that they look like this:
{noformat}
c:\source-simon\libssh-build>dir ..\argp /b
argp-eexst.c
argp-fmtstream.c
argp-fmtstream.h
argp-help.c
argp-namefrob.h
argp-parse.c
argp-pvh.c
argp.h
mempcpy.c
strcasecmp.c
strchrnul.c
strndup.c
{noformat}
* Make the following changes to samplesshd.c
{noformat}
...
#ifdef HAVE_ARGP_H
#include <argp.h>
#else
#    ifdef _WIN32
#        // don't know how to compile some windows only code via cmake so:
#        define HAVE_ARGP_H 1
#        include "/source-simon/argp/argp.h"
#        include "/source-simon/argp/argp-namefrob.h"
#        include "/source-simon/argp/argp-fmtstream.h"
#        include "/source-simon/argp/argp-parse.c"
#        include "/source-simon/argp/argp-pvh.c"
#        include "/source-simon/argp/argp-help.c"
#        include "/source-simon/argp/argp-fmtstream.c"
#        include "/source-simon/argp/argp-eexst.c"
#        include "/source-simon/argp/strcasecmp.c"
#        include "/source-simon/argp/mempcpy.c"
#        include "/source-simon/argp/strchrnul.c"
#        include "/source-simon/argp/strndup.c"
#    endif
#endif
...
int main(int argc, char **argv){
...
    // don't know how to have automatic struct declaration assignments
via MSVC so:

    options[enum_option____port].name  = "port"                 ;
    options[enum_option____port].key   = 'p'                    ;
    options[enum_option____port].arg   = "PORT"                 ;
    options[enum_option____port].flags = 0                      ;
    options[enum_option____port].doc   = "Set the port to bind.";
    options[enum_option____port].group = 0                      ;

    options[enum_option_hostkey].name  = "hostkey"              ;
    options[enum_option_hostkey].key   = 'k'                    ;
    options[enum_option_hostkey].arg   = "FILE"                 ;
    options[enum_option_hostkey].flags = 0                      ;
    options[enum_option_hostkey].doc   = "Set the host key."    ;
    options[enum_option_hostkey].group = 0;

    options[enum_option__dsakey].name  = "dsakey"               ;
    options[enum_option__dsakey].key   = 'd'                    ;
    options[enum_option__dsakey].arg   = "FILE"                 ;
    options[enum_option__dsakey].flags = 0                      ;
    options[enum_option__dsakey].doc   = "Set the dsa key."     ;
    options[enum_option__dsakey].group = 0                      ;

    options[enum_option__rsakey].name  = "rsakey"               ;
    options[enum_option__rsakey].key   = 'r'                    ;
    options[enum_option__rsakey].arg   = "FILE"                 ;
    options[enum_option__rsakey].flags = 0                      ;
    options[enum_option__rsakey].doc   = "Set the rsa key."     ;
    options[enum_option__rsakey].group = 0                      ;

    options[enum_option_verbose].name  = "verbose"              ;
    options[enum_option_verbose].key   = 'v'                    ;
    options[enum_option_verbose].arg   = NULL                   ;
    options[enum_option_verbose].flags = 0                      ;
    options[enum_option_verbose].doc   = "Get verbose output."  ;
    options[enum_option_verbose].group = 0                      ;

    options[enum_option____null].name  = NULL                   ;
    options[enum_option____null].key   = 0                      ;
    options[enum_option____null].arg   = 0                      ;
    options[enum_option____null].flags = 0                      ;
    options[enum_option____null].doc   = NULL                   ;
    options[enum_option____null].group = 0                      ;
...
{noformat}
* nmake
* The folder structure should end up looking like this:
{noformat}
c:\source-simon\libssh-build>tree /A ..
C:\SOURCE-SIMON
+---argp
+---libssh
|   +---build
|   +---cmake
|   |   \---Modules
|   +---doc
|   +---examples
|   +---include
|   |   \---libssh
|   +---src
|   |   \---threads
|   \---tests
|       +---benchmarks
|       +---client
|       +---sftp_stress
|       \---unittests
\---libssh-build
    +---CMakeFiles
    |   +---CMakeTmp
    |   |   \---CMakeFiles
    |   |       \---cmTryCompileExec.dir
    |   +---CMakeTmp2
    |   +---CMakeTmp3
    |   +---CompilerIdC
    |   \---CompilerIdCXX
    +---doc
    |   \---CMakeFiles
    +---examples
    |   \---CMakeFiles
    |       +---exec.dir
    |       +---libsshpp.dir
    |       +---libsshpp_noexcept.dir
    |       +---samplesshd-tty.dir
    |       +---samplesshd.dir
    |       \---senddata.dir
    +---include
    |   +---CMakeFiles
    |   \---libssh
    |       \---CMakeFiles
    \---src
        \---CMakeFiles
            \---ssh_shared.dir
{noformat}

h3. Running doctored samplesshd on Windows

* Create some keys otherwise samplessd refuses to start
** (!) This can be done on e.g. Linux and then copied to \source-simon\
** ssh-keygen -t rsa -b 2048 -f ../ssh_host_rsa_key
** ssh-keygen -t dsa -b 1024 -f ../ssh_host_dsa_key
* (!) All the examples rely on ssh.dll
* (!) If you don't have an ssh client on Windows then figure out what
your LAN IP is and substitute it on the following line:
{noformat}
copy /Y src\ssh.dll .\examples\ && .\examples\samplesshd -d
../ssh_host_dsa_key -r ../ssh_host_rsa_key --port 7000 --verbose
192.168.1.128
{noformat}
* Upon connection with password: lala:
{noformat}
[2012/02/08 18:54:54.682753, 3]   Enabling POLLOUT for socket
[2012/02/08 18:54:54.682753, 3]   Received banner:
SSH-2.0-OpenSSH_5.8p1 Debian-1ubuntu3
[2012/02/08 18:54:54.683753, 1]   SSH client banner:
SSH-2.0-OpenSSH_5.8p1 Debian-1ubuntu3
[2012/02/08 18:54:54.684753, 1]   Analyzing banner:
SSH-2.0-OpenSSH_5.8p1 Debian-1ubuntu3
[2012/02/08 18:54:54.684753, 1]   We are talking to an OpenSSH client
version: 5.8 (50800)
[2012/02/08 18:54:54.685753, 3]   Enabling POLLOUT for socket
[2012/02/08 18:54:54.686753, 3]   packet: wrote
[len=332,padding=9,comp=322,payload=322]
[2012/02/08 18:54:54.687753, 3]   packet: read type 20
[len=1140,padding=4,comp=1135,payload=1135]
[2012/02/08 18:54:54.687753, 3]   Dispatching handler for packet type 20
[2012/02/08 18:54:54.688753, 3]   Set output algorithm aes128-ctr
[2012/02/08 18:54:54.689753, 3]   Set input algorithm aes128-ctr
[2012/02/08 18:54:54.690753, 3]   Processing 80 bytes left in socket buffer
[2012/02/08 18:54:54.690753, 3]   packet: read type 30
[len=76,padding=5,comp=70,payload=70]
[2012/02/08 18:54:54.691754, 3]   Dispatching handler for packet type 30
[2012/02/08 18:54:54.693754, 3]   Received SSH_MSG_KEXDH_INIT
[2012/02/08 18:54:54.703754, 2]   SSH_MSG_KEXDH_REPLY sent
[2012/02/08 18:54:54.704754, 3]   packet: wrote
[len=636,padding=7,comp=628,payload=628]
[2012/02/08 18:54:54.705754, 3]   packet: wrote
[len=12,padding=10,comp=1,payload=1]
[2012/02/08 18:54:54.706754, 2]   SSH_MSG_NEWKEYS sent
[2012/02/08 18:54:54.706754, 3]   Enabling POLLOUT for socket
[2012/02/08 18:54:54.708755, 3]   packet: read type 21
[len=12,padding=10,comp=1,payload=1]
[2012/02/08 18:54:54.709755, 3]   Dispatching handler for packet type 21
[2012/02/08 18:54:54.709755, 2]   Received SSH_MSG_NEWKEYS
[2012/02/08 18:54:54.710755, 3]   ssh_handle_key_exchange: Actual state : 7
[2012/02/08 18:54:54.711755, 3]   packet: read type 5
[len=28,padding=10,comp=17,payload=17]
[2012/02/08 18:54:54.712755, 3]   Dispatching handler for packet type 5
[2012/02/08 18:54:54.713755, 3]   Received a SERVICE_REQUEST for
service ssh-userauth
[2012/02/08 18:54:54.714755, 3]   Sending a SERVICE_ACCEPT for service
ssh-userauth
[2012/02/08 18:54:54.715755, 3]   Enabling POLLOUT for socket
[2012/02/08 18:54:54.716755, 3]   packet: wrote
[len=28,padding=10,comp=17,payload=17]
[2012/02/08 18:54:54.718755, 3]   packet: read type 50
[len=44,padding=8,comp=35,payload=35]
[2012/02/08 18:54:54.719755, 3]   Dispatching handler for packet type 50
[2012/02/08 18:54:54.720755, 3]   Auth request for service
ssh-connection, method none for user 'aris'
[2012/02/08 18:54:54.724755, 3]   Sending a auth failure. methods that
can continue: password
[2012/02/08 18:54:54.725755, 3]   Enabling POLLOUT for socket
[2012/02/08 18:54:54.726756, 3]   packet: wrote
[len=28,padding=13,comp=14,payload=14]
[2012/02/08 18:54:56.737871, 3]   packet: read type 50
[len=124,padding=75,comp=48,payload=48]
[2012/02/08 18:54:56.737871, 3]   Dispatching handler for packet type 50
[2012/02/08 18:54:56.738871, 3]   Auth request for service
ssh-connection, method password for user 'aris'
User aris wants to auth with pass lala
[2012/02/08 18:54:56.740871, 3]   Enabling POLLOUT for socket
[2012/02/08 18:54:56.740871, 3]   packet: wrote
[len=12,padding=10,comp=1,payload=1]
[2012/02/08 18:54:56.741871, 3]   packet: read type 90
[len=44,padding=19,comp=24,payload=24]
[2012/02/08 18:54:56.742871, 3]   Dispatching handler for packet type 90
[2012/02/08 18:54:56.742871, 3]   Clients wants to open a session channel
[2012/02/08 18:54:56.743871, 3]   Accepting a channel request_open for chan 0
[2012/02/08 18:54:56.744871, 3]   Enabling POLLOUT for socket
[2012/02/08 18:54:56.745871, 3]   packet: wrote
[len=28,padding=10,comp=17,payload=17]
[2012/02/08 18:54:56.745871, 3]   packet: read type 98
[len=316,padding=13,comp=302,payload=302]
[2012/02/08 18:54:56.746871, 3]   Dispatching handler for packet type 98
[2012/02/08 18:54:56.747871, 3]   Received a pty-req channel_request
for channel (43:0) (want_reply=1)
[2012/02/08 18:54:56.747871, 3]   Processing 120 bytes left in socket buffer
[2012/02/08 18:54:56.748871, 3]   packet: read type 98
[len=44,padding=7,comp=36,payload=36]
[2012/02/08 18:54:56.749871, 3]   Dispatching handler for packet type 98
[2012/02/08 18:54:56.750871, 3]   Received a env channel_request for
channel (43:0) (want_reply=0)
[2012/02/08 18:54:56.751871, 3]   Processing 52 bytes left in socket buffer
[2012/02/08 18:54:56.752871, 3]   packet: read type 98
[len=28,padding=12,comp=15,payload=15]
[2012/02/08 18:54:56.752871, 3]   Dispatching handler for packet type 98
[2012/02/08 18:54:56.753871, 3]   Received a shell channel_request for
channel (43:0) (want_reply=1)
[2012/02/08 18:54:56.754872, 3]   Sending a channel_request success to channel 0
[2012/02/08 18:54:56.755872, 3]   Enabling POLLOUT for socket
[2012/02/08 18:54:56.755872, 3]   packet: wrote
[len=12,padding=6,comp=5,payload=5]
it works !
[2012/02/08 18:54:56.756872, 2]   Read (2048) buffered : 0 bytes. Window: 32000
{noformat}
* On another box e.g. Linux then with a copy of the keyfiles run the
following command in order to connect to the LAN IP:
{noformat}
ssh -v -i ../ssh_host_rsa_key.pub -l aris -p 7000 192.168.1.128
OpenSSH_5.8p1 Debian-1ubuntu3, OpenSSL 0.9.8o 01 Jun 2010
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to 192.168.1.128 [192.168.1.128] port 7000.
debug1: Connection established.
debug1: identity file ../ssh_host_rsa_key.pub type 1
debug1: Checking blacklist file /usr/share/ssh/blacklist.RSA-2048
debug1: Checking blacklist file /etc/ssh/blacklist.RSA-2048
debug1: identity file ../ssh_host_rsa_key.pub-cert type -1
debug1: Remote protocol version 2.0, remote software version libssh-0.6.0
debug1: no match: libssh-0.6.0
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.8p1 Debian-1ubuntu3
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA b0:82:f8:34:81:0d:71:f9:2b:3e:30:93:1d:1f:8f:09
debug1: Host '[192.168.1.128]:7000' is known and matches the RSA host key.
debug1: Found key in /home/simon/.ssh/known_hosts:27
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: password
debug1: Next authentication method: password
aris@xxxxxxxxxxxxx's password: lala
debug1: Authentication succeeded (password).
Authenticated to 192.168.1.128 ([192.168.1.128]:7000).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8
{noformat}

The End

References:
help needed compiling libssh with msvcSimon <simonhf@xxxxxxxxx>
Re: help needed compiling libssh with msvcAndreas Schneider <asn@xxxxxxxxxxxxxx>
Re: help needed compiling libssh with msvcSimon <simonhf@xxxxxxxxx>
Re: help needed compiling libssh with msvcAndreas Schneider <asn@xxxxxxxxxxxxxx>
Re: help needed compiling libssh with msvcSimon <simonhf@xxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org