First checkin of the test suite
Этот коммит содержится в:
родитель
2c5a8480b0
Коммит
064c6cde3a
19
test/Makefile
Обычный файл
19
test/Makefile
Обычный файл
@ -0,0 +1,19 @@
|
||||
LIBS = -L../src -lssh2
|
||||
CFLAGS = -c -I../include
|
||||
CC = gcc -Wall -g
|
||||
OBJS = main.o util.o methods.o auth.o forward.o
|
||||
|
||||
all: libssh2-test
|
||||
|
||||
libssh2-test: $(OBJS)
|
||||
$(CC) -o libssh2-test $(OBJS) $(LIBS)
|
||||
|
||||
|
||||
main.o: main.c libssh2.h
|
||||
util.o: util.c libssh2.h
|
||||
methods.o: methods.c libssh2.h
|
||||
auth.o: auth.c libssh2.h
|
||||
forward.o: forward.c libssh2.h
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) libssh2-test
|
27
test/README
Обычный файл
27
test/README
Обычный файл
@ -0,0 +1,27 @@
|
||||
This is meant to test the libssh2 code's protocol compliance against other
|
||||
implementations. If you want to add a test, you will need to do the following:
|
||||
|
||||
* create a new source file, and add it to the Makefile
|
||||
|
||||
* call your main function (runtest_yourtest) from main() in main.c
|
||||
|
||||
* at the top of your source file, put:
|
||||
|
||||
#include <libssh2.h>
|
||||
#include "libssh2-test.h"
|
||||
|
||||
extern struct authdefs auth;
|
||||
|
||||
|
||||
* call init_test("description of your test", number_of_steps)
|
||||
|
||||
* before every step in your test, call increase_progress()
|
||||
|
||||
* after every step, if it was successful, call step_successful()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
215
test/auth.c
Обычный файл
215
test/auth.c
Обычный файл
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* auth.c -- test authentication methods
|
||||
*
|
||||
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names
|
||||
* of any other contributors may be used to endorse or
|
||||
* promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libssh2.h>
|
||||
#include "libssh2-test.h"
|
||||
|
||||
extern struct authdefs auth;
|
||||
|
||||
|
||||
static int auth_publickey(LIBSSH2_SESSION *session)
|
||||
{
|
||||
|
||||
if(libssh2_userauth_publickey_fromfile(session, auth.username,
|
||||
auth.pubkey, auth.privkey, auth.passphrase))
|
||||
{
|
||||
log_line(ERROR, "Public key authentication failed\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!libssh2_userauth_authenticated(session))
|
||||
{
|
||||
log_line(ERROR, "Public key authentication succeeded, but authentication not set\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static int auth_password(LIBSSH2_SESSION *session)
|
||||
{
|
||||
|
||||
if(libssh2_userauth_password(session, auth.username, auth.password))
|
||||
{
|
||||
log_line(ERROR, "Password authentication failed\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!libssh2_userauth_authenticated(session))
|
||||
{
|
||||
log_line(ERROR, "Password authentication succeeded, but authentication not set\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static void all_auth(void)
|
||||
{
|
||||
LIBSSH2_SESSION *session;
|
||||
int sock, size, res, sum, i;
|
||||
unsigned char *hash;
|
||||
char *errmsg, *_authlist, *authlist, *authmethod, *sep;
|
||||
|
||||
authlist = NULL;
|
||||
authmethod = "";
|
||||
while(authmethod)
|
||||
{
|
||||
sock = new_socket();
|
||||
if(sock == -1)
|
||||
{
|
||||
log_line(ERROR, "new_socket() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
session = libssh2_session_init();
|
||||
|
||||
res = libssh2_session_startup(session, sock);
|
||||
if(res)
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "session_startup() failed: %s\n", errmsg);
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!authlist)
|
||||
{
|
||||
_authlist = libssh2_userauth_list(session, auth.username, strlen(auth.username));
|
||||
if(_authlist == NULL)
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "userauth_list() failed: %s\n", errmsg);
|
||||
libssh2_session_disconnect(session, "All done.");
|
||||
libssh2_session_free(session);
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
authlist = strdup(_authlist);
|
||||
authmethod = authlist;
|
||||
|
||||
/* only need to check hostkey hashes once... might as well do that here */
|
||||
increase_progress();
|
||||
hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||
if(hash)
|
||||
{
|
||||
sum = 0;
|
||||
for(i = 0; i < 16; i++)
|
||||
sum += hash[i];
|
||||
if(sum > 0)
|
||||
step_successful();
|
||||
else
|
||||
log_line(ERROR, "MD5 hostkey hash invalid\n");
|
||||
}
|
||||
else
|
||||
log_line(ERROR, "MD5 hostkey hash failed\n");
|
||||
|
||||
increase_progress();
|
||||
hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||
if(hash)
|
||||
{
|
||||
sum = 0;
|
||||
for(i = 0; i < 20; i++)
|
||||
sum += hash[i];
|
||||
if(sum > 0)
|
||||
step_successful();
|
||||
else
|
||||
log_line(ERROR, "SHA1 hostkey hash invalid\n");
|
||||
}
|
||||
else
|
||||
log_line(ERROR, "SHA1 hostkey hash failed\n");
|
||||
|
||||
}
|
||||
|
||||
if( (sep = strchr(authmethod, ',')) )
|
||||
*sep++ = '\0';
|
||||
|
||||
if(!strcasecmp(authmethod, "publickey"))
|
||||
{
|
||||
increase_progress();
|
||||
if(auth_publickey(session))
|
||||
step_successful();
|
||||
}
|
||||
else if(!strcasecmp(authmethod, "password"))
|
||||
{
|
||||
increase_progress();
|
||||
if(auth_password(session))
|
||||
step_successful();
|
||||
}
|
||||
else if(!strcasecmp(authmethod, "keyboard-interactive"))
|
||||
{
|
||||
/* no idea how to test this */
|
||||
}
|
||||
else
|
||||
{
|
||||
log_line(DEBUG, "Unknown authentication method %s\n", authmethod);
|
||||
}
|
||||
|
||||
authmethod = sep;
|
||||
|
||||
libssh2_session_disconnect(session, "All done.");
|
||||
libssh2_session_free(session);
|
||||
close(sock);
|
||||
}
|
||||
|
||||
free(authlist);
|
||||
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void runtest_auth(void)
|
||||
{
|
||||
|
||||
init_test("authentication", 4);
|
||||
|
||||
all_auth();
|
||||
|
||||
}
|
||||
|
272
test/forward.c
Обычный файл
272
test/forward.c
Обычный файл
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* forward.c -- ssh2 port forwarding test
|
||||
*
|
||||
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names
|
||||
* of any other contributors may be used to endorse or
|
||||
* promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <wordexp.h>
|
||||
|
||||
#include <libssh2.h>
|
||||
#include "libssh2-test.h"
|
||||
|
||||
struct authdefs auth;
|
||||
extern struct addrinfo *cur_ai;
|
||||
|
||||
#define LISTEN_PORT 22617
|
||||
#define TESTBUF_SIZE 10
|
||||
|
||||
|
||||
static int loopback(LIBSSH2_SESSION *session, int hostbind, int portbind)
|
||||
{
|
||||
LIBSSH2_CHANNEL *inbound, *outbound;
|
||||
LIBSSH2_LISTENER *listener;
|
||||
int listen_port, size, i, res;
|
||||
char paramstr[64], ipstr[128], *errmsg, *host, *sendbuf, *recvbuf;
|
||||
|
||||
snprintf(paramstr, 64, "(%shost bind, %sport bind)", hostbind ? "" : "no ", portbind ? "" : "no ");
|
||||
|
||||
host = NULL;
|
||||
if(hostbind)
|
||||
{
|
||||
if(getnameinfo(cur_ai->ai_addr, cur_ai->ai_addrlen, ipstr, sizeof(ipstr), NULL, 0, NI_NUMERICHOST))
|
||||
{
|
||||
log_line(ERROR, "getnameinfo() failed\n");
|
||||
return(0);
|
||||
}
|
||||
host = ipstr;
|
||||
}
|
||||
|
||||
listen_port = 0;
|
||||
if(portbind)
|
||||
listen_port = LISTEN_PORT;
|
||||
|
||||
listener = libssh2_channel_forward_listen_ex(session, host, listen_port, &listen_port, 2);
|
||||
if(!listener)
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "Listen failed %s: %s\n", paramstr, errmsg);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
outbound = libssh2_channel_direct_tcpip(session, auth.hostname, listen_port);
|
||||
if(!outbound)
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "Outbound channel setup failed %s: %s\n", paramstr, errmsg);
|
||||
|
||||
libssh2_channel_forward_cancel(listener);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
inbound = libssh2_channel_forward_accept(listener);
|
||||
if(!inbound)
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "Forwarding channel accept failed %s: %s\n", paramstr, errmsg);
|
||||
|
||||
libssh2_channel_free(outbound);
|
||||
libssh2_channel_forward_cancel(listener);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
sendbuf = malloc(TESTBUF_SIZE);
|
||||
if(!sendbuf)
|
||||
{
|
||||
log_line(ERROR, "sendbuf malloc failed\n");
|
||||
|
||||
libssh2_channel_free(inbound);
|
||||
libssh2_channel_free(outbound);
|
||||
libssh2_channel_forward_cancel(listener);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
for(i = 0; i < TESTBUF_SIZE; i++)
|
||||
sendbuf[i] = (char) random;
|
||||
|
||||
res = libssh2_channel_write(outbound, sendbuf, TESTBUF_SIZE);
|
||||
if(res != TESTBUF_SIZE)
|
||||
{
|
||||
if(res == -1)
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
else
|
||||
errmsg = NULL;
|
||||
log_line(ERROR, "Unable to send %d bytes across tunnel %s%s%s\n",
|
||||
TESTBUF_SIZE, paramstr, errmsg ? ": " : "", errmsg ? errmsg : "");
|
||||
|
||||
free(sendbuf);
|
||||
libssh2_channel_free(inbound);
|
||||
libssh2_channel_free(outbound);
|
||||
libssh2_channel_forward_cancel(listener);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
recvbuf = malloc(TESTBUF_SIZE);
|
||||
if(!recvbuf)
|
||||
{
|
||||
log_line(ERROR, "recvbuf malloc failed\n");
|
||||
|
||||
free(sendbuf);
|
||||
libssh2_channel_free(inbound);
|
||||
libssh2_channel_free(outbound);
|
||||
libssh2_channel_forward_cancel(listener);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
res = libssh2_channel_read(inbound, recvbuf, TESTBUF_SIZE);
|
||||
if(res != TESTBUF_SIZE)
|
||||
{
|
||||
if(res == -1)
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
else
|
||||
errmsg = NULL;
|
||||
log_line(ERROR, "Unable to receive %d bytes across tunnel %s%s%s\n",
|
||||
TESTBUF_SIZE, paramstr, errmsg ? ": " : "", errmsg ? errmsg : "");
|
||||
|
||||
free(sendbuf);
|
||||
free(recvbuf);
|
||||
libssh2_channel_free(inbound);
|
||||
libssh2_channel_free(outbound);
|
||||
libssh2_channel_forward_cancel(listener);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
res = 1;
|
||||
for(i = 0; i < TESTBUF_SIZE; i++)
|
||||
{
|
||||
if(recvbuf[i] != sendbuf[i])
|
||||
{
|
||||
log_line(ERROR, "Received data did not match sent data %s\n", paramstr);
|
||||
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(sendbuf);
|
||||
free(recvbuf);
|
||||
libssh2_channel_free(inbound);
|
||||
libssh2_channel_free(outbound);
|
||||
libssh2_channel_forward_cancel(listener);
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
|
||||
static void all_forward(void)
|
||||
{
|
||||
LIBSSH2_SESSION *session;
|
||||
int sock, res, size;
|
||||
char *errmsg;
|
||||
|
||||
sock = new_socket();
|
||||
if(sock == -1)
|
||||
{
|
||||
log_line(ERROR, "Unable to open a socket\n");
|
||||
return;
|
||||
}
|
||||
|
||||
session = libssh2_session_init();
|
||||
|
||||
res = libssh2_session_startup(session, sock);
|
||||
if(res)
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "Session startup failed: %s\n", errmsg);
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
if(libssh2_userauth_password(session, auth.username, auth.password))
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "Authentication failed%s%s\n", errmsg[0] ? ": " : "", errmsg);
|
||||
libssh2_session_disconnect(session, "All done.");
|
||||
libssh2_session_free(session);
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
increase_progress();
|
||||
if(loopback(session, 1, 1))
|
||||
step_successful();
|
||||
|
||||
increase_progress();
|
||||
if(loopback(session, 1, 0))
|
||||
step_successful();
|
||||
|
||||
increase_progress();
|
||||
if(loopback(session, 0, 1))
|
||||
step_successful();
|
||||
|
||||
increase_progress();
|
||||
if(loopback(session, 0, 0))
|
||||
step_successful();
|
||||
|
||||
libssh2_session_disconnect(session, "All done.");
|
||||
libssh2_session_free(session);
|
||||
close(sock);
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void runtest_forward(void)
|
||||
{
|
||||
|
||||
init_test("TCP port forwarding/tunneling", 4);
|
||||
|
||||
all_forward();
|
||||
|
||||
}
|
102
test/libssh2-test.h
Обычный файл
102
test/libssh2-test.h
Обычный файл
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* prototest.h
|
||||
*
|
||||
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names
|
||||
* of any other contributors may be used to endorse or
|
||||
* promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LIBSSH2_TEST_H
|
||||
#define LIBSSH2_TEST_H 1
|
||||
|
||||
#define MAX_LOGLINE_LEN 256
|
||||
|
||||
|
||||
void log_line(int priority, char *format, ...);
|
||||
void init_test(char *msg, int num_items);
|
||||
void increase_progress(void);
|
||||
void step_successful(void);
|
||||
void output_testresults(void);
|
||||
int new_socket(void);
|
||||
void runtest_methods(void);
|
||||
void runtest_auth(void);
|
||||
void runtest_forward(void);
|
||||
|
||||
|
||||
|
||||
struct authdefs {
|
||||
char *hostname;
|
||||
char *port;
|
||||
char *username;
|
||||
char *password;
|
||||
char *privkey;
|
||||
char *pubkey;
|
||||
char *passphrase;
|
||||
};
|
||||
|
||||
struct methodlist {
|
||||
int method_type;
|
||||
char *description;
|
||||
char **list;
|
||||
int cursor;
|
||||
int done;
|
||||
};
|
||||
|
||||
struct logentry {
|
||||
int priority;
|
||||
char *logline;
|
||||
struct logentry *next;
|
||||
};
|
||||
|
||||
struct logresults {
|
||||
char *description;
|
||||
int num_steps;
|
||||
int success_steps;
|
||||
int progress;
|
||||
struct logentry *log;
|
||||
struct logresults *next;
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
ERROR,
|
||||
WARNING,
|
||||
NORMAL,
|
||||
DEBUG
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
0
test/libssh2.h
Обычный файл
0
test/libssh2.h
Обычный файл
174
test/main.c
Обычный файл
174
test/main.c
Обычный файл
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* main.c -- ssh2 protocol compliance tester for libssh2
|
||||
*
|
||||
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names
|
||||
* of any other contributors may be used to endorse or
|
||||
* promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <wordexp.h>
|
||||
|
||||
#include <libssh2.h>
|
||||
#include "libssh2-test.h"
|
||||
|
||||
struct authdefs auth;
|
||||
char *progress_message;
|
||||
int progress, progress_max;
|
||||
struct addrinfo *hostai = NULL, *cur_ai = NULL;
|
||||
|
||||
extern struct logresults *testlogs;
|
||||
extern struct logentry *logfile;
|
||||
|
||||
|
||||
|
||||
void cleanup(void)
|
||||
{
|
||||
struct logresults *test, *nexttest;
|
||||
struct logentry *logfile, *nextlog;
|
||||
|
||||
if(hostai)
|
||||
freeaddrinfo(hostai);
|
||||
|
||||
test = testlogs;
|
||||
while(test)
|
||||
{
|
||||
logfile = test->log;
|
||||
while(logfile)
|
||||
{
|
||||
nextlog = logfile->next;
|
||||
free(logfile->logline);
|
||||
free(logfile);
|
||||
|
||||
logfile = nextlog;
|
||||
}
|
||||
nexttest = test->next;
|
||||
free(test);
|
||||
|
||||
test = nexttest;
|
||||
}
|
||||
|
||||
free(auth.hostname);
|
||||
free(auth.port);
|
||||
free(auth.username);
|
||||
free(auth.password);
|
||||
free(auth.privkey);
|
||||
free(auth.pubkey);
|
||||
free(auth.passphrase);
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *get_interactive(char *prompt, int size, char *default_value)
|
||||
{
|
||||
char *str;
|
||||
|
||||
if( !(str = malloc(size)) )
|
||||
{
|
||||
log_line(ERROR, "unable to malloc %d bytes for %s\n", size, prompt);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
printf("%s [%s]: ", prompt, default_value);
|
||||
fgets(str, size, stdin);
|
||||
if(str[strlen(str)-1] == '\n')
|
||||
str[strlen(str)-1] = 0;
|
||||
if(!str[0])
|
||||
strncpy(str, default_value, size);
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
|
||||
char *resolve_tilde(char *path)
|
||||
{
|
||||
wordexp_t we;
|
||||
|
||||
if( (wordexp(path, &we, 0)) == 0 && we.we_wordc == 1)
|
||||
{
|
||||
free(path);
|
||||
path = strdup(we.we_wordv[0]);
|
||||
wordfree(&we);
|
||||
}
|
||||
|
||||
return(path);
|
||||
}
|
||||
|
||||
|
||||
void get_auth(void)
|
||||
{
|
||||
|
||||
auth.hostname = get_interactive("hostname", 64, "localhost");
|
||||
auth.port = get_interactive("port", 6, "22");
|
||||
// auth.username = get_interactive("username", 20, getenv("USER"));
|
||||
// auth.password = get_interactive("password", 20, "");
|
||||
auth.username = get_interactive("username", 20, "bert2");
|
||||
auth.password = get_interactive("password", 20, "blinko");
|
||||
|
||||
auth.privkey = resolve_tilde(get_interactive("private key filename", 128, "~/.ssh/id_dsa"));
|
||||
auth.pubkey = resolve_tilde(get_interactive("public key filename", 128, "~/.ssh/id_dsa.pub"));
|
||||
auth.passphrase = get_interactive("passphrase", 256, "");
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
get_auth();
|
||||
if(!strlen(auth.username) || !strlen(auth.password))
|
||||
{
|
||||
printf("Not enough authentication info to continue.\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
runtest_methods();
|
||||
runtest_auth();
|
||||
runtest_forward();
|
||||
|
||||
output_testresults();
|
||||
|
||||
cleanup();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
219
test/methods.c
Обычный файл
219
test/methods.c
Обычный файл
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* methods.c -- test all available key exchange, hostkey, encryption, mac and compression methods
|
||||
*
|
||||
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names
|
||||
* of any other contributors may be used to endorse or
|
||||
* promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libssh2.h>
|
||||
#include "libssh2-test.h"
|
||||
|
||||
extern struct authdefs auth;
|
||||
|
||||
|
||||
static char *kex_methods[] = {
|
||||
"diffie-hellman-group1-sha1",
|
||||
"diffie-hellman-group14-sha1",
|
||||
"diffie-hellman-group-exchange-sha1",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *hostkey_methods[] = {
|
||||
"ssh-dss",
|
||||
"ssh-rsa",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *crypt_methods[] = {
|
||||
"aes256-cbc",
|
||||
"aes192-cbc",
|
||||
"aes128-cbc",
|
||||
"blowfish-cbc",
|
||||
"arcfour",
|
||||
"cast128-cbc",
|
||||
"3des-cbc",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *mac_methods[] = {
|
||||
"hmac-sha1",
|
||||
"hmac-sha1-96",
|
||||
"hmac-md5",
|
||||
"hmac-md5-96",
|
||||
"hmac-ripemd160",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *compression_methods[] = {
|
||||
"zlib",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static struct methodlist methods[] = {
|
||||
{ LIBSSH2_METHOD_KEX, "kex", kex_methods, 0, 0 },
|
||||
{ LIBSSH2_METHOD_HOSTKEY, "hostkey", hostkey_methods, 0, 0 },
|
||||
{ LIBSSH2_METHOD_CRYPT_CS, "crypt (cs)", crypt_methods, 0, 0 },
|
||||
{ LIBSSH2_METHOD_CRYPT_SC, "crypt (sc)", crypt_methods, 0, 0 },
|
||||
{ LIBSSH2_METHOD_MAC_CS, "MAC (cs)", mac_methods, 0, 0 },
|
||||
{ LIBSSH2_METHOD_MAC_SC, "MAC (sc)", mac_methods, 0, 0 },
|
||||
{ LIBSSH2_METHOD_COMP_CS, "compression (cs)", compression_methods, 0, 0 },
|
||||
{ LIBSSH2_METHOD_COMP_SC, "compression (sc)", compression_methods, 0, 0 },
|
||||
{ 0, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
static void dump_methods(LIBSSH2_SESSION *session)
|
||||
{
|
||||
|
||||
printf(" Key exchange methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_KEX));
|
||||
printf(" Hostkey methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_HOSTKEY));
|
||||
printf(" Crypt C->S methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_CRYPT_CS));
|
||||
printf(" Crypt S->C methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_CRYPT_SC));
|
||||
printf(" MAC C->S methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_MAC_CS));
|
||||
printf(" MAC S->C methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_MAC_SC));
|
||||
printf("Compression C->S methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_COMP_CS));
|
||||
printf("Compression S->C methods: %s\n", libssh2_session_methods(session, LIBSSH2_METHOD_COMP_SC));
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static void cycle_methods(void)
|
||||
{
|
||||
LIBSSH2_SESSION *session;
|
||||
int sock, size, methods_done, i, res;
|
||||
struct methodlist *method;
|
||||
char methodstring[256], *errmsg;
|
||||
|
||||
while(1)
|
||||
{
|
||||
increase_progress();
|
||||
sock = new_socket();
|
||||
if(sock == -1)
|
||||
{
|
||||
log_line(ERROR, "new_socket() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
session = libssh2_session_init();
|
||||
|
||||
i = 0;
|
||||
methodstring[0] = '\0';
|
||||
while(methods[i].description)
|
||||
{
|
||||
method = &methods[i];
|
||||
strncat(methodstring, method->list[method->cursor], 256);
|
||||
strncat(methodstring, " ", 256);
|
||||
res = libssh2_session_method_pref(session, method->method_type, method->list[method->cursor]);
|
||||
if(res != 0)
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "%s method set to '%s' failed: %s\n",
|
||||
method->description, method->list[method->cursor], errmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
res = libssh2_session_startup(session, sock);
|
||||
if(res == 0)
|
||||
{
|
||||
if(libssh2_userauth_password(session, auth.username, auth.password))
|
||||
{
|
||||
log_line(ERROR, "Authentication failed\n");
|
||||
}
|
||||
else
|
||||
step_successful();
|
||||
}
|
||||
else
|
||||
{
|
||||
libssh2_session_last_error(session, &errmsg, &size, 0);
|
||||
log_line(ERROR, "session startup with methods [ %s] failed: %s\n", methodstring, errmsg);
|
||||
}
|
||||
|
||||
libssh2_session_disconnect(session, "All done.");
|
||||
libssh2_session_free(session);
|
||||
close(sock);
|
||||
|
||||
/* increment method cursors */
|
||||
i = 0;
|
||||
methods_done = 0;
|
||||
while( (method = &methods[i++]) && method->description )
|
||||
{
|
||||
if(!method->list[++method->cursor])
|
||||
{
|
||||
method->done = 1;
|
||||
method->cursor = 0;
|
||||
}
|
||||
|
||||
methods_done += method->done;
|
||||
}
|
||||
if(--i == methods_done)
|
||||
break;
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void runtest_methods(void)
|
||||
{
|
||||
struct methodlist *method;
|
||||
int i, j, max;
|
||||
|
||||
max = 0;
|
||||
for(i = 0; methods[i].description; i++)
|
||||
{
|
||||
method = &methods[i];
|
||||
for(j = 0; method->list[j]; j++)
|
||||
;
|
||||
if(j > max)
|
||||
max = j;
|
||||
}
|
||||
|
||||
init_test("kex/hostkey/crypt/max/compression methods", max);
|
||||
|
||||
cycle_methods();
|
||||
|
||||
}
|
||||
|
222
test/util.c
Обычный файл
222
test/util.c
Обычный файл
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* util.c
|
||||
*
|
||||
* Copyright (C) 2005 Bert Vermeulen <bert@biot.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names
|
||||
* of any other contributors may be used to endorse or
|
||||
* promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libssh2.h>
|
||||
#include "libssh2-test.h"
|
||||
|
||||
|
||||
extern struct addrinfo *hostai, *cur_ai;
|
||||
struct logresults *testlogs = NULL, *cur_testlog;
|
||||
struct logentry *logfile = NULL, *cur_logentry;
|
||||
|
||||
extern struct authdefs auth;
|
||||
extern char *progress_message;
|
||||
extern int progress, progress_max;
|
||||
|
||||
|
||||
struct loglevel {
|
||||
int priority;
|
||||
char *descr;
|
||||
} loglevels[] = {
|
||||
{ ERROR, "ERROR" },
|
||||
{ WARNING, "WARNING" },
|
||||
{ NORMAL, "NORMAL" },
|
||||
{ DEBUG, "DEBUG" }
|
||||
};
|
||||
|
||||
|
||||
|
||||
void log_line(int priority, char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
struct logentry *entry;
|
||||
char line[MAX_LOGLINE_LEN];
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(line, MAX_LOGLINE_LEN, format, args);
|
||||
va_end(args);
|
||||
|
||||
entry = malloc(sizeof(struct logentry));
|
||||
entry->priority = priority;
|
||||
entry->logline = malloc(strlen(line)+1);
|
||||
strcpy(entry->logline, line);
|
||||
entry->next = NULL;
|
||||
|
||||
if(!cur_testlog->log)
|
||||
cur_testlog->log = entry;
|
||||
else
|
||||
cur_logentry->next = entry;
|
||||
|
||||
cur_logentry = entry;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void init_test(char *msg, int num_items)
|
||||
{
|
||||
struct logresults *newtest;
|
||||
|
||||
newtest = malloc(sizeof(struct logresults));
|
||||
newtest->description = msg;
|
||||
newtest->num_steps = num_items;
|
||||
newtest->success_steps = 0;
|
||||
newtest->progress = 0;
|
||||
newtest->log = NULL;
|
||||
newtest->next = NULL;
|
||||
|
||||
if(!testlogs)
|
||||
testlogs = newtest;
|
||||
else
|
||||
cur_testlog->next = newtest;
|
||||
|
||||
cur_testlog = newtest;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void increase_progress(void)
|
||||
{
|
||||
|
||||
cur_testlog->progress++;
|
||||
|
||||
printf("Testing %s... %3d/%d\r", cur_testlog->description, cur_testlog->progress, cur_testlog->num_steps);
|
||||
fflush(stdout);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void step_successful(void)
|
||||
{
|
||||
|
||||
cur_testlog->success_steps++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void output_testresults(void)
|
||||
{
|
||||
struct logresults *test;
|
||||
struct logentry *logfile;
|
||||
int total_steps, total_success;
|
||||
|
||||
printf("\nTest results\n============\n");
|
||||
|
||||
total_steps = 0;
|
||||
total_success = 0;
|
||||
test = testlogs;
|
||||
while(test)
|
||||
{
|
||||
total_steps += test->num_steps;
|
||||
total_success += test->success_steps;
|
||||
printf("Test: %s (%d/%d)\n", test->description, test->success_steps, test->num_steps);
|
||||
logfile = test->log;
|
||||
while(logfile)
|
||||
{
|
||||
printf(" %s", logfile->logline);
|
||||
logfile = logfile->next;
|
||||
}
|
||||
|
||||
test = test->next;
|
||||
}
|
||||
|
||||
printf("%d/%d steps successful\n", total_success, total_steps);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int new_socket(void)
|
||||
{
|
||||
int sock, res;
|
||||
struct addrinfo hints, *ai;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = PF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if(!hostai)
|
||||
{
|
||||
res = getaddrinfo(auth.hostname, auth.port, &hints, &hostai);
|
||||
if(res)
|
||||
{
|
||||
printf("unable to resolve %s: %s\n", auth.hostname, gai_strerror(res));
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
sock = 0;
|
||||
ai = hostai;
|
||||
while(ai)
|
||||
{
|
||||
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if(sock > 0)
|
||||
{
|
||||
res = connect(sock, ai->ai_addr, ai->ai_addrlen);
|
||||
if(res == 0)
|
||||
break;
|
||||
|
||||
close(sock);
|
||||
sock = 0;
|
||||
}
|
||||
ai = ai->ai_next;
|
||||
}
|
||||
|
||||
if(!sock)
|
||||
{
|
||||
printf("unable to connect: %s\n", strerror(errno));
|
||||
close(sock);
|
||||
sock = -1;
|
||||
}
|
||||
|
||||
cur_ai = ai;
|
||||
|
||||
return(sock);
|
||||
}
|
||||
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user