123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <utmp.h>
- #include <locale.h>
- #include <libgen.h>
- #include <sys/inotify.h>
- #include <errno.h>
- #define HOSTNAME "localhost"
- #define EVENT_SIZE (sizeof(struct inotify_event))
- //debug levels
- #define NONE 0
- #define WARNING 1
- #define INFO 2
- #define DEBUG 3
- char debug[5][10] = { "[NONE]", "[INFO]", "[WARNING]", "[DEBUG]" };
- char fn[30] = "";
- struct connexion
- {
- int pid;
- char cmd[128];
- char cmdline[1000];
- char user[128];
- char hostname[128];
- char host_ip[42];
- char host_ipv6[42];
- char date[60];
- };
- struct config
- {
- char commande[1024];
- char logfile[4096];
- char hostname[128];
- char configfile[4096];
- };
- struct notify_config
- {
- int fd;
- int wd;
- };
- struct config cfg = {"","","",""};
- int loglevel = DEBUG;
- // return date in localized format
- char * frtime(const time_t timet)
- {
- struct tm *date_tm;
- static char result[40];
- date_tm = localtime(&timet);
- strftime(result, 40, "%c", date_tm);
- return result;
- }
- int printlog(char str[], int level, int errnum)
- {
- FILE * fh = NULL;
- time_t now = 0;
- char tmp[128];
- int retval = EXIT_SUCCESS;
- static char fn_tmp[30];
- if ( level <= loglevel )
- {
- time( &now );
- if (errnum != 0)
- {
- sprintf( tmp, "%s %s: %s %s\n", debug[level], frtime(now), str, strerror(errnum));
- }else
- {
- sprintf( tmp, "%s %s: %s\n", debug[level], frtime(now), str);
- }
- if ( (fh = fopen(cfg.logfile, "a")) == NULL)
- {
- perror(cfg.logfile);
- retval = EXIT_FAILURE;
- }else
- {
- if( strcmp(fn_tmp, fn) != 0 )
- {
- fprintf(fh, "\n---------- function %s ----------\n", fn);
- strcpy(fn_tmp, fn);
- }
- fprintf(fh, "%s", tmp);
- fclose(fh);
- }
- printf("%s", tmp);
- }
- return retval;
- }
- int explode( char * str, char * separator, size_t m, size_t n, char exploded[m][n] )
- {
- char * pch;
- int x=0 ;
- strcpy( fn, "explode");
- pch = strtok( str, separator );
- while( pch != NULL )
- {
- printlog( pch, DEBUG, 0);
- strcpy( exploded[x++], pch) ;
- pch = strtok( NULL , separator );
- }
- return x;
- }
- // config function
- int readconfig( struct config * cfg )
- {
- FILE * fh = NULL;
- FILE * fh1 = NULL;
- char path[2][30] = {"/etc/sshdetect.conf", ""};
- int x;
- int retval=0;
- char str[1024];
- char strlog[128];
- 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, "/.local/share/sshdetect.log");
- for(x=0;x<2;x++)
- {
- if ((fh = fopen( path[x], "r")) == NULL)
- {
- printlog( path[x], WARNING, errno );
- retval = -1;
- }else
- {
- strcpy( cfg->configfile, path[x]);
- sprintf(strlog, "Found config file: %s\n", path[x]);
- printlog( strlog, WARNING, 0);
- x = 3;
- retval = 0;
- }
- }
- if (fh != NULL)
- {
- while(fgets(str, 1024, fh) != NULL)
- {
- explode(str, "= \n", 2, 1024, exploded);
- if ( strcmp( exploded[0], "commande") == 0 )
- {
- if ( (fh1 = fopen(exploded[1],"r")) != NULL)
- {
- strcpy( cfg->commande, exploded[1] );
- sprintf(strlog, "Found command: %s", cfg->commande);
- printlog(strlog, INFO, 0);
- fclose(fh1);
- }else
- {
- printlog( exploded[1], INFO, errno);
- }
- }else if( strcmp( exploded[0], "logfile") == 0)
- {
- if ( (fh1 = fopen(exploded[1], "a")) != NULL )
- {
- strcpy( cfg->logfile, exploded[1] );
- sprintf( strlog, "Found logfile: %s", cfg->logfile);
- printlog(strlog, INFO, 0);
- fclose(fh1);
- }
- }else if( strcmp( exploded[0], "hostname") == 0 )
- {
- strcpy( cfg->hostname, exploded[1] );
- sprintf(strlog, "Found hostname: %s", cfg->hostname);
- printlog(strlog, INFO, 0);
- }
- }
- }
- if ( cfg->logfile[0] == 0 )
- {
- if ( (fh1 = fopen("/var/log/sshdetect.log", "a")) != NULL )
- {
- strcpy( cfg->logfile, "/var/log/sshdetect.log" );
- fclose(fh1);
- }else if ( (fh1 = fopen(logfilepath, "a")) != NULL )
- {
- strcpy( cfg->logfile, logfilepath );
- fclose(fh1);
- }else
- {
- printlog( logfilepath, WARNING, errno);
- strcpy(cfg->logfile, "/dev/null");
- retval += 2;
- }
- printf("logfile not found, defaulting to %s\n", cfg->logfile);
- }
- if (cfg->hostname[0] == 0 )
- {
- buff = getenv("HOSTNAME");
- if ( buff != NULL)
- {
- strcpy(cfg->hostname, buff);
- }else
- {
- strcpy(cfg->hostname, HOSTNAME);
- }
- printf("hostname not found, defaulting to %s\n", cfg->hostname);
- }
- if (cfg->commande[0] == 0)
- {
- strcpy(cfg->commande,"no command found");
- printf("command not found in config file: no command will be executed\n");
- retval += 4;
- }
- return retval;
- }
- //test if pid is in list of known sshd processus
- // return number of pid
- int isinarray( int pid, int array[], int n )
- {
- int x;
- char strlog[128];
- strcpy( fn, "isinarray");
- for(x=1;x<=n;x++)
- {
- if( pid == array[x])
- {
- sprintf(strlog, "pid %i is in array", pid);
- printlog(strlog, DEBUG, 0 );
- return x;
- }
- }
- return 0;
- }
- // initialize config file watching
- int init_config_watch( char config_file[], struct notify_config * ncc )
- {
- strcpy( fn, "init_config_watch" );
- ncc->fd = inotify_init();
- if ( ncc->fd < 0 )
- {
- printlog("inotify_init", WARNING, errno );
- return -1;
- }
- ncc->wd = inotify_add_watch( ncc->fd, config_file, IN_MODIFY | IN_DELETE );
- if (ncc->wd == -1)
- {
- printlog(config_file, WARNING, errno);
- return -2;
- }
- return 0;
- }
- int notify_config_change(struct notify_config * ncc, char config_file[])
- {
- int length=0;
- int i=0;
- int buff_length = (1024 * (EVENT_SIZE + 16));
- char buff[buff_length];
- char strlog[128];
- fd_set rfds;
- struct timeval tv = {1,0};
- int retval;
- strcpy( fn, "notify_config_change");
- FD_ZERO(&rfds);
- FD_SET(ncc->fd, &rfds);
- retval = select(ncc->fd+1, &rfds, NULL, NULL, &tv);
- if (retval == -1)
- {
- printlog("select()", WARNING, errno);
- }
- else if (retval)
- {
- length = read(ncc->fd, buff, buff_length);
- if (length < 0)
- {
- printlog("reading", WARNING, errno);
- return -1;
- }
- while (i < length)
- {
- struct inotify_event *event = (struct inotify_event *) &buff[i];
- if (event->mask & IN_DELETE)
- {
- sprintf(strlog, "The file %s was deleted.", event->name);
- printlog(strlog, INFO, 0);
- init_config_watch( config_file, ncc);
- } else if (event->mask & IN_MODIFY)
- {
- sprintf(strlog, "The file %s was modified.", event->name);
- printlog(strlog, INFO, 0);
- readconfig(&cfg);
- }
- i += EVENT_SIZE + event->len;
- }
- }
- return 0;
- }
- //get utmp datas
- void getutmp( struct connexion * conn, time_t * time )
- {
- struct utmp * utmp;
- int ipv6;
- int ipv4;
- int x;
- char str[6];
- char strlog[128];
- strcpy( fn, "getutpm");
- conn->host_ip[0]='\0';
- conn->host_ipv6[0]='\0';
- setutent();
- while ( (utmp = getutent()) != NULL )
- {
- if ( utmp->ut_pid == conn->pid )
- {
- sprintf(conn->user, "%s", utmp->ut_user); //got user login
- printlog(conn->user, DEBUG, 0);
- sprintf(conn->hostname, "%s", utmp->ut_host); //got ip of origin
- printlog(conn->hostname, DEBUG, 0);
- if(utmp->ut_addr_v6[1] == 0)
- {
- ipv4 = utmp->ut_addr_v6[0] & 0x00000000000000ff;
- sprintf( str, "%d.", ipv4);
- strcat(conn->host_ip, str);
- ipv4 = (utmp->ut_addr_v6[0] & 0x000000000000ff00) >> 8;
- sprintf( str, "%d.", ipv4);
- strcat(conn->host_ip, str);
- ipv4 = (utmp->ut_addr_v6[0] & 0x0000000000ff0000) >> 16;
- sprintf( str, "%d.", ipv4);
- strcat(conn->host_ip, str);
- ipv4 = (utmp->ut_addr_v6[0] & 0x00000000ff000000) >> 24;
- sprintf( str, "%d", ipv4);
- strcat(conn->host_ip, str);
- printlog(conn->host_ip, DEBUG, 0);
- }else
- {
- for (x=0;x<4;x++)
- {
- ipv6 = utmp->ut_addr_v6[x] & 0x000000000000ffff;
- sprintf( str, "%x:", ipv6);
- strcat(conn->host_ipv6, str);
- ipv6 = (utmp->ut_addr_v6[x] & 0x00000000ffff0000) >> 16;
- sprintf( str, "%x:", ipv6);
- strcat(conn->host_ipv6, str);
- ipv6 = (utmp->ut_addr_v6[x] & 0x0000ffff00000000) >> 32;
- sprintf( str, "%x:", ipv6);
- strcat(conn->host_ipv6, str);
- ipv6 = (utmp->ut_addr_v6[x] & 0xffff000000000000) >> 48;
- sprintf( str, "%x:", ipv6);
- strcat(conn->host_ipv6, str);
- }
- conn->host_ipv6[strlen(conn->host_ipv6)-1] = '\0';
- printlog(conn->host_ipv6, DEBUG, 0);
- }
- *time = (time_t) utmp->ut_tv.tv_sec; //got connexion time
- sprintf(strlog, "heure de connexion - %s", frtime( *time ) );
- break;
- }
- }
- endutent();
- }
- //replace null characters by space
- 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] = ' ';
- }else
- {
- flag = 1;
- }
- }
- x++;
- }
- return x-1 ;
- }
- // get the childs pids
- int getpids(int pid, int exploded[])
- {
- FILE *fh;
- char * pch;
- char path[1024];
- char str[4096];
- char strlog[128];
- char separator[] = " ";
- int x = 0;
- strcpy( fn, "getpids");
- sprintf( path, "/proc/%d/task/%d/children", pid, pid);
- sprintf(strlog, "process path: %s", path);
- printlog(strlog, DEBUG,0);
- if ((fh = fopen( path, "r")) == NULL)
- {
- printlog(path, WARNING, errno);
- return -1;
- }
- if ( fgets( str, 40, fh ) != NULL )
- {
- pch = strtok( str, separator );
- while( pch != NULL )
- {
- printlog(pch, DEBUG, 0);
- exploded[x++] = atoi( pch );
- pch = strtok( NULL , separator );
- }
- fclose(fh);
- return x;
- }else
- {
- fclose(fh);
- return -1;
- }
- }
- // get informations on processus
- int getprocinfo( struct connexion * conn )
- {
- FILE *fh1;
- char child_path[1024];
- char str[1024];
- int child_pid[10];
- int flag = 0;
- int r;
- int level = 0;
- int retval = 0;
- //char tab[128];
- time_t timet=0;
- strcpy( fn, "getprocinfo");
- //get connexion time
- getutmp( conn, &timet );
- if ( timet == 0)
- {
- time( &timet );
- }
- sprintf( conn->date, "%s", frtime(timet) );
- //get the pid of the last processus
- while ( flag == 0)
- {
- r = getpids( conn->pid, child_pid );
- if ( r != -1 )
- {
- level++;
- //strcat(tab," ");
- conn->pid = child_pid[0];
- }else
- {
- flag = 1;
- }
- }
- // get the command parameters
- sprintf( child_path, "/proc/%d/cmdline", conn->pid );
- if ( (fh1 = fopen( child_path, "r" )) == NULL)
- {
- printlog(child_path, WARNING, errno);
- return 2;
- }
- fgets( str, 1024, fh1);
- null2space( str );
- sprintf(conn->cmdline, "%s", str);
- fclose(fh1);
- printlog(conn->cmdline, DEBUG, 0);
- if ((strstr(conn->cmdline, "pam") || strstr(conn->cmdline, "net") ) != 0)
- {
- printlog("comdline is pam or net", DEBUG, 0);
- retval = -1;
- }
- // get the command name
- sprintf( child_path, "/proc/%d/comm", conn->pid );
- if ( (fh1= fopen(child_path, "r" )) == NULL)
- {
- printlog(child_path, WARNING, errno);
- return 3;
- }
- fscanf( fh1, "%s", conn->cmd );
- fclose(fh1);
- return retval;
- }
- int main()
- {
- FILE *fh = NULL;
- //FILE *fh1;
- int n_ssh=10;
- int id;
- int pid;
- int y=0;
- int r=0;
- int i;
- int j;
- int n;
- int n_pid=0;
- int start=1;
- int childrens[n_ssh];
- int pids[n_ssh];
- int flag[n_ssh];
- int rinfo;
- int status;
- char ip[42]="";
- char str[1024];
- char date[60];
- time_t now = 0;
- char * language;
- char strlog[128];
- // char * buff;
- struct connexion conn;
- struct connexion connexions[n_ssh];
- struct notify_config ncc;
- //char * ptr;
- strcpy( fn, "main");
- // Loading configuration
- readconfig( &cfg );
- //localizing
- if ( (language = getenv("LANGUAGE")) != NULL)
- {
- strtok (language, ":");
- }else if ( (language = getenv("LC_ALL")) == NULL )
- {
- language="";
- }
- setlocale(LC_ALL,language);
- time( &now );
- sprintf( date, "%s", frtime(now));
- printlog("Démarrage de sshdetect", INFO, 0);
- sprintf( str, "%s \"%s - %s: Démarrage de sshdetect\"", cfg.commande, cfg.hostname, date );
- id=fork();
- if(id == 0)
- {
- r = system( str );
- printlog("str", WARNING, 0);
- exit(r);
- }else if( id<0 )
- {
- sprintf(strlog, "erreur de création du fork: %s", str);
- printlog(strlog, WARNING, 0);
- }
- init_config_watch( cfg.configfile, &ncc);
- while (1)
- {
- memset(&conn, 0, sizeof(conn));
- ip[0] = '\0';
- // get the sshd process ID (PID)
- if ( (fh = fopen("/run/sshd.pid", "r" )) == NULL)
- {
- printlog("/run/sshd.pid", WARNING, errno);
- return 1;
- }
- if ( fscanf(fh, "%i", &pid) == 0)
- {
- printlog("erreur fscanf: /run/sshd.pid", WARNING, 0 );
- return 10;
- }
- fclose(fh);
- sprintf(strlog, "%i", pid);
- printlog(strlog, DEBUG, 0);
- //get the list of children
- if ( (n=getpids( pid, pids )) != -1)
- {
- for ( y=0; y<n; y++)
- {
- pid = pids[y];
- sprintf( strlog, "pid %i", pid);
- printlog(strlog, DEBUG, 0);
- r = isinarray(pid, childrens, n_pid);
- if( r == 0 )
- {
- //conn.user[0]='\0';
- conn.pid=pid;
- rinfo = getprocinfo( &conn );
- if( rinfo == 0 )
- {
- if (conn.host_ip[0] != '\0')
- {
- strcpy(ip,conn.host_ip);
- }else if (conn.host_ipv6[0] != '\0')
- {
- strcpy(ip,conn.host_ipv6);
- }
- n_pid++;
- childrens[n_pid] = pid;
- flag[n_pid] = 1;
- connexions[n_pid] = conn;
- // date of connexion
- if (conn.user[0] == '\0')
- {
- sprintf( str, "%s \"%s: tunnel ouvert depuis %s pid: %d\"", cfg.commande, cfg.hostname, ip, conn.pid );
- }else
- {
- sprintf( str, "%s \"%s: %s s'est connecté depuis %s pid: %d\"", cfg.commande, cfg.hostname, conn.user, ip, conn.pid);
- }
- if ( start != 1 )
- {
- id=fork();
- if (id < 0)
- {
- sprintf(strlog, "erreur de création du fork: %s", str);
- printlog(strlog, WARNING, 0);
- }else if (id == 0)
- {
- printlog(str, INFO, 0);
- r = system( str );
- exit(r);
- }
- }else
- {
- sprintf(strlog, "%s Connecté depuis %s pid=%i ip=%s - %s %s", conn.user, conn.date, conn.pid, ip, conn.cmd, conn.cmdline);
- printlog(strlog, INFO, 0);
- }
- }else if (rinfo == -1)
- {
- sprintf(strlog, "%i => 2 pids : en cours de connexion", conn.pid);
- printlog(strlog, DEBUG, 0);
- }
- }else
- {
- flag[r] = 1;
- }
- }
- }
- for(i=1;i<=n_pid;i++)
- {
- if (flag[i] == 0 )
- {
- time( &now );
- sprintf( date, "%s", frtime(now) );
- sprintf(strlog, "Session %d de %s terminée", connexions[i].pid, connexions[i].user );
- printlog(strlog, INFO, 0);
- //sprintf(strlog, "%s: %s - pid %d - Connexion de %s terminée", connexions[i].date, cfg.hostname, connexions[i].pid, connexions[i].user);
- //printlog(strlog, INFO, 0);
- for( j=i; j<n_pid; j++ )
- {
- childrens[j] = childrens[j+1];
- connexions[j] = connexions[j+1];
- flag[j] = flag[j+1];
- }
- childrens[n_pid] = 0;
- flag[n_pid] = 0;
- i--;
- n_pid--;
- }else
- {
- flag[i] = 0;
- }
- }
- waitpid(-1, &status ,WNOHANG);
- // sleep(1);
- notify_config_change(&ncc, cfg.configfile);
- start = 0;
- }
- return 0;
- }
|