libssh2

Форк
0
/
test_ssh2.c 
277 строк · 7.2 Кб
1
/* Copyright (C) The libssh2 project and its contributors.
2
 *
3
 * SPDX-License-Identifier: BSD-3-Clause
4
 *
5
 * Self test, based on example/ssh2.c.
6
 */
7

8
#include "libssh2_setup.h"
9
#include <libssh2.h>
10

11
#ifdef HAVE_SYS_SOCKET_H
12
#include <sys/socket.h>
13
#endif
14
#ifdef HAVE_UNISTD_H
15
#include <unistd.h>
16
#endif
17
#ifdef HAVE_NETINET_IN_H
18
#include <netinet/in.h>
19
#endif
20
#ifdef HAVE_ARPA_INET_H
21
#include <arpa/inet.h>
22
#endif
23

24
#include <stdio.h>
25
#include <stdlib.h>  /* for getenv() */
26

27
static const char *hostname = "127.0.0.1";
28
static const int port_number = 4711;
29
static const char *pubkey = "key_rsa.pub";
30
static const char *privkey = "key_rsa";
31
static const char *username = "username";
32
static const char *password = "password";
33

34
static void portable_sleep(unsigned int seconds)
35
{
36
#ifdef _WIN32
37
    Sleep(seconds);
38
#else
39
    sleep(seconds);
40
#endif
41
}
42

