1
1
Этот коммит содержится в:
Aris Adamantiadis 2009-11-16 22:36:31 +01:00
родитель 3e90a11599
Коммит 02aecc1278
6 изменённых файлов: 170 добавлений и 21 удалений

Просмотреть файл

@ -40,6 +40,12 @@ char *user;
char *cmds[MAXCMD]; char *cmds[MAXCMD];
struct termios terminal; struct termios terminal;
#ifdef WITH_PCAP
/* this header file won't be necessary in the future */
#include <libssh/pcap.h>
char *pcap_file=NULL;
#endif
static int auth_callback(const char *prompt, char *buf, size_t len, static int auth_callback(const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata) { int echo, int verify, void *userdata) {
char *answer = NULL; char *answer = NULL;
@ -86,19 +92,27 @@ static void usage(){
" -l user : log in as user\n" " -l user : log in as user\n"
" -p port : connect to port\n" " -p port : connect to port\n"
" -d : use DSS to verify host public key\n" " -d : use DSS to verify host public key\n"
" -r : use RSA to verify host public key\n", " -r : use RSA to verify host public key\n"
#ifdef WITH_PCAP
" -P file : create a pcap debugging file\n"
#endif
,
ssh_version(0)); ssh_version(0));
exit(0); exit(0);
} }
static int opts(int argc, char **argv){ static int opts(int argc, char **argv){
int i; int i;
// for(i=0;i<argc;i++) // for(i=0;i<argc;i++)
// printf("%d : %s\n",i,argv[i]); // printf("%d : %s\n",i,argv[i]);
/* insert your own arguments here */ /* insert your own arguments here */
while((i=getopt(argc,argv,""))!=-1){ while((i=getopt(argc,argv,"P:"))!=-1){
switch(i){ switch(i){
#ifdef WITH_PCAP
case 'P':
pcap_file=optarg;
break;
#endif
default: default:
fprintf(stderr,"unknown option %c\n",optopt); fprintf(stderr,"unknown option %c\n",optopt);
usage(); usage();
@ -446,6 +460,31 @@ static int client(ssh_session session){
return 0; return 0;
} }
#ifdef WITH_PCAP
ssh_pcap_file pcap;
void set_pcap(ssh_session session);
void set_pcap(ssh_session session){
ssh_pcap_context ctx;
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ctx=ssh_pcap_context_new(session);
ssh_pcap_context_set_file(ctx,pcap);
ssh_set_pcap_context(session,ctx);
}
void cleanup_pcap(void);
void cleanup_pcap(){
ssh_pcap_file_free(pcap);
pcap=NULL;
}
#endif
int main(int argc, char **argv){ int main(int argc, char **argv){
ssh_session session; ssh_session session;
@ -461,10 +500,17 @@ int main(int argc, char **argv){
} }
opts(argc,argv); opts(argc,argv);
signal(SIGTERM, do_exit); signal(SIGTERM, do_exit);
#ifdef WITH_PCAP
set_pcap(session);
#endif
client(session); client(session);
ssh_disconnect(session); ssh_disconnect(session);
ssh_free(session); ssh_free(session);
#ifdef WITH_PCAP
cleanup_pcap();
#endif
ssh_finalize(); ssh_finalize();
return 0; return 0;

Просмотреть файл

@ -2,6 +2,7 @@
#define PCAP_H_ #define PCAP_H_
#include "config.h" #include "config.h"
#include "libssh/libssh.h"
#ifdef WITH_PCAP #ifdef WITH_PCAP
typedef struct ssh_pcap_context_struct* ssh_pcap_context; typedef struct ssh_pcap_context_struct* ssh_pcap_context;
@ -10,7 +11,7 @@ typedef struct ssh_pcap_file_struct* ssh_pcap_file;
ssh_pcap_file ssh_pcap_file_new(void); ssh_pcap_file ssh_pcap_file_new(void);
int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename); int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
int ssh_pcap_file_close(ssh_pcap_file pcap); int ssh_pcap_file_close(ssh_pcap_file pcap);
void ssh_pcap_free(ssh_pcap_file pcap); void ssh_pcap_file_free(ssh_pcap_file pcap);
/* to be removed from here after tests */ /* to be removed from here after tests */
int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, u_int32_t original_len); int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, u_int32_t original_len);
@ -25,6 +26,8 @@ void ssh_pcap_context_set_file(ssh_pcap_context, ssh_pcap_file);
int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, void *data, int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, void *data,
u_int32_t len, u_int32_t origlen); u_int32_t len, u_int32_t origlen);
void ssh_set_pcap_context(ssh_session session, ssh_pcap_context pcap);
#endif /* WITH_PCAP */ #endif /* WITH_PCAP */
#endif /* PCAP_H_ */ #endif /* PCAP_H_ */
/* vim: set ts=2 sw=2 et cindent: */ /* vim: set ts=2 sw=2 et cindent: */

Просмотреть файл

@ -23,6 +23,7 @@
#define SESSION_H_ #define SESSION_H_
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/packet.h" #include "libssh/packet.h"
#include "libssh/pcap.h"
typedef struct ssh_kbdint_struct* ssh_kbdint; typedef struct ssh_kbdint_struct* ssh_kbdint;
@ -96,6 +97,9 @@ struct ssh_session_struct {
ssh_callbacks callbacks; /* Callbacks to user functions */ ssh_callbacks callbacks; /* Callbacks to user functions */
/* options */ /* options */
#ifdef WITH_PCAP
ssh_pcap_context pcap_ctx; /* pcap debugging context */
#endif
char *username; char *username;
char *host; char *host;
char *bindaddr; /* TODO: check if needed */ char *bindaddr; /* TODO: check if needed */

Просмотреть файл

@ -66,7 +66,11 @@ char *ssh_get_banner(ssh_session session) {
leave_function(); leave_function();
return NULL; return NULL;
} }
#ifdef WITH_PCAP
if(session->pcap_ctx && buffer[i] == '\n'){
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
}
#endif
if (buffer[i] == '\r') { if (buffer[i] == '\r') {
buffer[i] = '\0'; buffer[i] = '\0';
} }
@ -197,7 +201,10 @@ int ssh_send_banner(ssh_session session, int server) {
leave_function(); leave_function();
return -1; return -1;
} }
#ifdef WITH_PCAP
if(session->pcap_ctx)
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,buffer,strlen(buffer),strlen(buffer));
#endif
leave_function(); leave_function();
return 0; return 0;
} }

