[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: detecter sessions SSH



En C un peu propre (donc pas de system/exec), comme dit precedemment, libproc-dev.

Sinon tu t'amuse toi-meme a scanner /proc. C'est juste (presque tres!) fastidieux.
Pour le fun, je t'ai fais un exemple sans pretention.

Perl et autres, beaucoup plus facile et rapide. C.f. le module Proc::ProcessTable
par example pour perl.

A+, JD.

On Thursday 28 April 2005 13:46, Frederic Beck wrote:
FB > non c'est pas que je debute, je connais system ou la famille exec, mais
FB > system ne m'arrange pas car je ne peux pas récupérer la sortie

-- 
Jean-Damien Durand CERN/IT/FIO/DS - Geneva, Switzerland
PGP: http://home.cern.ch/~jdurand/public_key.asc
CERN CA: http://cern.ch/service-grid-ca/crt/root_crt.html
WWW: http://home.cern.ch/~jdurand
/* Basic, stupid and al. example on how to one can use /proc */
/* Fits on systems where ssh pid is _correctly_ launched as a */
/* daemon and stored its pid in /var/run/sshd.pid */

/* cc -Wall -o sshspy sshspy.c; ./sshspy */

#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#define SSH_PID "/var/run/sshd.pid"

static int sshspydoit(int);
static char *readlink_malloc(char *);

int main() {
  int sshpidfd;
  char buf[21];
  int sshpid = 0;
  int nssh;

  /* Recupere sshd pid */
  if ((sshpidfd = open(SSH_PID,O_RDONLY)) < 0) {
    perror(SSH_PID);
  } else {
    /* Will it ever be more than 21 bytes !? */
    if (read(sshpidfd,buf,21) <= 0) {
      perror(SSH_PID);
    } else {
      memset(buf,20,'\0');
      if ((sshpid = atoi(buf)) <= 0) {
	fprintf(stderr,"Negative ssh pid in %s !?\n", SSH_PID);
	sshpid = 0;
      }
      close(sshpidfd);
    }
  }


  if (sshpid == 0) {
    fprintf(stderr,"Warning - you are likely to match ssh master daemon\n");
  }

  if (getuid() != 0) {
    fprintf(stderr,"Warning - you will not match all sessions unless you are root\n");
  }

  nssh = sshspydoit(sshpid);
  fprintf(stdout,"%d ssh session%s found\n", nssh, nssh > 1 ? "s" : "");
  exit(EXIT_SUCCESS);
}

static int sshspydoit(sshpid)
     int sshpid;
{
  int rc = 0;
  DIR *proc_dir;

  if ((proc_dir = opendir("/proc")) == NULL) {
    perror("/proc");
  } else {
    int proc_dir_return_code;
    struct dirent proc_dir_entry;
    struct dirent *proc_dir_result;

    for (proc_dir_return_code = readdir_r(proc_dir, &proc_dir_entry, &proc_dir_result);
	 proc_dir_result != NULL && proc_dir_return_code == 0;
	 proc_dir_return_code = readdir_r(proc_dir, &proc_dir_entry, &proc_dir_result)) {
      char *fullpath;
      struct stat statbuf;
      char *filename;

      /* Let's scan entries that have onlt digits */
      if (strspn(proc_dir_entry.d_name,"1234567890") != strlen(proc_dir_entry.d_name)) {
	continue;
      }

      /* Master ssh pid !? */
      if (atoi(proc_dir_entry.d_name) == sshpid) {
	continue;
      }

      /* We will stat /proc/proc_dir_entry.d_name/exe and /proc/proc_dir_entry.d_name/stat and */
      if ((fullpath = (char *) malloc(strlen("/proc/") + strlen(proc_dir_entry.d_name) + strlen("/exe") + 2)) == NULL) {
	perror("malloc");
	continue;
      }

      strcpy(fullpath,"/proc/");
      strcat(fullpath,proc_dir_entry.d_name);
      strcat(fullpath,"/exe");

      if (stat(fullpath,&statbuf) == 0) {
	/* This is a link - only linux we expect so */
	if ((filename = readlink_malloc(fullpath)) != NULL) {
	  char *p;

	  /* Ends with "/sshd" ? */
	  if ((p = strrchr(filename,'/')) != NULL) {
	    *p++ = '\0';
	    if (strcmp(p,"sshd") == 0) {

	      *--p = '/';

	      /* Try to open /proc/pid/stat if we know the sshd master */
	      if (sshpid > 0) {
		int fd;

		strcpy(fullpath,"/proc/");
		strcat(fullpath,proc_dir_entry.d_name);
		strcat(fullpath,"/stat");

		if ((fd = open(fullpath,O_RDONLY)) >= 0) {
		  char buf[4097];
		  /* We are only interested in the token No 4: pid (command) state ppid ... */
		  /* This cannot exceed 4096 bytes - can it ? */
		  memset(buf,4096,'\0');
		  if (read(fd,buf,4096) > 0) {
		    char *p;
		    char *last = NULL;

		    buf[4096] = '\0';
		    /* I hate sscanf - that's all */
		    if ((p = strtok_r(buf," ",&last)) != NULL) {        /* pid */
		      if ((p = strtok_r(NULL," ",&last)) != NULL) {     /* (command) */
			if ((p = strtok_r(NULL," ",&last)) != NULL) {   /* state */
			  if ((p = strtok_r(NULL," ",&last)) != NULL) { /* ppid */
			    int ppid = atoi(p);
			    if (ppid == sshpid) {
			      fprintf(stdout,"PID=%s PPID=%d %s\n", proc_dir_entry.d_name, ppid, filename);
			      ++rc;
			    } else if (ppid == 1) {
			      fprintf(stdout,"PID%s PPID=%d %s (orphaned !?)\n", proc_dir_entry.d_name, ppid, filename);
			      ++rc;
			    }
			  }
			}
		      }
		    }
		  }
		  close(fd);
		}
	      }
	    }
	  }
	  free(filename);
	}
      }
      free(fullpath);
    }
    closedir(proc_dir);
  }
  return(rc);
}

static char *readlink_malloc(filename)
     char *filename;
{
  int size = 100;

  while (1) {
      char *buffer = (char *) calloc(size,1);
      if (buffer == NULL) {
	perror("calloc");
	return(NULL);
      }
      int nchars = readlink (filename, buffer, size);
      if (nchars < 0) {
	perror(filename);
	return(NULL);
      }
      if (nchars < size) {
	return(buffer);
      }
      free (buffer);
      size *= 2;
    }
}

Attachment: smime.p7s
Description: S/MIME cryptographic signature


Reply to: