1
0
This repository has been archived on 2023-11-30. You can view files and clone it, but cannot push or open issues or pull requests.
dtux__sshdetect/main.c

622 lines
13 KiB
C
Raw Normal View History

2020-05-02 13:15:48 +02:00
#include <stdio.h>
#include <stdlib.h>
2020-05-04 17:22:24 +02:00
#include <string.h>
#include <unistd.h>
#include <time.h>
2020-05-07 13:54:04 +02:00
#include <sys/types.h>
#include <sys/wait.h>
2020-05-07 17:10:00 +02:00
#include <utmp.h>
2020-05-08 14:11:12 +02:00
#include <locale.h>
2020-05-09 14:24:55 +02:00
#include <libgen.h>
#include <sys/inotify.h>
2020-05-02 13:15:48 +02:00
2020-05-13 18:55:48 +02:00
#define HOSTNAME "localhost"
#define EVENT_SIZE (sizeof(struct inotify_event))
int debug = 0;
2020-05-04 17:22:24 +02:00
struct connexion
{
int pid;
char cmd[24];
char cmdline[1000];
char user[24];
char hostname[128];
char host_ip[42];
char host_ipv6[42];
char date[60];
};
2020-05-13 18:55:48 +02:00
struct config
{
char commande[1024];
char logfile[4096];
char hostname[128];
char configfile[4096];
};
2020-05-13 18:55:48 +02:00
struct notify_config
{
int fd;
int wd;
2020-05-13 18:55:48 +02:00
};
2020-05-13 18:55:48 +02:00
int explode( char * str, char * separator, size_t m, size_t n, char exploded[m][n] )
{
char * pch;
int x=0 ;
pch = strtok( str, separator );
while( pch != NULL )
{
if (debug >= 2) printf("%s\n", pch);
2020-05-13 18:55:48 +02:00
strcpy( exploded[x++], pch) ;
pch = strtok( NULL , separator );
}
return x;
}
// config function
int readconfig( struct config * cfg )
{
FILE * fh = NULL;
char path[2][30] = {"/etc/sshdetect.conf", ""};
int x;
int retval=0;
char str[1024];
char exploded[2][1024];
char * homepath;
char * buff;
char logfilepath[1024];
homepath = getenv("HOME");
if ( homepath != NULL )
{
sprintf( path[1], "%s%s", homepath, "/.config/sshdetect.conf" );
}
sprintf( logfilepath, "%s%s", homepath, "/.locale/share/sshdetect.log");
for(x=0;x<2;x++)
{
if ((fh = fopen( path[x], "r")) == NULL)
{
if (debug >= 1) perror(path[x]);
2020-05-13 18:55:48 +02:00
if(x==1) retval = -1;
}else
{
strcpy( cfg->configfile, path[x]);
if (debug >= 1) printf("Found config file: %s\n", path[x]);
2020-05-13 18:55:48 +02:00
x = 3;
}
}
if (fh != NULL)
{
while(fgets(str, 1024, fh) != NULL)
{
explode(str, "= \n", 2, 1024, exploded);
if ( strcmp( exploded[0], "commande") == 0 )
{
if ( fopen(exploded[1],"r") != NULL)
{
strcpy( cfg->commande, exploded[1] );
if (debug >= 1) printf("Found command: %s\n", cfg->commande);
2020-05-13 18:55:48 +02:00
}else
{
if (debug >= 1) perror(exploded[1]);
2020-05-13 18:55:48 +02:00
}
}else if( strcmp( exploded[0], "logfile") == 0)
{
if ( fopen(exploded[1], "a") != NULL )
{
strcpy( cfg->logfile, exploded[1] );
if (debug >= 1) printf("Found logfile: %s\n", cfg->logfile);
2020-05-13 18:55:48 +02:00
}
}else if( strcmp( exploded[0], "hostname") == 0 )
{
strcpy( cfg->hostname, exploded[1] );
if (debug >= 1 ) printf("Found hostname: %s\n", cfg->hostname);
2020-05-13 18:55:48 +02:00
}
}
}
if ( cfg->logfile[0] == 0 )
{
if ( fopen("/var/log/sshdetect.log", "a") != NULL )
{
strcpy( cfg->logfile, "/var/log/sshdetect.log" );
}else if ( fopen(logfilepath, "a") != NULL )
{
strcpy( cfg->logfile, logfilepath );
}else
{
if (debug >= 1) perror(logfilepath);
2020-05-13 18:55:48 +02:00
strcpy(cfg->logfile, "/dev/null");
retval += 2;
}
}
if (cfg->hostname[0] == 0 )
{
buff = getenv("HOSTNAME");
if ( buff != NULL)
{
strcpy(cfg->hostname, buff);
}else
{
strcpy(cfg->hostname, HOSTNAME);
}
}
if (cfg->commande[0] == 0)
{
if (debug >=1) printf("command not found in config file: no command will be executed\n");
2020-05-13 18:55:48 +02:00
retval += 4;
}
return retval;
}
//test if pid is in list of known sshd processus
2020-05-04 17:22:24 +02:00
int isinarray( int pid, int array[], int n )
{
int x;
for(x=1;x<=n;x++)
{
if( pid == array[x])
{
return x;
}
}
return 0;
2020-05-07 17:10:00 +02:00
}
2020-05-08 13:52:11 +02:00
char* frtime(const time_t timet)
{
struct tm *date_tm;
static char result[40];
2020-05-08 14:26:12 +02:00
2020-05-08 13:52:11 +02:00
date_tm = localtime(&timet);
2020-05-08 14:14:24 +02:00
strftime(result, 40, "%c", date_tm);
2020-05-08 13:52:11 +02:00
return result;
}
int init_config_watch( char config_file[], struct notify_config * ncc )
{
ncc->fd = inotify_init();
if ( ncc->fd < 0 )
{
perror( "inotify_init" );
return -1;
}
ncc->wd = inotify_add_watch( ncc->fd, config_file, IN_MODIFY | IN_DELETE );
if (ncc->wd == -1)
{
perror(config_file);
printf("%s\n", config_file);
return -2;
}
return 0;
}
int notify_config_change(struct notify_config * ncc, char config_file[], struct config * cfg)
{
int length=0;
int i=0;
int buff_length = (1024 * (EVENT_SIZE + 16));
char buff[buff_length];
fd_set rfds;
struct timeval tv = {1,0};
int retval;
FD_ZERO(&rfds);
FD_SET(ncc->fd, &rfds);
retval = select(ncc->fd+1, &rfds, NULL, NULL, &tv);
if (retval == -1)
{
if (debug >= 1) perror("select()");
}
else if (retval)
{
length = read(ncc->fd, buff, buff_length);
if (length < 0)
{
if (debug >= 1) perror("reading");
return -1;
}
while (i < length)
{
struct inotify_event *event = (struct inotify_event *) &buff[i];
if (event->mask & IN_DELETE)
{
if (debug >= 2) printf("The file %s was deleted.\n", event->name);
init_config_watch( config_file, ncc);
} else if (event->mask & IN_MODIFY)
{
if (debug >= 2) printf("The file %s was modified.\n", event->name);
readconfig(cfg);
}
i += EVENT_SIZE + event->len;
}
}
return 0;
}
2020-05-08 02:16:35 +02:00
//get utmp datas
void getutmp( struct connexion * conn, time_t * time )
2020-05-07 17:10:00 +02:00
{
struct utmp * utmp;
2020-05-08 13:07:36 +02:00
int ipv6;
2020-05-08 12:52:33 +02:00
int ipv4;
2020-05-08 02:16:35 +02:00
int x;
char str[6];
conn->host_ip[0]='\0';
conn->host_ipv6[0]='\0';
2020-05-07 17:14:51 +02:00
setutent();
while ( (utmp = getutent()) != NULL )
2020-05-07 17:10:00 +02:00
{
if ( utmp->ut_pid == conn->pid )
2020-05-07 17:44:02 +02:00
{
sprintf(conn->user, "%s", utmp->ut_user); //got user login
sprintf(conn->hostname, "%s", utmp->ut_host); //got ip of origin
2020-05-08 02:16:35 +02:00
if((utmp->ut_addr_v6[1] && utmp->ut_addr_v6[2] && utmp->ut_addr_v6[3]) == 0)
{
2020-05-08 13:07:36 +02:00
ipv4 = utmp->ut_addr_v6[0] & 0x00000000000000ff;
2020-05-08 13:10:56 +02:00
sprintf( str, "%d.", ipv4);
strcat(conn->host_ip, str);
2020-05-08 13:07:36 +02:00
ipv4 = (utmp->ut_addr_v6[0] & 0x000000000000ff00) >> 8;
2020-05-08 13:10:56 +02:00
sprintf( str, "%d.", ipv4);
strcat(conn->host_ip, str);
2020-05-08 13:07:36 +02:00
ipv4 = (utmp->ut_addr_v6[0] & 0x0000000000ff0000) >> 16;
2020-05-08 13:10:56 +02:00
sprintf( str, "%d.", ipv4);
strcat(conn->host_ip, str);
2020-05-08 13:07:36 +02:00
ipv4 = (utmp->ut_addr_v6[0] & 0x00000000ff000000) >> 24;
2020-05-08 13:10:56 +02:00
sprintf( str, "%d", ipv4);
strcat(conn->host_ip, str);
2020-05-08 02:16:35 +02:00
}else
{
for (x=0;x<4;x++)
{
2020-05-08 13:07:36 +02:00
ipv6 = utmp->ut_addr_v6[x] & 0x000000000000ffff;
sprintf( str, "%x:", ipv6);
strcat(conn->host_ipv6, str);
2020-05-08 13:07:36 +02:00
ipv6 = (utmp->ut_addr_v6[x] & 0x00000000ffff0000) >> 16;
sprintf( str, "%x:", ipv6);
strcat(conn->host_ipv6, str);
2020-05-08 13:07:36 +02:00
ipv6 = (utmp->ut_addr_v6[x] & 0x0000ffff00000000) >> 32;
sprintf( str, "%x:", ipv6);
strcat(conn->host_ipv6, str);
2020-05-08 13:07:36 +02:00
ipv6 = (utmp->ut_addr_v6[x] & 0xffff000000000000) >> 48;
sprintf( str, "%x:", ipv6);
strcat(conn->host_ipv6, str);
2020-05-08 02:16:35 +02:00
}
conn->host_ipv6[strlen(conn->host_ipv6)-1] = '\0';
2020-05-08 02:16:35 +02:00
}
*time = (time_t) utmp->ut_tv.tv_sec; //got connexion time
2020-05-07 17:48:24 +02:00
break;
2020-05-07 17:44:02 +02:00
}
2020-05-04 17:22:24 +02:00
}
2020-05-07 17:10:00 +02:00
endutent();
2020-05-04 17:22:24 +02:00
}
2020-05-08 02:16:35 +02:00
//replace null characters by space
2020-05-06 17:14:36 +02:00
int null2space( char str[] )
{
int flag =0;
int x = 0;
while ( flag == 0 )
{
if ( (int) str[x] == 0 )
{
if ( (int) str[x+1] != 0 )
{
str[x] = ' ';
2020-05-13 18:56:19 +02:00
}else
2020-05-13 18:55:48 +02:00
2020-05-06 17:14:36 +02:00
{
flag = 1;
}
}
x++;
}
return x-1 ;
}
2020-05-08 02:16:35 +02:00
// get the childs pids
2020-05-06 15:23:12 +02:00
int getpids(int pid, int exploded[])
{
FILE *fh;
char * pch;
char path[1024];
char str[4096];
char separator[] = " ";
int x = 0;
sprintf( path, "/proc/%d/task/%d/children", pid, pid);
if (debug >= 1) printf("process path: %s", path);
2020-05-06 15:23:12 +02:00
if ((fh = fopen( path, "r")) == NULL)
{
if (debug >= 1) perror(path);
2020-05-06 15:23:12 +02:00
return -1;
}
if ( fgets( str, 40, fh ) != NULL )
{
pch = strtok( str, separator );
while( pch != NULL )
{
if (debug >= 2) printf("%s\n", pch);
2020-05-06 15:23:12 +02:00
exploded[x++] = atoi( pch );
pch = strtok( NULL , separator );
2020-05-09 14:24:55 +02:00
}
2020-05-06 15:23:12 +02:00
fclose(fh);
return x;
}else
{
fclose(fh);
return -1;
}
}
int getprocinfo( struct connexion * conn )
2020-05-02 13:15:48 +02:00
{
2020-05-04 17:22:24 +02:00
FILE *fh1;
char child_path[128];
char str[1024];
2020-05-06 15:23:12 +02:00
int child_pid[10];
2020-05-04 17:22:24 +02:00
int flag = 0;
int r;
2020-05-06 15:23:12 +02:00
int level = 0;
int retval = 0;
2020-05-13 18:55:48 +02:00
char tab[128];
2020-05-07 19:19:34 +02:00
time_t timet=0;
2020-05-04 17:22:24 +02:00
2020-05-08 02:16:35 +02:00
//get connexion time
getutmp( conn, &timet );
2020-05-07 19:25:37 +02:00
if ( timet == 0)
2020-05-07 19:05:41 +02:00
{
2020-05-07 19:19:34 +02:00
time( &timet );
2020-05-07 19:05:41 +02:00
}
sprintf( conn->date, "%s", frtime(timet) );
2020-05-08 02:16:35 +02:00
//get the pid of the last processus
2020-05-04 17:22:24 +02:00
while ( flag == 0)
{
r = getpids( conn->pid, child_pid );
2020-05-06 15:23:12 +02:00
if( level == 0 && r == 2 )
2020-05-04 17:22:24 +02:00
{
2020-05-06 15:23:12 +02:00
flag = 1;
2020-05-06 18:50:57 +02:00
retval = -1;
2020-05-06 15:23:12 +02:00
}else if ( r != -1 )
2020-05-04 17:22:24 +02:00
{
2020-05-06 15:23:12 +02:00
level++;
2020-05-13 18:55:48 +02:00
strcat(tab," ");
conn->pid = child_pid[0];
2020-05-04 17:22:24 +02:00
}else
{
flag = 1;
}
}
2020-05-08 02:16:35 +02:00
// get the command parameters
sprintf( child_path, "/proc/%d/cmdline", conn->pid );
2020-05-04 17:22:24 +02:00
if ( (fh1= fopen( child_path, "r" )) == NULL)
{
if (debug >= 1) perror(child_path);
2020-05-06 15:23:12 +02:00
return 2;
2020-05-04 17:22:24 +02:00
}
fgets( str, 1024, fh1);
2020-05-06 17:14:36 +02:00
null2space( str );
sprintf(conn->cmdline, "%s", str);
2020-05-04 17:22:24 +02:00
fclose(fh1);
2020-05-08 02:16:35 +02:00
// get the command name
sprintf( child_path, "/proc/%d/comm", conn->pid );
2020-05-04 17:22:24 +02:00
if ( (fh1= fopen(child_path, "r" )) == NULL)
{
if (debug >= 1) perror(child_path);
2020-05-06 15:23:12 +02:00
return 3;
2020-05-04 17:22:24 +02:00
}
fscanf( fh1, "%s", conn->cmd );
2020-05-04 17:22:24 +02:00
fclose(fh1);
2020-05-06 15:23:12 +02:00
return retval;
2020-05-04 17:22:24 +02:00
}
int main()
2020-05-04 17:22:24 +02:00
{
2020-05-13 18:55:48 +02:00
FILE *fh = NULL;
2020-05-04 17:22:24 +02:00
FILE *fh1;
2020-05-06 15:23:12 +02:00
int n_ssh=10;
2020-05-04 17:22:24 +02:00
int id;
int pid;
int x=0;
2020-05-06 15:23:12 +02:00
int y=0;
2020-05-13 18:55:48 +02:00
int r=0;
2020-05-04 17:22:24 +02:00
int i;
int j;
2020-05-06 15:23:12 +02:00
int n;
int start=1;
int childrens[n_ssh];
int pids[n_ssh];
int flag[n_ssh];
int rinfo;
2020-05-07 13:54:04 +02:00
int status;
char ip[42]="";
2020-05-04 17:22:24 +02:00
char str[1024];
char date[60];
2020-05-13 18:55:48 +02:00
time_t now = 0;
2020-05-08 15:27:06 +02:00
char * language;
// char * buff;
struct connexion conn;
struct connexion connexions[n_ssh];
struct config cfg = {"","","",""};
struct notify_config ncc;
2020-05-08 15:32:55 +02:00
//char * ptr;
2020-05-09 14:24:55 +02:00
// Loading configuration
2020-05-13 18:55:48 +02:00
readconfig( &cfg );
2020-05-09 14:24:55 +02:00
2020-05-13 18:55:48 +02:00
//localizing
if ( (language = getenv("LANGUAGE")) != NULL)
2020-05-08 18:44:06 +02:00
{
2020-05-13 18:55:48 +02:00
strtok (language, ":");
}else if ( (language = getenv("LC_ALL")) == NULL )
2020-05-08 18:44:06 +02:00
{
2020-05-13 18:55:48 +02:00
language="";
2020-05-08 18:44:06 +02:00
}
2020-05-13 18:55:48 +02:00
setlocale(LC_ALL,language);
2020-05-08 14:51:57 +02:00
2020-05-04 17:22:24 +02:00
time( &now );
2020-05-08 15:32:55 +02:00
sprintf( date, "%s", frtime(now));
2020-05-13 18:55:48 +02:00
if ( (fh = fopen(cfg.logfile, "a")) == NULL)
2020-05-04 17:22:24 +02:00
{
if (debug >= 1) perror(cfg.logfile);
2020-05-13 18:55:48 +02:00
return 7;
2020-05-04 17:22:24 +02:00
}
2020-05-06 15:23:12 +02:00
fprintf(fh, "%s: Démarrage de sshdetect\n", date);
2020-05-04 17:22:24 +02:00
fclose(fh);
2020-05-13 18:55:48 +02:00
sprintf( str, "%s \"%s - %s: Démarrage de sshdetect\"", cfg.commande, cfg.hostname, date );
2020-05-04 17:22:24 +02:00
id=fork();
if(id == 0)
{
2020-05-13 18:55:48 +02:00
if (cfg.commande[0] != 0)
{
r = system( str );
}else
{
if (debug >= 2) printf("no command defined: no command launched\n");
2020-05-13 18:55:48 +02:00
}
2020-05-04 17:22:24 +02:00
exit(r);
}else if( id<0 )
{
if (debug >= 1) printf("erreur de création du fork: %s\n", str);
2020-05-04 17:22:24 +02:00
}
init_config_watch( cfg.configfile, &ncc);
2020-05-04 17:22:24 +02:00
while (1)
{
// get the sshd process ID (PID)
if ( (fh = fopen("/run/sshd.pid", "r" )) == NULL)
{
if (debug >= 1) perror("/run/sshd.pid");
2020-05-04 17:22:24 +02:00
return 1;
}
if ( fscanf(fh, "%i", &pid) == 0)
{
if (debug >= 1) printf("erreur fscanf: /run/sshd.pid\n" );
2020-05-04 17:22:24 +02:00
return 10;
}
fclose(fh);
if (debug >= 1) printf("%i", pid);
2020-05-04 17:22:24 +02:00
//get the list of children
2020-05-06 16:36:48 +02:00
if ( (n=getpids( pid, pids )) != -1)
2020-05-04 17:22:24 +02:00
{
2020-05-06 19:05:56 +02:00
for ( y=0; y<n; y++)
2020-05-04 17:22:24 +02:00
{
2020-05-06 15:23:12 +02:00
pid = pids[y];
r = isinarray(pid, childrens, x);
if( r == 0 )
2020-05-04 17:22:24 +02:00
{
conn.user[0]='\0';
conn.pid=pid;
rinfo = getprocinfo( &conn );
2020-05-06 15:23:12 +02:00
if( rinfo == 0 )
2020-05-04 17:22:24 +02:00
{
if (conn.host_ip[0] != '\0')
{
strcpy(ip,conn.host_ip);
}else if (conn.host_ipv6[0] != '\0')
{
strcpy(ip,conn.host_ipv6);
}
2020-05-06 15:23:12 +02:00
x++;
childrens[x] = pid;
flag[x] = 1;
connexions[x] = conn;
2020-05-07 19:05:41 +02:00
// date of connexion
if (conn.user[0] == '\0')
2020-05-06 18:50:57 +02:00
{
sprintf( str, "%s \"%s: tunnel ouvert le %s depuis %s pid: %d avec la commande: %s %s\"", cfg.commande, cfg.hostname, conn.date, ip, conn.pid, conn.cmd, conn.cmdline );
2020-05-06 18:50:57 +02:00
}else
{
sprintf( str, "%s \"%s: %s s'est connecté le %s depuis %s pid: %d avec la commande: %s %s\"", cfg.commande, cfg.hostname, conn.user, conn.date,ip, conn.pid, conn.cmd, conn.cmdline );
2020-05-06 18:50:57 +02:00
}
2020-05-06 15:23:12 +02:00
if ( start != 1 )
{
id=fork();
2020-05-13 18:55:48 +02:00
if(id > 0)
2020-05-06 15:23:12 +02:00
{
2020-05-13 18:55:48 +02:00
if ( (fh1 = fopen(cfg.logfile, "a")) == NULL)
2020-05-06 15:23:12 +02:00
{
if (debug >= 1) perror(cfg.logfile);
2020-05-06 15:23:12 +02:00
return 7;
}
2020-05-08 18:44:06 +02:00
fprintf(fh1, "%s: Connexion de %s depuis %s commande: %s %s\n", conn.date, conn.user, ip, conn.cmd, conn.cmdline);
2020-05-06 15:23:12 +02:00
fclose(fh1);
2020-05-13 18:55:48 +02:00
}else if (id < 0)
2020-05-06 15:23:12 +02:00
{
if (debug >= 1) printf("erreur de création du fork: %s\n", str);
2020-05-06 15:23:12 +02:00
}else
{
2020-05-13 18:55:48 +02:00
if (cfg.commande[0] != 0)
{
if (debug >= 1) printf("%s\n", str);
2020-05-13 18:55:48 +02:00
r = system( str );
}else
{
if (debug >= 1) printf("no command defined: no command launched\n");
2020-05-13 18:55:48 +02:00
}
exit(r);
2020-05-06 15:23:12 +02:00
}
}else
2020-05-04 17:22:24 +02:00
{
2020-05-13 18:55:48 +02:00
if ( (fh1 = fopen(cfg.logfile, "a")) == NULL)
2020-05-05 10:29:16 +02:00
{
if (debug >= 1) perror(cfg.logfile);
2020-05-05 10:29:16 +02:00
return 7;
}
fprintf(fh1, "%s: %s Connecté depuis %s - %s %s\n", conn.date, conn.user, ip, conn.cmd, conn.cmdline);
2020-05-05 10:29:16 +02:00
fclose(fh1);
2020-05-04 17:22:24 +02:00
}
2020-05-13 18:55:48 +02:00
}else if (rinfo == -1)
{
if (debug >= 2) printf("%i => 2 pids : en cours de connexion\n", conn.pid);
2020-05-04 17:22:24 +02:00
}
2020-05-06 15:23:12 +02:00
}else
{
flag[r] = 1;
2020-05-04 17:22:24 +02:00
}
}
2020-05-06 15:23:12 +02:00
for(i=1;i<=x;i++)
2020-05-04 17:22:24 +02:00
{
2020-05-06 15:23:12 +02:00
if (flag[i] == 0 )
2020-05-04 17:22:24 +02:00
{
time( &now );
2020-05-13 18:55:48 +02:00
sprintf( date, "%s", frtime(now) );
if (debug >= 2) printf( "Session %d de %s terminée le %s\n", connexions[i].pid, connexions[i].user, date );
2020-05-13 18:55:48 +02:00
if ( (fh1 = fopen(cfg.logfile, "a")) == NULL)
2020-05-08 18:44:06 +02:00
{
if (debug >= 1) perror(cfg.logfile);
2020-05-08 18:44:06 +02:00
return 7;
}
2020-05-13 18:55:48 +02:00
fprintf(fh1, "%s: pid %d -Connexion de %s terminée le %s\n", cfg.hostname, connexions[i].pid, connexions[i].user, connexions[i].date);
2020-05-06 15:23:12 +02:00
for( j=i; j<x; j++ )
{
childrens[j] = childrens[j+1];
flag[j] = flag[j+1];
}
i--;
x--;
}else
{
flag[i] = 0;
2020-05-04 17:22:24 +02:00
}
}
}
waitpid(-1, &status ,WNOHANG);
// sleep(1);
notify_config_change(&ncc, cfg.configfile, &cfg);
2020-05-04 17:22:24 +02:00
start = 0;
}
return 0;
2020-05-02 13:15:48 +02:00
}