Просмотреть файл

@ -42,6 +42,7 @@
#include "libssh/channels.h" #include "libssh/channels.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/messages.h" #include "libssh/messages.h"
#include "libssh/pcap.h"
/* XXX include selected mac size */ /* XXX include selected mac size */
static int macsize=SHA_DIGEST_LEN; static int macsize=SHA_DIGEST_LEN;
@ -159,6 +160,14 @@ static int packet_read2(ssh_session session) {
ssh_set_error(session, SSH_FATAL, "Decrypt error"); ssh_set_error(session, SSH_FATAL, "Decrypt error");
goto error; goto error;
} }
#ifdef WITH_PCAP
if(session->pcap_ctx){
ssh_pcap_context_write(session->pcap_ctx,
SSH_PCAP_DIR_IN, buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer),
buffer_get_len(session->in_buffer));
}
#endif
ssh_socket_read(session->socket, mac, macsize); ssh_socket_read(session->socket, mac, macsize);
if (packet_hmac_verify(session, session->in_buffer, mac) < 0) { if (packet_hmac_verify(session, session->in_buffer, mac) < 0) {
@ -488,7 +497,13 @@ static int packet_send2(ssh_session session) {
if (buffer_add_data(session->out_buffer, padstring, padding) < 0) { if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
goto error; goto error;
} }
#ifdef WITH_PCAP
if(session->pcap_ctx){
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,
buffer_get(session->out_buffer),buffer_get_len(session->out_buffer)
,buffer_get_len(session->out_buffer));
}
#endif
hmac = packet_encrypt(session, buffer_get(session->out_buffer), hmac = packet_encrypt(session, buffer_get(session->out_buffer),
buffer_get_len(session->out_buffer)); buffer_get_len(session->out_buffer));
if (hmac) { if (hmac) {

Просмотреть файл

@ -26,16 +26,21 @@
* \addtogroup ssh_pcap * \addtogroup ssh_pcap
* @{ */ * @{ */
#include "config.h"
#ifdef WITH_PCAP
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/socket.h>
#include <errno.h>
#include "config.h"
#include "libssh/libssh.h" #include "libssh/libssh.h"
#include "libssh/pcap.h" #include "libssh/pcap.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/buffer.h" #include "libssh/buffer.h"
#include "libssh/socket.h"
#ifdef WITH_PCAP
/* The header of a pcap file is the following. We are not going to make it /* The header of a pcap file is the following. We are not going to make it
* very complicated. * very complicated.
* Just for information. * Just for information.
@ -83,6 +88,7 @@ struct pcaprec_hdr_s {
struct ssh_pcap_context_struct { struct ssh_pcap_context_struct {
ssh_session session; ssh_session session;
ssh_pcap_file file; ssh_pcap_file file;
int connected;
/* All of these informations are useful to generate /* All of these informations are useful to generate
* the dummy IP and TCP packets * the dummy IP and TCP packets
*/ */
@ -100,6 +106,7 @@ struct ssh_pcap_context_struct {
*/ */
struct ssh_pcap_file_struct { struct ssh_pcap_file_struct {
FILE *output; FILE *output;
u_int16_t ipsequence;
}; };
/** /**
@ -192,7 +199,7 @@ int ssh_pcap_file_close(ssh_pcap_file pcap){
return SSH_OK; return SSH_OK;
} }
void ssh_pcap_free(ssh_pcap_file pcap){ void ssh_pcap_file_free(ssh_pcap_file pcap){
ssh_pcap_file_close(pcap); ssh_pcap_file_close(pcap);
SAFE_FREE(pcap); SAFE_FREE(pcap);
} }
@ -217,10 +224,69 @@ void ssh_pcap_context_set_file(ssh_pcap_context ctx, ssh_pcap_file pcap){
ctx->file=pcap; ctx->file=pcap;
} }
/** @internal
* @brief sets the IP and port parameters in the connection
*/
static int ssh_pcap_context_connect(ssh_pcap_context ctx){
ssh_session session=ctx->session;
struct sockaddr_in local, remote;
socket_t fd;
socklen_t len;
if(session==NULL)
return SSH_ERROR;
if(session->socket==NULL)
return SSH_ERROR;
fd=ssh_socket_get_fd(session->socket);
/* TODO: adapt for windows */
if(fd<0)
return SSH_ERROR;
len=sizeof(local);
if(getsockname(fd,(struct sockaddr *)&local,&len)<0){
ssh_set_error(session,SSH_REQUEST_DENIED,"Getting local IP address: %s",strerror(errno));
return SSH_ERROR;
}
len=sizeof(remote);
if(getpeername(fd,(struct sockaddr *)&remote,&len)<0){
ssh_set_error(session,SSH_REQUEST_DENIED,"Getting remote IP address: %s",strerror(errno));
return SSH_ERROR;
}
if(local.sin_family != AF_INET){
ssh_set_error(session,SSH_REQUEST_DENIED,"Only IPv4 supported for pcap logging");
return SSH_ERROR;
}
memcpy(&ctx->ipsource,&local.sin_addr,sizeof(ctx->ipsource));
memcpy(&ctx->ipdest,&remote.sin_addr,sizeof(ctx->ipdest));
memcpy(&ctx->portsource,&local.sin_port,sizeof(ctx->portsource));
memcpy(&ctx->portdest,&remote.sin_port,sizeof(ctx->portdest));
ctx->connected=1;
return SSH_OK;
}
#define IPHDR_LEN 20
#define TCPHDR_LEN 20
#define TCPIPHDR_LEN (IPHDR_LEN + TCPHDR_LEN)
/** @internal
* @brief write a SSH packet as a TCP over IP in a pcap file
* @param ctx open pcap context
* @param direction SSH_PCAP_DIRECTION_IN if the packet has been received
* @param direction SSH_PCAP_DIRECTION_OUT if the packet has been emitted
* @param data pointer to the data to write
* @param len data to write in the pcap file. May be smaller than origlen.
* @param origlen number of bytes of complete data.
* @returns SSH_OK write is successful
* @returns SSH_ERROR an error happened.
*/
int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction direction int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction direction
, void *data, u_int32_t len, u_int32_t origlen){ , void *data, u_int32_t len, u_int32_t origlen){
ssh_buffer ip=buffer_new(); ssh_buffer ip;
int err; int err;
if(ctx==NULL || ctx->file ==NULL)
return SSH_ERROR;
if(ctx->connected==0)
if(ssh_pcap_context_connect(ctx)==SSH_ERROR)
return SSH_ERROR;
ip=buffer_new();
if(ip==NULL){ if(ip==NULL){
ssh_set_error_oom(ctx->session); ssh_set_error_oom(ctx->session);
return SSH_ERROR; return SSH_ERROR;
@ -231,9 +297,10 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction directio
/* tos */ /* tos */
buffer_add_u8(ip,0); buffer_add_u8(ip,0);
/* total len */ /* total len */
buffer_add_u16(ip,htons(origlen + 40)); buffer_add_u16(ip,htons(origlen + TCPIPHDR_LEN));
/* id */ /* IP id number */
buffer_add_u16(ip,htons(1)); buffer_add_u16(ip,htons(ctx->file->ipsequence));
ctx->file->ipsequence++;
/* fragment offset */ /* fragment offset */
buffer_add_u16(ip,htons(0)); buffer_add_u16(ip,htons(0));
/* TTL */ /* TTL */
@ -251,17 +318,19 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction directio
} }
/* TCP */ /* TCP */
if(direction==SSH_PCAP_DIR_OUT){ if(direction==SSH_PCAP_DIR_OUT){
buffer_add_u16(ip,ntohs(ctx->portsource)); buffer_add_u16(ip,ctx->portsource);
buffer_add_u16(ip,ntohs(ctx->portdest)); buffer_add_u16(ip,ctx->portdest);
} else { } else {
buffer_add_u16(ip,ntohs(ctx->portdest)); buffer_add_u16(ip,ctx->portdest);
buffer_add_u16(ip,ntohs(ctx->portsource)); buffer_add_u16(ip,ctx->portsource);
} }
/* sequence number */ /* sequence number */
if(direction==SSH_PCAP_DIR_OUT){ if(direction==SSH_PCAP_DIR_OUT){
buffer_add_u32(ip,ntohl(ctx->outsequence)); buffer_add_u32(ip,ntohl(ctx->outsequence));
ctx->outsequence+=origlen;
} else { } else {
buffer_add_u32(ip,ntohl(ctx->insequence)); buffer_add_u32(ip,ntohl(ctx->insequence));
ctx->insequence+=origlen;
} }
/* ack number */ /* ack number */
if(direction==SSH_PCAP_DIR_OUT){ if(direction==SSH_PCAP_DIR_OUT){
@ -269,7 +338,7 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction directio
} else { } else {
buffer_add_u32(ip,ntohl(ctx->outsequence)); buffer_add_u32(ip,ntohl(ctx->outsequence));
} }
/* header len */ /* header len = 20 = 5 * 32 bits, at offset 4*/
buffer_add_u8(ip,5 << 4); buffer_add_u8(ip,5 << 4);
/* flags */ /* flags */
buffer_add_u8(ip,TH_PUSH | TH_ACK); buffer_add_u8(ip,TH_PUSH | TH_ACK);
@ -281,11 +350,16 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction directio
buffer_add_u16(ip,0); buffer_add_u16(ip,0);
/* actual data */ /* actual data */
buffer_add_data(ip,data,len); buffer_add_data(ip,data,len);
err=ssh_pcap_file_write_packet(ctx->file,ip,origlen + 40); err=ssh_pcap_file_write_packet(ctx->file,ip,origlen + TCPIPHDR_LEN);
buffer_free(ip); buffer_free(ip);
return err; return err;
} }
void ssh_set_pcap_context(ssh_session session, ssh_pcap_context pcap){
session->pcap_ctx=pcap;
}
#endif /* WITH_PCAP */ #endif /* WITH_PCAP */
/** @} */ /** @} */
/* vim: set ts=2 sw=2 et cindent: */ /* vim: set ts=2 sw=2 et cindent: */