diff --git a/example/Makefile.am b/example/Makefile.am index cfa16d9..c396fdf 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -8,7 +8,7 @@ noinst_PROGRAMS = ssh2 \ sftp_write sftp_write_nonblock \ sftp_mkdir sftp_mkdir_nonblock \ sftp_RW_nonblock \ - sftpdir sftpdir_nonblock ssh2_exec + sftpdir sftpdir_nonblock ssh2_exec ssh2_agent # the examples need the $(top_builddir)/src since when building outside of the # source dir they still need to reach the libssh2_config.h header diff --git a/example/ssh2_agent.c b/example/ssh2_agent.c new file mode 100644 index 0000000..a8e8519 --- /dev/null +++ b/example/ssh2_agent.c @@ -0,0 +1,229 @@ +/* + * Sample showing how to do SSH2 connect using ssh-agent. + * + * The sample code has default values for host name, user name: + * + * "ssh2_agent host user" + */ + +#include "libssh2_config.h" +#include +#include + +#ifdef HAVE_WINDOWS_H +# include +#endif +#ifdef HAVE_WINSOCK2_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +# ifdef HAVE_UNISTD_H +#include +#endif +# ifdef HAVE_ARPA_INET_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +const char *username="username"; + +int main(int argc, char *argv[]) +{ + unsigned long hostaddr; + int sock = -1, i, j, rc; + struct sockaddr_in sin; + const char *fingerprint; + char *userauthlist; + LIBSSH2_SESSION *session; + LIBSSH2_CHANNEL *channel; + LIBSSH2_AGENT *agent = NULL; + struct libssh2_agent_publickey *identity, *prev_identity = NULL; +#ifdef WIN32 + WSADATA wsadata; + + WSAStartup(MAKEWORD(2,0), &wsadata); +#endif + + if (argc > 1) { + hostaddr = inet_addr(argv[1]); + } else { + hostaddr = htonl(0x7F000001); + } + + if(argc > 2) { + username = argv[2]; + } + + /* Ultra basic "connect to port 22 on localhost". Your code is + * responsible for creating the socket establishing the connection + */ + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) { + fprintf(stderr, "failed to create socket!\n"); + rc = 1; + goto shutdown; + } + + sin.sin_family = AF_INET; + sin.sin_port = htons(22); + sin.sin_addr.s_addr = hostaddr; + if (connect(sock, (struct sockaddr*)(&sin), + sizeof(struct sockaddr_in)) != 0) { + fprintf(stderr, "failed to connect!\n"); + goto shutdown; + } + + /* Create a session instance and start it up. This will trade welcome + * banners, exchange keys, and setup crypto, compression, and MAC layers + */ + session = libssh2_session_init(); + if (libssh2_session_startup(session, sock)) { + fprintf(stderr, "Failure establishing SSH session\n"); + return 1; + } + + /* Connect to the ssh-agent */ + agent = libssh2_agent_init(session); + if (!agent) { + fprintf(stderr, "Failure initializing ssh-agent support\n"); + rc = 1; + goto shutdown; + } + if (libssh2_agent_connect(agent)) { + fprintf(stderr, "Failure connecting to ssh-agent\n"); + rc = 1; + goto shutdown; + } + if (libssh2_agent_list_identities(agent)) { + fprintf(stderr, "Failure requesting identities to ssh-agent\n"); + rc = 1; + goto shutdown; + } + while (1) { + rc = libssh2_agent_get_identity(agent, &identity, prev_identity); + if (rc == 1) + break; + if (rc < 0) { + fprintf(stderr, + "Failure obtaining identity from ssh-agent support\n"); + rc = 1; + goto shutdown; + } + if (libssh2_agent_userauth(agent, username, identity)) { + printf("\tAuthentication with username %s and " + "public key %s failed!\n", + username, identity->comment); + } else { + printf("\tAuthentication with username %s and " + "public key %s succeeded!\n", + username, identity->comment); + break; + } + prev_identity = identity; + } + if (rc) { + fprintf(stderr, "Couldn't continue authentication\n"); + goto shutdown; + } + + /* At this point we havn't authenticated. The first thing to do is check + * the hostkey's fingerprint against our known hosts Your app may have it + * hard coded, may go to a file, may present it to the user, that's your + * call + */ + fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); + printf("Fingerprint: "); + for(i = 0; i < 16; i++) { + printf("%02X ", (unsigned char)fingerprint[i]); + } + printf("\n"); + + /* check what authentication methods are available */ + userauthlist = libssh2_userauth_list(session, username, strlen(username)); + printf("Authentication methods: %s\n", userauthlist); + if (strstr(userauthlist, "publickey") == NULL) { + fprintf(stderr, "\"publickey\" authentication is not supported\n"); + goto shutdown; + } + + /* Request a shell */ + if (!(channel = libssh2_channel_open_session(session))) { + fprintf(stderr, "Unable to open a session\n"); + goto shutdown; + } + + /* Some environment variables may be set, + * It's up to the server which ones it'll allow though + */ + libssh2_channel_setenv(channel, "FOO", "bar"); + + /* Request a terminal with 'vanilla' terminal emulation + * See /etc/termcap for more options + */ + if (libssh2_channel_request_pty(channel, "vanilla")) { + fprintf(stderr, "Failed requesting pty\n"); + goto skip_shell; + } + + /* Open a SHELL on that pty */ + if (libssh2_channel_shell(channel)) { + fprintf(stderr, "Unable to request shell on allocated pty\n"); + goto shutdown; + } + + /* At this point the shell can be interacted with using + * libssh2_channel_read() + * libssh2_channel_read_stderr() + * libssh2_channel_write() + * libssh2_channel_write_stderr() + * + * Blocking mode may be (en|dis)abled with: libssh2_channel_set_blocking() + * If the server send EOF, libssh2_channel_eof() will return non-0 + * To send EOF to the server use: libssh2_channel_send_eof() + * A channel can be closed with: libssh2_channel_close() + * A channel can be freed with: libssh2_channel_free() + */ + + skip_shell: + if (channel) { + libssh2_channel_free(channel); + channel = NULL; + } + + /* Other channel types are supported via: + * libssh2_scp_send() + * libssh2_scp_recv() + * libssh2_channel_direct_tcpip() + */ + + shutdown: + + libssh2_agent_disconnect(agent); + libssh2_agent_free(agent); + + libssh2_session_disconnect(session, + "Normal Shutdown, Thank you for playing"); + libssh2_session_free(session); + + if (sock != -1) { +#ifdef WIN32 + closesocket(sock); +#else + close(sock); +#endif + } + + printf("all done!\n"); + return rc; +}