43
int main(int argc, char *argv[])
44
{
45
    uint32_t hostaddr;
46
    libssh2_socket_t sock;
47
    int i, auth_pw = 0;
48
    struct sockaddr_in sin;
49
    const char *fingerprint;
50
    char *userauthlist;
51
    int rc;
52
    LIBSSH2_SESSION *session = NULL;
53
    LIBSSH2_CHANNEL *channel;
54
    unsigned int counter;
55

56
#ifdef _WIN32
57
    WSADATA wsadata;
58

59
    rc = WSAStartup(MAKEWORD(2, 0), &wsadata);
60
    if(rc) {
61
        fprintf(stderr, "WSAStartup failed with error: %d\n", rc);
62
        return 1;
63
    }
64
#endif
65

66
    (void)argc;
67
    (void)argv;
68

69
    #ifdef _WIN32
70
    #define LIBSSH2_FALLBACK_USER_ENV "USERNAME"
71
    #else
72
    #define LIBSSH2_FALLBACK_USER_ENV "LOGNAME"
73
    #endif
74

75
    if(getenv("USER"))
76
        username = getenv("USER");
77
    else if(getenv(LIBSSH2_FALLBACK_USER_ENV))
78
        username = getenv(LIBSSH2_FALLBACK_USER_ENV);
79

80
    if(getenv("PRIVKEY"))
81
        privkey = getenv("PRIVKEY");
82

83
    if(getenv("PUBKEY"))
84
        pubkey = getenv("PUBKEY");
85

86
    hostaddr = inet_addr(hostname);
87
    if(hostaddr == (uint32_t)(-1)) {
88
        fprintf(stderr, "Failed to convert %s host address\n", hostname);
89
        return 1;
90
    }
91

92
    rc = libssh2_init(0);
93
    if(rc) {
94
        fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
95
        return 1;
96
    }
97

98
    rc = 1;
99

100
    sock = socket(AF_INET, SOCK_STREAM, 0);
101
    if(sock == LIBSSH2_INVALID_SOCKET) {
102
        fprintf(stderr, "failed to create socket.\n");
103
        goto shutdown;
104
    }
105

106
    sin.sin_family = AF_INET;
107
    sin.sin_port = htons((unsigned short)port_number);
108
    sin.sin_addr.s_addr = hostaddr;
109

110
    for(counter = 0; counter < 3; ++counter) {
111
        if(connect(sock, (struct sockaddr*)(&sin),
112
                   sizeof(struct sockaddr_in))) {
113
            fprintf(stderr,
114
                    "Connection to %s:%d attempt #%d failed: retrying...\n",
115
                    hostname, port_number, counter);
116
            portable_sleep(1 + 2*counter);
117
        }
118
        else {
119
            break;
120
        }
121
    }
122
    if(sock == LIBSSH2_INVALID_SOCKET) {
123
        fprintf(stderr, "Failed to connect to %s:%d\n",
124
                hostname, port_number);
125
        goto shutdown;
126
    }
127

128
    /* Create a session instance and start it up. This will trade welcome
129
     * banners, exchange keys, and setup crypto, compression, and MAC layers
130
     */
131
    session = libssh2_session_init();
132
    if(!session) {
133
        fprintf(stderr, "Could not initialize SSH session.\n");
134
        goto shutdown;
135
    }
136

137
    if(getenv("FIXTURE_TRACE_ALL_CONNECT") ||
138
       getenv("FIXTURE_TRACE_ALL")) {
139
        libssh2_trace(session, ~0);
140
        fprintf(stdout, "Trace all enabled.\n");
141
    }
142

143
    libssh2_session_set_blocking(session, 1);
144

145
    {
146
        int retries = 0, retry = 0;
147
#ifdef LIBSSH2_WINCNG
148
        /* FIXME: Retry tests with WinCNG due to flakiness in hostkey
149
           verification: https://github.com/libssh2/libssh2/issues/804 */
150
        retries += 2;
151
#endif
152
        do {
153
            rc = libssh2_session_handshake(session, sock);
154
            if(rc == 0) {
155
                break;
156
            }
157
            fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
158
            if(
159
#ifdef LIBSSH2_WINCNG
160
               rc != LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE ||
161
#endif
162
               ++retry > retries) {
163
                break;
164
            }
165
            fprintf(stderr, "Retrying... %d / %d\n", retry, retries);
166
        } while(1);
167
    }
168

169
    rc = 1;
170

171
    /* At this point we have not yet authenticated.  The first thing to do
172
     * is check the hostkey's fingerprint against our known hosts Your app
173
     * may have it hard coded, may go to a file, may present it to the
174
     * user, that's your call
175
     */
176
    fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
177
    fprintf(stderr, "Fingerprint: ");
178
    for(i = 0; i < 20; i++) {
179
        fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
180
    }
181
    fprintf(stderr, "\n");
182

183
    /* check what authentication methods are available */
184
    userauthlist = libssh2_userauth_list(session, username,
185
                                         (unsigned int)strlen(username));
186
    if(userauthlist) {
187
        fprintf(stderr, "Authentication methods: %s\n", userauthlist);
188
        if(strstr(userauthlist, "password")) {
189
            auth_pw |= 1;
190
        }
191
        if(strstr(userauthlist, "keyboard-interactive")) {
192
            auth_pw |= 2;
193
        }
194
        if(strstr(userauthlist, "publickey")) {
195
            auth_pw |= 4;
196
        }
197

198
        if(auth_pw & 4) {
199
            /* Authenticate by public key */
200
            if(libssh2_userauth_publickey_fromfile(session, username,
201
                                                   pubkey, privkey,
202
                                                   password)) {
203
                fprintf(stderr, "Authentication by public key failed.\n");
204
                goto shutdown;
205
            }
206
            else {
207
                fprintf(stderr, "Authentication by public key succeeded.\n");
208
            }
209
        }
210
        else {
211
            fprintf(stderr, "No supported authentication methods found.\n");
212
            goto shutdown;
213
        }
214
    }
215

216
    /* Request a session channel on which to run a shell */
217
    channel = libssh2_channel_open_session(session);
218
    if(!channel) {
219
        fprintf(stderr, "Unable to open a session\n");
220
        goto shutdown;
221
    }
222

223
    /* Some environment variables may be set,
224
     * It's up to the server which ones it'll allow though
225
     */
226
    libssh2_channel_setenv(channel, "FOO", "bar");
227

228
    /* Request a terminal with 'vanilla' terminal emulation
229
     * See /etc/termcap for more options. This is useful when opening
230
     * an interactive shell.
231
     */
232
    if(libssh2_channel_request_pty(channel, "vanilla")) {
233
        fprintf(stderr, "Failed requesting pty\n");
234
        goto skip_shell;
235
    }
236

237
    /* Open a SHELL on that pty */
238
    if(libssh2_channel_shell(channel)) {
239
        fprintf(stderr, "Unable to request shell on allocated pty\n");
240
        goto shutdown;
241
    }
242

243
    rc = 0;
244

245
skip_shell:
246

247
    if(channel) {
248
        libssh2_channel_free(channel);
249
        channel = NULL;
250
    }
251

252
shutdown:
253

254
    if(session) {
255
        libssh2_session_disconnect(session, "Normal Shutdown");
256
        libssh2_session_free(session);
257
    }
258

259
    if(sock != LIBSSH2_INVALID_SOCKET) {
260
        shutdown(sock, 2 /* SHUT_RDWR */);
261
#ifdef _WIN32
262
        closesocket(sock);
263
#else
264
        close(sock);
265
#endif
266
    }
267

268
    fprintf(stderr, "all done\n");
269

270
    libssh2_exit();
271

272
#ifdef _WIN32
273
    WSACleanup();
274
#endif
275

276
    return rc;
277
}
278

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.