예제 #1
0
파일: pref.cpp 프로젝트: asash/dspam-fork
int _ds_ff_pref_set (
  config_t config,
  const char *username,
  const char *home,
  const char *preference,
  const char *value,
  void *ignore)
{
  char filename[MAX_FILENAME_LENGTH];
  FILE *out_file;
  config = config; /* Keep compiler happy */
  ignore = ignore; /* Keep compiler happy */

  if (username == NULL) {
    snprintf(filename, MAX_FILENAME_LENGTH, "%s/default.prefs", home);
  } else {
    _ds_userdir_path (filename, home, username, "prefs");
  }

  out_file = _ds_ff_pref_prepare_file(filename, preference, NULL);

  if (out_file == NULL)
    return EFAILURE;

  fprintf(out_file, "%s=%s\n", preference, value);

  return _ds_ff_pref_commit(filename, out_file);
}
예제 #2
0
파일: pref.cpp 프로젝트: asash/dspam-fork
int _ds_ff_pref_del (
  config_t config,
  const char *username,
  const char *home,
  const char *preference,
  void *ignore)
{
  char filename[MAX_FILENAME_LENGTH];
  FILE *out_file;
  int nlines; 
  config = config; /* Keep compiler happy */
  ignore = ignore; /* Keep compiler happy */

  if (username == NULL) {
    snprintf(filename, MAX_FILENAME_LENGTH, "%s/default.prefs", home);
  } else {
    _ds_userdir_path (filename, home, username, "prefs");
  }

  out_file = _ds_ff_pref_prepare_file(filename, preference, &nlines);

  if (out_file == NULL)
    return EFAILURE;

  if (!nlines) {
    char backup[MAX_FILENAME_LENGTH];
    fclose(out_file);
    snprintf(backup, sizeof(backup), "%s.bak", filename);
    unlink(backup);
    return unlink(filename);
  }

  return _ds_ff_pref_commit(filename, out_file);
}
예제 #3
0
int
_ds_set_signature (DSPAM_CTX * CTX, struct _ds_spam_signature *SIG,
                   const char *signature)
{
  char filename[MAX_FILENAME_LENGTH];
  char scratch[128];
  FILE *file;

  _ds_userdir_path(filename, 
                   CTX->home, 
                   (CTX->group) ? CTX->group : CTX->username, 
                   "sig");

  snprintf(scratch, sizeof(scratch), "/%s.sig", signature);
  strlcat(filename, scratch, sizeof(filename));
  _ds_prepare_path_for(filename);

  file = fopen(filename, "w");
  if (!file) {
    LOG(LOG_ERR, ERR_IO_FILE_WRITE, filename, strerror(errno));
    return EFAILURE;
  }
  if(fwrite(SIG->data, SIG->length, 1, file)!=1) {
    fclose(file);
    unlink(filename);
    LOG(LOG_ERR, ERR_IO_FILE_WRITING, filename, strerror(errno));
    return(EFAILURE);
  }
  fclose(file);

  return 0;
}
예제 #4
0
파일: pref.c 프로젝트: mark711/mahogany
agent_pref_t _ds_ff_pref_load(
  config_t config,
  const char *user, 
  const char *home,
  void *ignore)
{
  char filename[MAX_FILENAME_LENGTH];
  agent_pref_t PTX = malloc(sizeof(agent_attrib_t )*PREF_MAX);
  char buff[258];
  FILE *file;
  char *p, *q, *bufptr;
  int i = 0;

  UNUSED(config);
  UNUSED(ignore);

  if (PTX == NULL) {
    LOG(LOG_CRIT, ERR_MEM_ALLOC);
    return NULL;
  }
  PTX[0] = NULL;

  if (user == NULL) {
    snprintf(filename, MAX_FILENAME_LENGTH, "%s/default.prefs", home);
  } else {
    _ds_userdir_path (filename, home, user, "prefs");
  }
  file = fopen(filename, "r");
 
  /* Apply default preferences from dspam.conf */
                                                                                
  if (file != NULL) {
    char *ptrptr;
    while(i<(PREF_MAX-1) && fgets(buff, sizeof(buff), file)!=NULL) {
      if (buff[0] == '#' || buff[0] == 0)
        continue;
      chomp(buff);

      bufptr = buff;

      p = strtok_r(buff, "=", &ptrptr);

      if (p == NULL)
        continue;
      q = p + strlen(p)+1;

      LOGDEBUG("Loading preference '%s' = '%s'", p, q);

      PTX[i] = _ds_pref_new(p, q);
      PTX[i+1] = NULL;
      i++;
    }
    fclose(file);
  } else {
    free(PTX);
    return NULL;
  }

  return PTX;
}
예제 #5
0
int
_ds_delete_signature (DSPAM_CTX * CTX, const char *signature)
{
  char filename[MAX_FILENAME_LENGTH];
  char scratch[128];

  _ds_userdir_path(filename, 
                   CTX->home, 
                   (CTX->group) ? CTX->group : CTX->username, 
                   "sig");

  snprintf(scratch, sizeof(scratch), "/%s.sig", signature);
  strlcat(filename, scratch, sizeof(filename));  
  return unlink(filename);
}
예제 #6
0
int
_ds_verify_signature (DSPAM_CTX * CTX, const char *signature)
{
  char filename[MAX_FILENAME_LENGTH];
  char scratch[128];
  struct stat statbuf;

  _ds_userdir_path(filename, 
                   CTX->home, 
                   (CTX->group) ? CTX->group : CTX->username, 
                   "sig");

  snprintf(scratch, sizeof(scratch), "/%s.sig", signature);
  strlcat(filename, scratch, sizeof(filename));

  if (stat (filename, &statbuf)) 
    return 1;

  return 0;
}
예제 #7
0
int
_ds_get_signature (DSPAM_CTX * CTX, struct _ds_spam_signature *SIG,
                   const char *signature)
{
  char filename[MAX_FILENAME_LENGTH];
  char scratch[128];
  FILE *file;
  struct stat statbuf;

  _ds_userdir_path(filename, 
                   CTX->home, 
                   (CTX->group) ? CTX->group : CTX->username,  
                   "sig");

  snprintf(scratch, sizeof(scratch), "/%s.sig", signature);
  strlcat(filename, scratch, sizeof(filename));

  if (stat (filename, &statbuf)) {
    LOG(LOG_ERR, ERR_IO_FILE_OPEN, filename, strerror(errno));
    return EFAILURE;
  };

  SIG->data = malloc(statbuf.st_size);
  if (!SIG->data) {
    LOG(LOG_CRIT, ERR_MEM_ALLOC);
    return EUNKNOWN;
  }

  file = fopen(filename, "r");
  if (!file) {
    LOG(LOG_ERR, ERR_IO_FILE_OPEN, filename, strerror(errno));
    return EFAILURE;
  }
  fread(SIG->data, statbuf.st_size, 1, file);
  SIG->length = statbuf.st_size;
  fclose(file);
  return 0;
}
예제 #8
0
int
_hash_drv_lock_get (
  DSPAM_CTX *CTX,
  struct _hash_drv_storage *s,
  const char *username)
{
  char filename[MAX_FILENAME_LENGTH];
  int r;

  _ds_userdir_path(filename, CTX->home, username, "lock");
  _ds_prepare_path_for(filename);

  s->lock = fopen(filename, "a");
  if (s->lock == NULL) {
    LOG(LOG_ERR, ERR_IO_FILE_WRITE, filename, strerror(errno));
    return EFAILURE;
  }
  r = _ds_get_fcntl_lock(fileno(s->lock));
  if (r) {
    fclose(s->lock);
    LOG(LOG_ERR, ERR_IO_LOCK, filename, r, strerror(errno));
  }
  return r;
}
예제 #9
0
int
_ds_init_storage (DSPAM_CTX * CTX, void *dbh)
{
  struct _sqlite_drv_storage *s;
  FILE *file;
  char buff[1024];
  char filename[MAX_FILENAME_LENGTH];
  char *err=NULL;
  struct stat st;
  int noexist;

  buff[0] = 0;

  if (CTX == NULL)
    return EINVAL;

  if (!CTX->home) {
    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
    return EINVAL;
  } 

  if (CTX->flags & DSF_MERGED) {
    LOG(LOG_ERR, ERR_DRV_NO_MERGED);
    return EINVAL;
  }

  /* don't init if we're already initted */
  if (CTX->storage != NULL)
  {
    LOGDEBUG ("_ds_init_storage: storage already initialized");
    return EINVAL;
  }

  s = malloc (sizeof (struct _sqlite_drv_storage));
  if (s == NULL)
  {
    LOG (LOG_CRIT, ERR_MEM_ALLOC);
    return EUNKNOWN;
  }

  s->dbh = NULL;
  s->control_token = 0;
  s->iter_token = NULL;
  s->iter_sig = NULL;
  s->control_token = 0;
  s->control_sh = 0;
  s->control_ih = 0;
  s->dbh_attached = (dbh) ? 1 : 0;

  if (CTX->group == NULL || CTX->group[0] == 0)
    _ds_userdir_path (filename, CTX->home, CTX->username, "sdb");
  else
    _ds_userdir_path (filename, CTX->home, CTX->group, "sdb");
  _ds_prepare_path_for (filename);

  noexist = stat(filename, &st);

  if (dbh)
    s->dbh = dbh;
  else
    s->dbh = sqlite_open(filename, 0660, &err);
                                                                                
  if (s->dbh == NULL)
  {
    LOGDEBUG
      ("_ds_init_storage: sqlite_open: unable to initialize database: %s", err);    return EUNKNOWN;
  }

  /* Commit timeout of 20 minutes */
  sqlite_busy_timeout(s->dbh, 1000 * 60 * 20);

  /* Create database objects */

  if (noexist) {

    sqlite_exec(s->dbh, 
                "create table dspam_token_data (token char(20) primary key, "
                "spam_hits int, innocent_hits int, last_hit date)",
                NULL,
                NULL,
                &err);

    sqlite_exec(s->dbh,
                "create index id_token_data_02 on dspam_token_data"
                "(innocent_hits)",
                NULL,
                NULL,
                &err);

    sqlite_exec(s->dbh,
                "create table dspam_signature_data ("
                "signature char(128) primary key, data blob, created_on date)",
                NULL,
                NULL,
                &err);
                                                                                
    sqlite_exec(s->dbh,
                "create table dspam_stats (dspam_stat_id int primary key, "
                "spam_learned int, innocent_learned int, "
                "spam_misclassified int, innocent_misclassified int, "
                "spam_corpusfed int, innocent_corpusfed int, "
                "spam_classified int, innocent_classified int)",
                NULL,
                NULL,
                &err);
  }

  if (_ds_read_attribute(CTX->config->attributes, "SQLitePragma")) {
    char pragma[1024];
    attribute_t t = _ds_find_attribute(CTX->config->attributes, "SQLitePragma");
    while(t != NULL) {
      snprintf(pragma, sizeof(pragma), "PRAGMA %s", t->value);
      if ((sqlite_exec(s->dbh, pragma, NULL, NULL, &err))!=SQLITE_OK)
      {
        LOG(LOG_WARNING, "sqlite.pragma function error: %s: %s", err, pragma);
        _sqlite_drv_query_error (err, pragma);
      }
      t = t->next;
    } 
  } else if (CTX->home) {
    snprintf(filename, MAX_FILENAME_LENGTH, "%s/sqlite.pragma", CTX->home);
    file = fopen(filename, "r");
    if (file != NULL) {
      while((fgets(buff, sizeof(buff), file))!=NULL) {
        chomp(buff);
        if ((sqlite_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK)
        {
          LOG(LOG_WARNING, "sqlite.pragma function error: %s: %s", err, buff);
          _sqlite_drv_query_error (err, buff);
        }
      }
      fclose(file);
    }
  }

  CTX->storage = s;
  s->dir_handles = nt_create (NT_INDEX);

  s->control_token = 0;
  s->control_ih = 0;
  s->control_sh = 0; 

  /* get spam totals on successful init */
  if (CTX->username != NULL)
  {
      if (_sqlite_drv_get_spamtotals (CTX))
      {
        LOGDEBUG ("unable to load totals.  using zero values.");
      }
  }
  else
  {
    memset (&CTX->totals, 0, sizeof (struct _ds_spam_totals));
    memset (&s->control_totals, 0, sizeof (struct _ds_spam_totals));
  }

  return 0;
}
예제 #10
0
int
dspam_init_driver (DRIVER_CTX *DTX)
{
  DSPAM_CTX *CTX;
  char *HashConcurrentUser;
#ifdef DAEMON
   unsigned long connection_cache = 1;
#endif

  if (DTX == NULL) 
    return 0;

  CTX = DTX->CTX;
  HashConcurrentUser = READ_ATTRIB("HashConcurrentUser");

#ifdef DAEMON

  /*
   *  Stateful concurrent hash databases are preloaded into memory and
   *  shared using a reader-writer lock. At the present moment, only a single
   *  user can be loaded into any instance of the daemon, so it is only useful
   *  if you are running with a system-wide filtering user. 
   */

  if (DTX->flags & DRF_STATEFUL) {
    char filename[MAX_FILENAME_LENGTH];
    hash_drv_map_t map;
    unsigned long hash_rec_max = HASH_REC_MAX;
    unsigned long max_seek     = HASH_SEEK_MAX;
    unsigned long max_extents  = 0;
    unsigned long extent_size  = HASH_EXTENT_MAX;
    int pctincrease = 0;
    int flags = HMAP_AUTOEXTEND;
    int ret, i;

    if (READ_ATTRIB("HashConnectionCache") && !HashConcurrentUser)
      connection_cache = strtol(READ_ATTRIB("HashConnectionCache"), NULL, 0);

    DTX->connection_cache = connection_cache;

    if (READ_ATTRIB("HashRecMax"))
      hash_rec_max = strtol(READ_ATTRIB("HashRecMax"), NULL, 0);

    if (READ_ATTRIB("HashExtentSize"))
      extent_size = strtol(READ_ATTRIB("HashExtentSize"), NULL, 0);

    if (READ_ATTRIB("HashMaxExtents"))
      max_extents = strtol(READ_ATTRIB("HashMaxExtents"), NULL, 0);

    if (!MATCH_ATTRIB("HashAutoExtend", "on"))
      flags = 0;

    if (READ_ATTRIB("HashPctIncrease")) {
      pctincrease = atoi(READ_ATTRIB("HashPctIncrease"));
      if (pctincrease > 100) {
          LOG(LOG_ERR, "HashPctIncrease out of range; ignoring");
          pctincrease = 0;
      }
    }

    if (READ_ATTRIB("HashMaxSeek"))
       max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0);

    /* Connection array (just one single connection for hash_drv) */
    DTX->connections = calloc(1, sizeof(struct _ds_drv_connection *) * connection_cache);
    if (DTX->connections == NULL) 
      goto memerr;

    /* Initialize Connections */
    for(i=0;i<connection_cache;i++) {
      DTX->connections[i] = calloc(1, sizeof(struct _ds_drv_connection));
      if (DTX->connections[i] == NULL) 
        goto memerr;

      /* Our connection's storage structure */
      if (HashConcurrentUser) {
        DTX->connections[i]->dbh = calloc(1, sizeof(struct _hash_drv_map));
        if (DTX->connections[i]->dbh == NULL) 
          goto memerr;
        pthread_rwlock_init(&DTX->connections[i]->rwlock, NULL);
      } else {
        DTX->connections[i]->dbh = NULL;
        pthread_mutex_init(&DTX->connections[i]->lock, NULL);
      }
    }

    /* Load concurrent database into resident memory */
    if (HashConcurrentUser) {
      map = (hash_drv_map_t) DTX->connections[0]->dbh;

      /* Tell the server our connection lock will be reader/writer based */
      if (!(DTX->flags & DRF_RWLOCK))
        DTX->flags |= DRF_RWLOCK;

      _ds_userdir_path(filename, DTX->CTX->home, HashConcurrentUser, "css");
      _ds_prepare_path_for(filename);
      LOGDEBUG("preloading %s into memory via mmap()", filename);
      ret = _hash_drv_open(filename, map, hash_rec_max, 
          max_seek, max_extents, extent_size, pctincrease, flags); 

      if (ret) {
        LOG(LOG_CRIT, "_hash_drv_open(%s) failed on error %d: %s", 
                      filename, ret, strerror(errno)); 
        free(DTX->connections[0]->dbh);
        free(DTX->connections[0]);
        free(DTX->connections);
        return EFAILURE;
      }
    }
  }
#endif

  return 0;

#ifdef DAEMON
memerr:
  if (DTX) {
    if (DTX->connections) {
      int i;
      for(i=0;i<connection_cache;i++) {
        if (DTX->connections[i]) 
          free(DTX->connections[i]->dbh);
        free(DTX->connections[i]);
      }
    }
    free(DTX->connections);
  }
  LOG(LOG_CRIT, ERR_MEM_ALLOC);
  return EUNKNOWN;
#endif
  
}
예제 #11
0
int
_ds_init_storage (DSPAM_CTX * CTX, void *dbh)
{
  struct _hash_drv_storage *s = NULL;
  hash_drv_map_t map = NULL;
  int ret;

  if (CTX == NULL)
    return EINVAL;

  if (!CTX->home) {
    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
    return EINVAL;
  }

  if (CTX->flags & DSF_MERGED) {
    LOG(LOG_ERR, ERR_DRV_NO_MERGED);
    return EINVAL;
  }

  if (CTX->storage)
    return EINVAL;

  /* Persistent driver storage */

  s = calloc (1, sizeof (struct _hash_drv_storage));
  if (s == NULL)
  {
    LOG(LOG_CRIT, ERR_MEM_ALLOC);
    return EUNKNOWN;
  }

  /* If running in HashConcurrentUser mode, use existing hash mapping */

  if (dbh) {
    map = dbh;
    s->dbh_attached = 1;
  } else {
    map = calloc(1, sizeof(struct _hash_drv_map));
    if (!map) {
      LOG(LOG_CRIT, ERR_MEM_ALLOC);
      free(s);
      return EUNKNOWN;
    }
    s->dbh_attached = 0;
  }

  s->map = map;

  /* Mapping defaults */

  s->hash_rec_max = HASH_REC_MAX;
  s->max_seek     = HASH_SEEK_MAX;
  s->max_extents  = 0;
  s->extent_size  = HASH_EXTENT_MAX;
  s->pctincrease  = 0;
  s->flags        = HMAP_AUTOEXTEND;

  if (READ_ATTRIB("HashRecMax"))
    s->hash_rec_max = strtol(READ_ATTRIB("HashRecMax"), NULL, 0);

  if (READ_ATTRIB("HashExtentSize"))
    s->extent_size = strtol(READ_ATTRIB("HashExtentSize"), NULL, 0);

  if (READ_ATTRIB("HashMaxExtents"))
    s->max_extents = strtol(READ_ATTRIB("HashMaxExtents"), NULL, 0);

  if (!MATCH_ATTRIB("HashAutoExtend", "on"))
    s->flags = 0;

  if (READ_ATTRIB("HashPctIncrease")) {
    s->pctincrease = atoi(READ_ATTRIB("HashPctIncrease"));
    if (s->pctincrease > 100) {
        LOG(LOG_ERR, "HashPctIncrease out of range; ignoring");
        s->pctincrease = 0;
    }
  }

  if (READ_ATTRIB("HashMaxSeek"))
    s->max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0);

  if (!dbh && CTX->username != NULL)
  {
    char db[MAX_FILENAME_LENGTH];
    int lock_result;

    if (CTX->group == NULL)
      _ds_userdir_path(db, CTX->home, CTX->username, "css");
    else
      _ds_userdir_path(db, CTX->home, CTX->group, "css");

    lock_result = _hash_drv_lock_get (CTX, s, 
      (CTX->group) ? CTX->group : CTX->username);
    if (lock_result < 0) 
      goto BAIL;

    ret = _hash_drv_open(db, s->map, s->hash_rec_max, s->max_seek, 
        s->max_extents, s->extent_size, s->pctincrease, s->flags);

    if (ret) {
      _hash_drv_close(s->map);
      free(s);
      return EFAILURE;
    }
  }

  CTX->storage = s;
  s->dir_handles = nt_create (NT_INDEX);

  if (_hash_drv_get_spamtotals (CTX))
  {
    LOGDEBUG ("unable to load totals.  using zero values.");
    memset (&CTX->totals, 0, sizeof (struct _ds_spam_totals));
  }

  return 0;

BAIL:
  free(s);
  return EFAILURE;
}