Hey,
I just wanted to ask if there is any update.
Thanks!
You are not logged in. Please login or register.
Please post questions or comments you have about wolfSSL products here. It is helpful to be as descriptive as possible when asking your questions.
ReferenceswolfSSL - Embedded SSL Library → Posts by testwolverinebagel
Pages 1
Hey,
I just wanted to ask if there is any update.
Thanks!
Hey John,
I prepared a minimal example which shows the behavior I described earlier.
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <wolfssh/ssh.h>
#include <errno.h>
#include <sys/epoll.h>
#define SSH_SERVER_ADDR "192.168.188.69"
#define SSH_USER "myUsername"
#define SSH_PASS "myPassword"
int sock = 0;
WOLFSSH_CTX* ctx = NULL;
WOLFSSH* ssh = NULL;
struct epoll_event events[5];
enum states
{
CONNECTING,
LOGIN,
DONE
};
int currState = CONNECTING;
int setup_socket();
int connect_sock();
int get_socket_error();
int init_ssh();
int authCb(byte authType, WS_UserAuthData* authData, void* userData);
int login();
int main()
{
// create nonblocking socket
if(setup_socket() < 0)
{
perror("Setting up socket failed");
if(sock > 0)
close(sock);
exit(0);
}
// call non-blocking connect
if(connect_sock() < 0)
{
perror("Connecting failed");
close(sock);
exit(0);
}
// initialize wolfssh
if(init_ssh() < 0)
{
printf("ssh error: %d", wolfSSH_get_error(ssh));
if(ctx)
wolfSSH_CTX_free(ctx);
if(ssh)
wolfSSH_free(ssh);
close(sock);
exit(0);
}
// setup epoll
int epoll = epoll_create(1);
struct epoll_event event;
event.events = EPOLLIN | EPOLLOUT;
event.data.fd = sock;
if(epoll_ctl(epoll, EPOLL_CTL_ADD, sock, &event) < 0)
{
perror("epoll_ctl");
wolfSSH_CTX_free(ctx);
wolfSSH_free(ssh);
close(sock);
exit(0);
}
int nfds;
int notDone = 1;
while(notDone)
{
nfds = epoll_wait(epoll, events, sizeof(events), 3);
if(nfds == -1)
{
perror("epoll_wait");
break;
}
int ret;
for(int n = 0; n < nfds; ++n)
{
if(events[n].data.fd == sock && (events[n].events & (EPOLLIN | EPOLLOUT)))
{
switch(currState)
{
case CONNECTING:
ret = get_socket_error();
if(ret != 0 && ret != EINPROGRESS)
{
printf("Failed to connect, %s\n", strerror(ret));
currState = DONE;
}
else if(ret != EINPROGRESS)
{
printf("Connected\n");
currState = LOGIN;
}
else
{
currState = CONNECTING;
}
break;
case LOGIN:
ret = login();
if(ret == WS_SUCCESS)
{
printf("Login success");
currState = DONE;
}
else if(ret == WS_WANT_READ || ret == WS_WANT_WRITE)
{
// repeat calling login()
currState = LOGIN;
}
else
{
printf("Login failed, code %d", wolfSSH_get_error(ssh));
currState = DONE;
}
break;
case DONE:
notDone = 0;
break;
}
}
}
}
wolfSSH_shutdown(ssh);
wolfSSH_CTX_free(ctx);
wolfSSH_free(ssh);
close(sock);
return 0;
}
int setup_socket()
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
return -1;
// set non-blocking
if(fcntl(sock, F_SETFL, O_NONBLOCK | fcntl(sock, F_GETFL, 0)) < 0)
return -1;
return 0;
}
int connect_sock()
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(22);
inet_pton(AF_INET, SSH_SERVER_ADDR, &(addr.sin_addr));
if(connect(sock, (struct sockaddr*)(&addr), sizeof(addr)) < 0 && errno != EINPROGRESS)
return -1;
return 0;
}
int get_socket_error()
{
int err;
socklen_t size = sizeof(err);
int ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &size);
if(ret < 0)
return ret;
return err;
}
int init_ssh()
{
wolfSSH_Init();
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
if(!ctx)
return -1;
ssh = wolfSSH_new(ctx);
if(!ssh)
return -1;
int ret = wolfSSH_set_fd(ssh, sock);
if(ret != WS_SUCCESS)
return -1;
// set channel to shell
ret = wolfSSH_SetChannelType(ssh, WOLFSSH_SESSION_SHELL, NULL, 0);
if(ret != WS_SUCCESS)
return -1;
// set auth callback
wolfSSH_SetUserAuth(ctx, authCb);
// set callback data
wolfSSH_SetUserAuthCtx(ssh, NULL);
// set username
wolfSSH_SetUsername(ssh, SSH_USER);
return 0;
}
int authCb(byte authType, WS_UserAuthData* authData, void* userData)
{
if(authType == WOLFSSH_USERAUTH_PASSWORD)
{
authData->sf.password.password = (byte*)(SSH_PASS);
authData->sf.password.passwordSz = strlen(SSH_PASS);
}
else
{
return WOLFSSH_USERAUTH_REJECTED;
}
return WOLFSSH_USERAUTH_SUCCESS;
}
int login()
{
int ret = wolfSSH_connect(ssh);
// Here comes th odd part. If you remove the call to usleep(),
// WS_OVERFLOW_E is returned by wolfssh.
// With usleep it works perfectly.
usleep(10000);
if(ret != WS_SUCCESS)
{
return wolfSSH_get_error(ssh);
}
return WS_SUCCESS;
}
Thank you very much!
Hi Eric,
Thanks for your reply. I am compiling for x86 & x64 architectures, but I am using uclibc. As I said it actually works if I add a call to sleep() after wolfSSH_connect() and sometimes if I enable the wolfssh debug log.
Hey,
I'm having trouble figuring out how to use wolfSSH_connect() with epoll. wolfSSH_connect() is called again on every EPOLLIN/EPOLLOUT event if the previous call to the function returned WS_WANT_READ/WS_WANT_WRITE. But I always get an WS_OVERFLOW_E error after the server sent his DH Key Exchange Reply.
It works if I add a delay of about 100ms after (not before!) the call to wolfSSH_connect(), but that somehow defeats the purpose of using non-blocking sockets.
Am I using the function in a wrong way?
Pages 1
wolfSSL - Embedded SSL Library → Posts by testwolverinebagel
Powered by PunBB, supported by Informer Technologies, Inc.
Generated in 0.017 seconds (96% PHP - 4% DB) with 4 queries