[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Server woes - Bad packet length, corrupted MAC on input
[Thread Prev] | [Thread Next]
- Subject: Re: Server woes - Bad packet length, corrupted MAC on input
- From: "jeetu.golani@xxxxxxxxx" <jeetu.golani@xxxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Sat, 22 Oct 2011 14:20:11 +0500
- To: libssh@xxxxxxxxxx
Hi Aris, I'm attaching my proof of concept server code as.....ebpsshd-singlesession.c has compile instructions at the beginning of the code. You will also need to generate a key.h file that holds the public key of the user who will be connecting to this server - this is tempoarary since as of now I'm not reading this info from an authorized_keys or something similar. Just create a key.h file in the same directory and put something like : #define MY_PUB_KEY "[YOUR PUBLIC KEY WITHIN THESE QUOTES]" Also as of now ebpsshd-singlesession listens in on port 2000. So ssh should connect to that port. I also have a libssh-project-wrapper script that allows me to try this out without needing to install the libssh i've built. It basically has the content: #!/bin/sh export LD_LIBRARY_PATH=/home/jeetu/utils/libssh/libssh-project/build/src:/home/jeetu/utils/libssh/libssh-project/build/src/threads ./$1 I have been testing this code with simple examples like xeyes and xcalc. For some reason xcalc shows the problem much sooner than with xeyes, maybe because of the volume of data being transmitted to and fro? This is proof of concept code with a lot of fiddling with buffer sizes as I have been trying to study if any of that makes an impact however please point out any way you think this can be improved on :) I'm sorry to drop this in your lap especially if it turns out it was some server side code issue, however I completely appreciate your help on this. I would like to squash this bug regardless of where it lies i.e. in my code or libssh, unfortunately my understanding of libssh and the ssh protocol is a little limited. However I do not want to put all of this load completely in your lap and if you share your thoughts and there's something you would like me to look into then please let me know. Thanks, Jeetu ebrain.in | Beehive Computing Discover and run software from any device around you - an open source (GPL) project. On Fri, Oct 21, 2011 at 11:22 PM, jeetu.golani@xxxxxxxxx <jeetu.golani@xxxxxxxxx> wrote: > Hi Aris, > >> I think I'll need a proof-of-concept code to debug this. Would you mind >> sharing your code, or it's not possible (too much integration with >> existing code). > > No problem at all :) The code is an independent unit as of now since I > wanted to make it work before I integrate it within my open source > project (eBrainPool) > > I'll mail this out to you tomm (not on the machine with the code right now :) ) > > Thanks so much for looking into this.....truly appreciate it :) > > Bye for now > > > On Fri, Oct 21, 2011 at 7:26 PM, Aris Adamantiadis <aris@xxxxxxxxxxxx> wrote: >> Hi Jeetu, >> >> By seeing your logs, I understand this: >> Both side have a hmac error. The openssh client sees it first, sends a >> disconnect (that works), then there's the error in the libssh log. >> >> I think I'll need a proof-of-concept code to debug this. Would you mind >> sharing your code, or it's not possible (too much integration with >> existing code). >> >> If so, do you think I can reproduce the problem by "fixing" samplesshd >> to make new X11 channels connection connect to the local X11 unix socket ? >> >> Thanks. >> >> Aris >> >> >> Le 18/10/11 20:34, jeetu.golani@xxxxxxxxx a écrit : >>>> This is not a problem and shouldn't cause invalid MAC errors. I'm on >>>> travel so I'll look at the log when i'm back. >>> >>> Thanks so much Aris :) >>> >>> On Tue, Oct 18, 2011 at 5:52 PM, Aris Adamantiadis <aris@xxxxxxxxxxxx> wrote: >>>> Hi, >>>> >>>> This is not a problem and shouldn't cause invalid MAC errors. I'm on >>>> travel so I'll look at the log when i'm back. >>>> >>>> Aris >>>> >>>> Le 18/10/11 12:30, u@xxxxxxxxxxxxx a écrit : >>>>> Hi all, >>>>> >>>>> debug3: Incorrect RSA1 identifier >>>>> debug3: Could not load "/home/jeetu/.ssh/id_rsa" as a RSA1 public key >>>>> debug2: key_type_from_name: unknown key type '-----BEGIN' >>>>> >>>>> >>>>> On Tue, Oct 18, 2011 at 03:22:08PM +0500, jeetu.golani@xxxxxxxxx wrote: >>>>>> Hi Aris, >>>>>> >>>>>> I've attached a log of the libssh server >>>>>> (log-1-ebpsshd-singlesession-18102011.txt) and the OpenSSH client >>>>>> (log-ssh-1-18102011.txt). >>>>> >>>>> Greetings >>>>> -- >>>>> Stefan Kuttler ==*== nc.netbeisser.de >>>>> >>>> >>>> >>> >> >> >
/* ebpsshd-singlesession.c compile: gcc -g -Wall -Wstrict-prototypes -O0 -o ebpsshd-singlesession -I/home/jeetu/utils/libssh/libssh-project/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include/ ebpsshd-singlesession.c -L/home/jeetu/utils/libssh/libssh-project/build/src -lssh -L/home/jeetu/utils/libssh/libssh-project/build/src/threads -lssh_threads -lglib-2.0 -lgthread-2.0 */ #include <libssh/libssh.h> #include <libssh/server.h> #include <libssh/callbacks.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <glib.h> #include <stdlib.h> #include <errno.h> #include <poll.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include "key.h" //jeetu - temporary hardcoded key #ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER #else #define KEYS_FOLDER "/home/jeetu/tmp/" //jeetu - temporary #endif #endif #define MAX_X11_AUTH_PROTO_STR_SZ 18 #define MAX_X11_AUTH_COOKIE_STR_SZ 50 //jeetu - all hardcoded defines; should probably figure out how these values came to be in the orig openssh code #define MAX_DISPLAYS 1000 #define NI_MAXSERV 32 #define NUM_SOCKS 10 #define SSH_LISTEN_BACKLOG 128 static int copy_chan_to_fd(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata); static void chan_close(ssh_session session, ssh_channel channel, void *userdata); static int copy_fd_to_chan(socket_t fd, int revents, void *userdata); /* struct ssh_channel_callbacks_struct cb = { .channel_data_function = copy_chan_to_fd, .channel_eof_function = chan_close, .channel_close_function = chan_close, .userdata = NULL }; */ typedef struct x11_session_struct { char *x11_auth_cookie; char *x11_auth_protocol; int screen_number; int single_connection; unsigned int display_number; } x11_session; typedef struct { ssh_session session; int *sockets; } WaitThreadData; static WaitThreadData * thread_data_new (void); int authenticate_user(ssh_session session); int pubkey_auth(char *pk64); int server_loop(ssh_session session); int session_x11_req(ssh_session session,ssh_message message,x11_session* x11session); int session_setup_x11fwd(ssh_session session,x11_session* x11session); int x11_create_display_inet(ssh_session session,unsigned int *display_numberp, int *sockets); static gpointer wait_for_something(gpointer user_data); static gpointer server_thread(gpointer session_data); int exec_command(const char *command,x11_session* x11session); //struct x11_session_struct x11session; //jeetu - may not need to be global ssh_channel chan=0; ssh_session session; /*static GMutex *mutex_for_copy_fd_to_chan = NULL; static GMutex *mutex_for_copy_chan_to_fd = NULL; */ /* Return Values: * 0 - Success * 1 - ssh_bind_listen failed - error listening to socket * 2 - ssh_bind_accept failed - error accepting a connection * 3 - ssh_handle_key_change failed * 4 - authenticate_user failed */ int main(int argc, char **argv) { ssh_bind sshbind; int auth=0; int r; int port = 2000; int verbosity = SSH_LOG_PACKET; int session_count = 0; g_thread_init(NULL); // ssh_threads_set_callbacks(ssh_threads_get_pthread()); if(ssh_init() == -1) { printf("\nError initializing ssh: ssh_init() failed"); exit(1); } sshbind=ssh_bind_new(); session = ssh_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT,&port); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); if(ssh_bind_listen(sshbind)<0) { printf("Error listening to socket: %s\n",ssh_get_error(sshbind)); return 1; } ssh_options_getopt(session,&argc,argv); r=ssh_bind_accept(sshbind,session); if(r==SSH_ERROR) { printf("error accepting a connection : %s\n",ssh_get_error(sshbind)); return 2; } ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity ); if(ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n",ssh_get_error(session)); return 3; } /* public key authentication */ auth = authenticate_user(session); if(!auth) { printf("auth error: %s\n",ssh_get_error(session)); ssh_disconnect(session); return 4; } server_thread(session); /* if(x11session.x11_auth_protocol != NULL) free(x11session.x11_auth_protocol); if(x11session.x11_auth_cookie != NULL) free(x11session.x11_auth_cookie); */ // ssh_disconnect(session[session_count]); ssh_bind_free(sshbind); ssh_finalize(); return 0; } /* returns 1 for OK, 0 for KO */ int authenticate_user(ssh_session session) { ssh_message message; ssh_string pubkey = NULL; char *pk64 = NULL; int signature_state = SSH_PUBLICKEY_STATE_NONE; do { message = ssh_message_get(session); if(!message) return 0; switch(ssh_message_type(message)) { case SSH_REQUEST_AUTH: switch(ssh_message_subtype(message)) { case SSH_AUTH_METHOD_PUBLICKEY: pubkey = publickey_to_string(ssh_message_auth_publickey(message)); pk64 = g_base64_encode((const guchar *)ssh_string_to_char(pubkey), ssh_string_len(pubkey)); signature_state = ssh_message_auth_publickey_state(message); if(signature_state == SSH_PUBLICKEY_STATE_NONE) { /* no signature */ ssh_message_auth_reply_pk_ok_simple(message); break; } else if(signature_state != SSH_PUBLICKEY_STATE_VALID) { /* will be rejected later */ } else { /* signature is good at that point */ if(pubkey_auth(pk64)) { /* user is allowed */ ssh_message_auth_reply_success(message, 0); ssh_message_free(message); return 1; } } /* the following is not necessary if we want only pubkey auth */ ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PUBLICKEY); /* reject authentication */ ssh_message_reply_default(message); break; case SSH_AUTH_METHOD_PASSWORD: /* handle password auth if needed */ default: ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PUBLICKEY); ssh_message_reply_default(message); } break; default: ssh_message_reply_default(message); } ssh_message_free(message); }while(1); return 0; } int pubkey_auth(char* pk64) { if(strcmp(pk64,MY_PUB_KEY) == 0) return 1; return 0; } static gpointer server_thread(gpointer session_data) { ssh_message message; int message_subtype = 0; int message_type = 0; int ret = 0; ssh_session session = (ssh_session) session_data; struct ssh_message_struct *msg; x11_session x11session; do { message=ssh_message_get(session); msg = message; if(message) { message_type = ssh_message_type(message); message_subtype = ssh_message_subtype(message); // printf("\nmessage_type = %d subtype = %d",message_type,message_subtype); switch(message_type) { case SSH_REQUEST_CHANNEL_OPEN: if(message_subtype == SSH_CHANNEL_SESSION) { printf("\nSSH_CHANNEL_SESSION"); chan=ssh_message_channel_request_open_reply_accept(message); } break; case SSH_REQUEST_CHANNEL: printf("\nSSH_REQUEST_CHANNEL subtype = %d SSH_CHANNEL_REQUEST_X11 = %d",message_subtype,SSH_CHANNEL_REQUEST_X11); if(message_subtype == SSH_CHANNEL_REQUEST_X11) { printf("\nSSH_CHANNEL_REQUEST_X11"); if(session_x11_req(session,message,&x11session) != 1) { printf("\nsession_x11_req error"); ssh_message_reply_default(message); ssh_disconnect(session); return NULL; } else ssh_message_channel_request_reply_success(message); } if(message_subtype == SSH_CHANNEL_REQUEST_ENV) { printf("\nSSH_CHANNEL_REQUEST_ENV"); ssh_message_channel_request_reply_success(message); } if(message_subtype == SSH_CHANNEL_REQUEST_EXEC) { printf("\nSSH_CHANNEL_REQUEST_EXEC command = %s\n",ssh_message_channel_request_command(message)); ret = exec_command(ssh_message_channel_request_command(message),&x11session); if(ret == 0) { printf("\nserver_loop: unable to exec command\n"); } ssh_message_channel_request_reply_success(message); } break; default: ssh_message_reply_default(message); } ssh_message_free(message); } } while(1); // return 1; return NULL; } int session_x11_req(ssh_session session,ssh_message message,x11_session* x11session) { int ret = 1; FILE* fpxauth; char xauth_path[] = "/usr/bin/xauth"; char strxauth_exec[200]; //jeetu - buffer size sufficient?; xauth path name may be larger; ideally not fixed x11session->x11_auth_protocol = NULL; x11session->x11_auth_cookie = NULL; x11session->x11_auth_protocol = malloc(MAX_X11_AUTH_PROTO_STR_SZ+2); strncpy(x11session->x11_auth_protocol,ssh_message_channel_request_x11_auth_protocol(message),MAX_X11_AUTH_PROTO_STR_SZ+1); x11session->x11_auth_protocol[MAX_X11_AUTH_PROTO_STR_SZ] = '\0'; if(strncmp(x11session->x11_auth_protocol,"MIT-MAGIC-COOKIE-1",MAX_X11_AUTH_PROTO_STR_SZ+1) == 0) { x11session->x11_auth_cookie = malloc(MAX_X11_AUTH_COOKIE_STR_SZ+2); strncpy(x11session->x11_auth_cookie,ssh_message_channel_request_x11_auth_cookie(message),MAX_X11_AUTH_COOKIE_STR_SZ+1); x11session->x11_auth_cookie[MAX_X11_AUTH_COOKIE_STR_SZ] = '\0'; x11session->screen_number = ssh_message_channel_request_x11_screen_number(message); x11session->single_connection = ssh_message_channel_request_x11_single_connection(message); } else return 0; // ret = execl("/usr/bin/xauth","/usr/bin/xauth","add","unix:10.0",x11session.x11_auth_protocol,x11session.x11_auth_cookie,(char *) NULL); ret = session_setup_x11fwd(session,x11session); if(ret == 0) { printf("\nsession_setup_x11fwd failed"); return 0; } printf("\nx11_auth_protocol=%s\nx11_auth_cookie=%s\nscreen_number = %d\nsingle_connection = %d\ndisplay_number = %d\n",x11session->x11_auth_protocol,x11session->x11_auth_cookie,x11session->screen_number,x11session->single_connection,x11session->display_number); snprintf(strxauth_exec,199,"%s remove :%d",xauth_path,x11session->display_number); printf("\nstrxauth_exec = %s",strxauth_exec); fpxauth = popen(strxauth_exec,"r"); if(fpxauth == NULL) return 0; pclose(fpxauth); strxauth_exec[0] = '\0'; snprintf(strxauth_exec,199,"%s add unix:%d %s %s",xauth_path,x11session->display_number,x11session->x11_auth_protocol,x11session->x11_auth_cookie); // snprintf(strxauth_exec,199,"%s add unix:10 %s %s",xauth_path,x11session.x11_auth_protocol,x11session.x11_auth_cookie); printf("\nstrxauth_exec = %s",strxauth_exec); fpxauth = popen(strxauth_exec,"r"); if(fpxauth == NULL) return 0; pclose(fpxauth); return ret; } int session_setup_x11fwd(ssh_session session,x11_session* x11session) { int ret = 1; WaitThreadData *waitdata; int *sockets; //jeetu - sufficient array size? sockets = malloc( (sizeof(int) * 10) ); ret = x11_create_display_inet(session,&x11session->display_number,sockets); if(ret == 0) { printf("\nx11_create_display_inet failed"); return 0; } printf("\nsockets[0] = %d",sockets[0]); waitdata = thread_data_new(); //jeetu - memory needs to be freed waitdata->session = session; waitdata->sockets = sockets; g_thread_create(wait_for_something,waitdata,FALSE,NULL); // wait_for_something(waitdata); //free(sockets); return ret; } int x11_create_display_inet(ssh_session session,unsigned int *display_numberp, int *sockets) { int ret = 1; int display_num = 0,sock = 0,num_socks = 0; unsigned int port = 0; struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr,n,socks[NUM_SOCKS]; static int x11_display_offset = 10; //jeetu - temporarily hardcoded here printf("\nx11_create_display_inet: x11_display_offset = %d\n",x11_display_offset); for(display_num = x11_display_offset; display_num < MAX_DISPLAYS; display_num++) { port = 6000 + display_num; hints.ai_family = AF_INET; hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; snprintf(strport, sizeof strport, "%d", port); if((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { printf("\ngetaddrinfo: %s",gai_strerror(gaierr)); return 0; } for(ai = aitop; ai; ai = ai->ai_next) { if(ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; sock = socket(ai->ai_family, ai->ai_socktype,ai->ai_protocol); if(sock < 0) { if((errno != EINVAL) && (errno != EAFNOSUPPORT)) { printf("\nsocket error: %s", strerror(errno)); freeaddrinfo(aitop); return 0; } else { printf("\nx11_create_display_inet: Socket family %d not supported",ai->ai_family); continue; } } if(bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { printf("bind port %d: %s", port, strerror(errno)); close(sock); for(n = 0; n < num_socks; n++) { close(socks[n]); } num_socks = 0; break; } socks[num_socks++] = sock; if(num_socks == NUM_SOCKS) break; } freeaddrinfo(aitop); if(num_socks > 0) break; } if(display_num >= MAX_DISPLAYS) { printf("\nFailed to allocate internet-domain X11 display socket."); return 0; } /* Start listening for connections on the socket. */ for(n = 0; n < num_socks; n++) { sock = socks[n]; *(sockets+n) = sock; if(listen(sock, SSH_LISTEN_BACKLOG) < 0) { printf("\nlisten: %s", strerror(errno)); close(sock); return 0; } } *display_numberp = display_num; x11_display_offset++; return ret; } static gpointer wait_for_something(gpointer user_data) { fd_set infds, testfds; struct timeval tv = { 30, 0 }; int maxfds = 0; int nready; int client_sock, cli_len; struct sockaddr_in cli_addr; ssh_event event; short events; ssh_channel chan_x11=0; WaitThreadData *data; struct ssh_channel_callbacks_struct cb = { .channel_data_function = copy_chan_to_fd, .channel_eof_function = chan_close, .channel_close_function = chan_close, .userdata = NULL }; data = user_data; FD_ZERO(&infds); FD_SET(data->sockets[0], &infds); printf("\ndata->sockets[0] = %d",data->sockets[0]); maxfds = data->sockets[0]; while(1) { testfds = infds; printf("\nwait_for_something: before select"); tv.tv_sec = 15; nready = select(maxfds + 1, &testfds, NULL, NULL, &tv); if(nready == -1) { printf("\nselect error: %s\n",strerror(errno)); } if(nready > 0) { printf("\nwait_for_something: nready > 0"); if(FD_ISSET(data->sockets[0], &testfds)) { printf("\nFD_ISSET\n"); cli_len = sizeof (cli_addr); bzero((char *) &cli_addr, sizeof (cli_addr)); client_sock = accept(data->sockets[0], (struct sockaddr *) &cli_addr, (socklen_t *) &cli_len); printf("\nclient_sock = %d",client_sock); chan_x11 = ssh_channel_new(data->session); // printf("\nchan_x11 session = %x\n",data->session); if(ssh_channel_open_x11(chan_x11,"127.0.0.1",client_sock) == SSH_ERROR) { printf("ssh_channel_open_x11 error : %s\n",ssh_get_error(chan_x11)); return NULL; } else printf("\nssh_channel_open_x11\n"); cb.userdata = &client_sock; ssh_callbacks_init(&cb); ssh_set_channel_callbacks(chan_x11, &cb); events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; event = ssh_event_new(); if(event == NULL) { printf("Couldn't get a event\n"); return NULL; } else printf("\nevent != NULL"); if(ssh_event_add_fd(event, client_sock, events, copy_fd_to_chan, chan_x11) != SSH_OK) { printf("Couldn't add an fd to the event\n"); return NULL; } else printf("\nAdded fd to event"); if(ssh_event_add_session(event, data->session) != SSH_OK) { printf("Couldn't add the session to the event\n"); return NULL; } else printf("\nadded the session to the event\n"); do { ssh_event_dopoll(event, 1000); } while(!ssh_channel_is_closed(chan_x11)); printf("\nssh_channel_open_x11: channel closed\n"); /* ssh_event_remove_fd(event, client_sock); ssh_event_remove_session(event, data->session); ssh_event_free(event);*/ break; } } } printf("\nexiting wait_for_something"); return NULL; } static int copy_fd_to_chan(socket_t fd, int revents, void *userdata) { ssh_channel chan = (ssh_channel)userdata; char buf[40000]; int sz = 0; buf[0] = '\0'; if(!chan) { close(fd); return -1; } if(revents & POLLIN) { sz = read(fd, buf, 39999); if(sz == 0) { printf("\ncopy_fd_to_chan: sz == 0\n"); ssh_channel_close(chan); close(fd); sz = -1; } if(sz > 0) { ssh_channel_write(chan, buf, sz); } } if(revents & POLLHUP) { ssh_channel_close(chan); sz = -1; } return sz; } static int copy_chan_to_fd(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata) { int fd = *(int*)userdata; int sz; (void)session; (void)channel; (void)is_stderr; sz = write(fd, data, len); return sz; } static void chan_close(ssh_session session, ssh_channel channel, void *userdata) { int fd = *(int*)userdata; (void)session; (void)channel; close(fd); } static WaitThreadData * thread_data_new (void) { WaitThreadData *data; data = g_new0 (WaitThreadData, 1); return data; } int exec_command(const char *command,x11_session* x11session) { FILE *fpcmd; char str_exec[200]; //jeetu - buffer size sufficient?; command name may be larger; ideally not fixed printf("\nexec_command: x11session->display_number = %d\n",x11session->display_number); str_exec[0] = '\0'; snprintf(str_exec,199,"%s -display :%d",command,x11session->display_number); fpcmd = popen(str_exec,"r"); if(fpcmd == NULL) return 0; return 1; }
Re: Server woes - Bad packet length, corrupted MAC on input | "jeetu.golani@xxxxxxxxx" <jeetu.golani@xxxxxxxxx> |
Re: Server woes - Bad packet length, corrupted MAC on input | Aris Adamantiadis <aris@xxxxxxxxxxxx> |
Re: Server woes - Bad packet length, corrupted MAC on input | u@xxxxxxxxxxxxx |
Re: Server woes - Bad packet length, corrupted MAC on input | Aris Adamantiadis <aris@xxxxxxxxxxxx> |
Re: Server woes - Bad packet length, corrupted MAC on input | "jeetu.golani@xxxxxxxxx" <jeetu.golani@xxxxxxxxx> |
Re: Server woes - Bad packet length, corrupted MAC on input | Aris Adamantiadis <aris@xxxxxxxxxxxx> |
Re: Server woes - Bad packet length, corrupted MAC on input | "jeetu.golani@xxxxxxxxx" <jeetu.golani@xxxxxxxxx> |