Beispiel #1
0
int
process_all_users (void)
{
  DSPAM_CTX *CTX;
  char *user;

  CTX = dspam_create (NULL, NULL, _ds_read_attribute(agent_config, "Home"), DSM_TOOLS, 0);
  open_ctx = CTX;
  if (CTX == NULL)
  {
    fprintf (stderr, "Could not initialize context: %s\n", strerror (errno));
    return EFAILURE;
  }

  set_libdspam_attributes(CTX);
  if (dspam_attach(CTX, NULL)) {
    LOG (LOG_WARNING, "unable to attach dspam context");
    fprintf (stderr, "Unable to attach DSPAM context\n");
    return EFAILURE;
  }


  user = _ds_get_nextuser (CTX);
  while (user != NULL)
  {
    dump_user (user);
    user = _ds_get_nextuser (CTX);
  }

  dspam_destroy (CTX);
  open_ctx = NULL;
  return 0;
}
Beispiel #2
0
int list_aggregate_preference_attributes(const char *username)
{
  agent_pref_t PTX = NULL;
  agent_pref_t STX = NULL;
  agent_pref_t UTX = NULL;
  agent_attrib_t pref;
  int i;
  
  STX =  _ds_pref_load(agent_config,
                       NULL,
                       _ds_read_attribute(agent_config, "Home"), NULL);

  if (STX == NULL || STX[0] == 0) {
    if (STX) {
      _ds_pref_free(STX);
    }
    LOGDEBUG("default preferences empty. reverting to dspam.conf preferences.");
    STX = pref_config();
  } else {
    LOGDEBUG("loaded default preferences externally");
  }

  if (username[0] == 0 || !strncmp(username, "default", strlen(username)))
    UTX = _ds_pref_load(agent_config, NULL, _ds_read_attribute(agent_config, "Home"), NULL);
  else {
    UTX = _ds_pref_load(agent_config, username,  _ds_read_attribute(agent_config, "Home"), NULL);
  }

  PTX = _ds_pref_aggregate(STX, UTX);
  _ds_pref_free(STX);
  free(STX);
  if (UTX != NULL) {
    _ds_pref_free(UTX);
    free(UTX);
  }

  for(i=0;PTX[i];i++) {
    pref = PTX[i];
    printf("%s=%s\n", pref->attribute, pref->value);
  }

  _ds_pref_free(PTX);
  free(PTX);
  return 0;
}
Beispiel #3
0
int del_preference_attribute(
  const char *username,
  const char *attr)
{
  int i;

  if (username[0] == 0 || !strncmp(username, "default", strlen(username)))
    i = _ds_pref_del(agent_config, NULL, _ds_read_attribute(agent_config, "Home"), attr, NULL);
  else
    i = _ds_pref_del(agent_config, username, _ds_read_attribute(agent_config, "Home"), attr, NULL);

  if (!i)
    printf("operation successful.\n");
  else
    printf("operation failed with error %d.\n", i);

  return i;
}
Beispiel #4
0
int set_preference_attribute(
  const char *username, 
  const char *attr, 
  const char *value)
{
  int i;

  if (username[0] == 0 || !strcmp(username, "default"))
    i = _ds_pref_set(agent_config, NULL, _ds_read_attribute(agent_config, "Home"), attr, value, NULL);
  else
    i = _ds_pref_set(agent_config, username, _ds_read_attribute(agent_config, "Home"), attr, value, NULL);

  if (!i) 
    printf("operation successful.\n");
  else
    printf("operation failed with error %d.\n", i);

  return i;
}
Beispiel #5
0
int attach_context(DSPAM_CTX *CTX, void *dbh) {
  int maxtries = 1, tries = 0;
  int r;

  if (!_ds_read_attribute(agent_config, "DefaultProfile"))
    return dspam_attach(CTX, dbh);

  /* Perform failover if an attach fails */

  if (_ds_read_attribute(agent_config, "FailoverAttempts"))
    maxtries = atoi(_ds_read_attribute(agent_config, "FailoverAttempts"));

  r = dspam_attach(CTX, dbh);
  while (r && tries < maxtries) {
    char key[128];
    char *failover;

    snprintf(key, sizeof(key), "Failover.%s", _ds_read_attribute(agent_config, "DefaultProfile"));

    failover = _ds_read_attribute(agent_config, key);

    if (!failover) {
      LOG(LOG_ERR, ERR_AGENT_FAILOVER_OUT);
      return r;
    }

    LOG(LOG_WARNING, ERR_AGENT_FAILOVER, failover);
    _ds_overwrite_attribute(agent_config, "DefaultProfile", failover);

    if (dspam_clearattributes(CTX)) {
      LOG(LOG_ERR, ERR_AGENT_CLEAR_ATTRIB);
      return r;
    }

    set_libdspam_attributes(CTX);

    tries++;
    r = dspam_attach(CTX, dbh);
  }

  return r;
}
Beispiel #6
0
int set_libdspam_attributes(DSPAM_CTX *CTX) {
  attribute_t t;
  int i, ret = 0;
  char *profile;

  t = _ds_find_attribute(agent_config, "IgnoreHeader");
  while(t) {
    ret += dspam_addattribute(CTX, t->key, t->value);
    t = t->next;
  }

  profile = _ds_read_attribute(agent_config, "DefaultProfile");

  for(i=0;agent_config[i];i++) {
    t = agent_config[i];

    while(t) {

      if (!strncasecmp(t->key, "MySQL", 5)  ||
          !strncasecmp(t->key, "PgSQL", 5)  ||
          !strncasecmp(t->key, "Ora", 3)    ||
          !strncasecmp(t->key, "SQLite", 6) ||
          !strcasecmp(t->key, "LocalMX")    ||
          !strncasecmp(t->key, "LDAP", 4)   ||
          !strncasecmp(t->key, "Storage", 7) ||
          !strncasecmp(t->key, "Processor", 9) ||
          !strncasecmp(t->key, "Hash", 4))
      {
        if (profile == NULL || profile[0] == 0)
        {
          ret += dspam_addattribute(CTX, t->key, t->value);
        }
        else if (strchr(t->key, '.'))
        {
          if (!strcasecmp((strchr(t->key, '.')+1), profile)) {
            char *x = strdup(t->key);
            char *y = strchr(x, '.');
            y[0] = 0;

            ret += dspam_addattribute(CTX, x, t->value);
            free(x);
          }
        }
      }
      t = t->next;
    }
  }

  ret += configure_algorithms(CTX);

  return ret;
}
Beispiel #7
0
int list_preference_attributes(const char *username)
{
  agent_pref_t PTX;
  agent_attrib_t pref;
  int i;
  
  if (username[0] == 0 || !strncmp(username, "default", strlen(username)))
    PTX = _ds_pref_load(agent_config, NULL, _ds_read_attribute(agent_config, "Home"), NULL);
  else
    PTX = _ds_pref_load(agent_config, username,  _ds_read_attribute(agent_config, "Home"), NULL);

  if (PTX == NULL) 
    return 0;

  for(i=0;PTX[i];i++) {
    pref = PTX[i];
    printf("%s=%s\n", pref->attribute, pref->value);
  }

  _ds_pref_free(PTX);
  free(PTX);
  return 0;
}
Beispiel #8
0
int
dump_user (const char *username)
{
  struct passwd *p;
  struct _ds_storage_record *record;
  DSPAM_CTX *CTX;

  p = getpwnam (username);
  if (p == NULL)
  {
    fprintf (stderr, "Unable to obtain uid for user %s\n", username);
    return EUNKNOWN;
  }

  CTX = dspam_create (username, NULL, _ds_read_attribute(agent_config, "Home"), DSM_CLASSIFY, 0);
  open_mtx = CTX;
  if (CTX == NULL)
  {
    fprintf (stderr, "Could not init context: %s\n", strerror (errno));
    return EUNKNOWN;
  }

  set_libdspam_attributes(CTX);
  if (dspam_attach(CTX, NULL)) {
    LOG (LOG_WARNING, "unable to attach dspam context");
    fprintf (stderr, "Unable to attach DSPAM context\n");
    return EFAILURE;
  }

  printf
    ("insert into dspam_stats (uid, spam_learned, innocent_learned, spam_misclassified, innocent_misclassified, spam_corpusfed, innocent_corpusfed, spam_classified, innocent_classified) values(%d, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld);\n",
     (int) p->pw_uid, CTX->totals.spam_learned, CTX->totals.innocent_learned,
     CTX->totals.spam_misclassified, CTX->totals.innocent_misclassified,
     CTX->totals.spam_corpusfed, CTX->totals.innocent_corpusfed,
     CTX->totals.spam_classified, CTX->totals.innocent_classified);

  record = _ds_get_nexttoken (CTX);
  while (record != NULL)
  {
    printf
      ("insert into dspam_token_data (uid, token, spam_hits, innocent_hits, last_hit) values(%d, \"%"LLU_FMT_SPEC"\", %ld, %ld, %ld);\n",
       (int) p->pw_uid, record->token, record->spam_hits,
       record->innocent_hits, (long) record->last_hit);
    record = _ds_get_nexttoken (CTX);
  }

  dspam_destroy (CTX);
  open_mtx = NULL;
  return 0;
}
Beispiel #9
0
int configure_algorithms(DSPAM_CTX *CTX) {
  if (_ds_read_attribute(agent_config, "Algorithm"))
    CTX->algorithms = 0;
                                                                                
  if (_ds_match_attribute(agent_config, "Algorithm", "graham"))
    CTX->algorithms |= DSA_GRAHAM;
                                                                                
  if (_ds_match_attribute(agent_config, "Algorithm", "burton"))
    CTX->algorithms |= DSA_BURTON;
                                                                                
  if (_ds_match_attribute(agent_config, "Algorithm", "robinson"))
    CTX->algorithms |= DSA_ROBINSON;

  if (_ds_match_attribute(agent_config, "Algorithm", "naive"))
    CTX->algorithms |= DSA_NAIVE;
                                                                                
  if (_ds_match_attribute(agent_config, "PValue", "robinson"))
    CTX->algorithms |= DSP_ROBINSON;
  else if (_ds_match_attribute(agent_config, "PValue", "markov"))
    CTX->algorithms |= DSP_MARKOV;
  else
    CTX->algorithms |= DSP_GRAHAM;

  if (_ds_match_attribute(agent_config, "Tokenizer", "word")) 
    CTX->tokenizer = DSZ_WORD;
  else if (_ds_match_attribute(agent_config, "Tokenizer", "chain") ||
           _ds_match_attribute(agent_config, "Tokenizer", "chained"))
    CTX->tokenizer = DSZ_CHAIN;
  else if (_ds_match_attribute(agent_config, "Tokenizer", "sbph"))
    CTX->tokenizer = DSZ_SBPH;
  else if (_ds_match_attribute(agent_config, "Tokenizer", "osb"))
    CTX->tokenizer = DSZ_OSB;
 
  if (_ds_match_attribute(agent_config, "Algorithm", "chi-square"))
  {
    if (CTX->algorithms != 0 && CTX->algorithms != DSP_ROBINSON) {
      LOG(LOG_WARNING, "Warning: Chi-Square algorithm enabled with other algorithms. False positives may ensue.");
    }
    CTX->algorithms |= DSA_CHI_SQUARE;
  }

  return 0;
}
Beispiel #10
0
char*
external_lookup(config_t agent_config, const char *username, char *external_uid)
{

	char *driver = _ds_read_attribute(agent_config, "ExtLookupDriver");

	if (strcmp(driver, "ldap") == 0) {
#ifdef USE_LDAP
		return ldap_lookup(agent_config, username, external_uid);
#else
		LOG(LOG_ERR, "external_lookup: LDAP driver was not enabled at compile time.");
		return NULL;
#endif
	} else if (strcmp(driver, "program") == 0) {
		return program_lookup(agent_config, username, external_uid);
	/* add here your 'else if' statements like the one above to extend */
	} else if (driver == NULL) {
		LOG(LOG_ERR, "external_lookup: lookup driver not defined");
		return NULL;
	} else {
		LOG(LOG_ERR, "external_lookup: lookup driver %s not yet implemented.", driver);
		return NULL;
	}
}
Beispiel #11
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;
}
Beispiel #12
0
int
main (int argc, char *argv[])
{
  AGENT_CTX ATX;
  int exitcode = EXIT_SUCCESS;
  buffer *message = NULL;       /* input Message */
  int agent_init = 0;		/* agent is initialized */

  setbuf (stdout, NULL);	/* unbuffered output */
#ifdef DEBUG
  DO_DEBUG = 0;
#endif

  srand ((long) time << (long) getpid());
  umask (006);

#ifndef DAEMON
  LOG(LOG_ERR, ERR_DAEMON_NO_SUPPORT);
  exit(EXIT_FAILURE);
#endif

  /* Read dspam.conf into global config structure (ds_config_t) */

  agent_config = read_config(NULL);
  if (!agent_config) {
    LOG(LOG_ERR, ERR_AGENT_READ_CONFIG);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  if (!_ds_read_attribute(agent_config, "Home")) {
    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  /* Set up agent context to define behavior of processor */

  if (initialize_atx(&ATX)) {
    LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  } else {
    agent_init = 1;
  }

  if (process_arguments(&ATX, argc, argv)) {
    LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  if (apply_defaults(&ATX)) {
    LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  if (check_configuration(&ATX)) {
    LOG(LOG_ERR, ERR_AGENT_MISCONFIGURED);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  /* Read the message in and apply ParseTo services */

  message = read_stdin(&ATX);
  if (message == NULL) {
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  if (ATX.users->items == 0)
  {
    LOG (LOG_ERR, ERR_AGENT_USER_UNDEFINED);
    fprintf (stderr, "%s\n", SYNTAX);
    exitcode = EXIT_FAILURE;
    goto BAIL;
  }

  /* Perform client-based processing */

#ifdef DAEMON
  if (_ds_read_attribute(agent_config, "ClientIdent") &&
      (_ds_read_attribute(agent_config, "ClientHost") ||
       _ds_read_attribute(agent_config, "ServerDomainSocketPath")))
  {
    exitcode = client_process(&ATX, message);
  } else {
    LOG(LOG_ERR, ERR_CLIENT_INVALID_CONFIG);
    exitcode = EINVAL;
  }
#endif

BAIL:

  if (message)
    buffer_destroy(message);

  if (agent_init)
    nt_destroy(ATX.users);

  if (agent_config)
    _ds_destroy_config(agent_config);

  exit (exitcode);
}
Beispiel #13
0
/*
** Code taken from pgsql_drv.c
*/
void OutputMessage(DSPAM_CTX *open_ctx,char *sqlfile)
{
    FILE *file;
    char filename[MAX_FILENAME_LENGTH];
    char buffer[256];
    char hostname[128] = "";
    char user[64] = "";
    char db[64] = "";
    int port = 5432, i = 0;
    if (_ds_read_attribute(open_ctx->config->attributes, "PgSQLServer")) {
        char *p;

        strlcpy(hostname,
                _ds_read_attribute(open_ctx->config->attributes, "PgSQLServer"),
                sizeof(hostname));

        if (_ds_read_attribute(open_ctx->config->attributes, "PgSQLPort"))
            port = atoi(_ds_read_attribute(open_ctx->config->attributes, "PgSQLPort"));
        else
            port = 0;

        if ((p = _ds_read_attribute(open_ctx->config->attributes, "PgSQLUser")))
            strlcpy(user, p, sizeof(user));
        if ((p = _ds_read_attribute(open_ctx->config->attributes, "PgSQLDb")))
            strlcpy(db, p, sizeof(db));

    } else {
        snprintf (filename, MAX_FILENAME_LENGTH, "%s/pgsql.data", open_ctx->home);
        file = fopen (filename, "r");
        if (file == NULL)
        {
            fprintf(stderr, "Failed to open config file %s - %s\n",
                    filename, strerror(errno));
            dieout(0);
        }

        db[0] = 0;

        while (fgets (buffer, sizeof (buffer), file) != NULL)
        {
            chomp (buffer);
            if (!i)
                strlcpy (hostname, buffer, sizeof (hostname));
            else if (i == 1)
                port = atoi (buffer);
            else if (i == 2)
                strlcpy (user, buffer, sizeof (user));
            else if (i == 4)
                strlcpy (db, buffer, sizeof (db));
            i++;
        }
        fclose (file);
    }

    if (db[0] == 0)
    {
        fprintf(stderr, "file %s: incomplete pgsql connect data", filename);
        dieout(0);
    }

    if (port == 0) port = 5432;

    fprintf(stderr, "Created SQL in %s; run using:\n", sqlfile);

    if ( strlen(hostname) == 0 )
        fprintf(stderr, "\tpsql -q -p %d -U %s -d %s -f %s -v AUTOCOMMIT=off\n",
                port, user, db, sqlfile);
    else
        fprintf(stderr, "\tpsql -q -h %s -p %d -U %s -d %s -f %s -v AUTOCOMMIT=off\n",
                hostname, port, user, db, sqlfile);

}
Beispiel #14
0
int
main (int argc, char **argv)
{
#ifndef _WIN32
#ifdef TRUSTED_USER_SECURITY
    struct passwd *p = getpwuid (getuid ());
#endif
#endif
    struct _pgsql_drv_storage *store;
    char file[PATH_MAX+1];
    int i, ch;
#ifndef HAVE_GETOPT
    int optind = 1;
#endif

    /* Read dspam.conf */

    agent_config = read_config(NULL);
    if (!agent_config) {
        LOG(LOG_ERR, ERR_AGENT_READ_CONFIG);
        exit(EXIT_FAILURE);
    }

    if (!_ds_read_attribute(agent_config, "Home")) {
        LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
        _ds_destroy_config(agent_config);
        exit(EXIT_FAILURE);
    }

#ifndef _WIN32
#ifdef TRUSTED_USER_SECURITY
    if (!_ds_match_attribute(agent_config, "Trust", p->pw_name) && p->pw_uid) {
        fprintf(stderr, ERR_TRUSTED_MODE "\n");
        _ds_destroy_config(agent_config);
        exit(EXIT_FAILURE);
    }
#endif
#endif

    for(i=0; i<argc; i++) {

        if (!strncmp (argv[i], "--profile=", 10))
        {
            if (!_ds_match_attribute(agent_config, "Profile", argv[i]+10)) {
                LOG(LOG_ERR, ERR_AGENT_NO_SUCH_PROFILE, argv[i]+10);
                _ds_destroy_config(agent_config);
                exit(EXIT_FAILURE);
            } else {
                _ds_overwrite_attribute(agent_config, "DefaultProfile", argv[i]+10);
            }
            break;
        }
    }

    open_ctx = open_mtx = NULL;

    signal (SIGINT, dieout);
    signal (SIGPIPE, dieout);
    signal (SIGTERM, dieout);

    /* Process command line */
    ch = 0;
#ifdef HAVE_GETOPT
    while((ch = getopt(argc, argv, "h")) != -1)
#else
    while ( argv[optind] &&
            argv[optind][0] == '-' &&
            (ch = argv[optind][1]) &&
            argv[optind][2] == '\0' )
#endif
    {
        switch(ch) {
        case 'h':
            /* print help, and then exit. usage exits for us */
            usage();
            break;

#ifndef HAVE_GETOPT
        default:
            fprintf(stderr, "%s: unknown option \"%s\".\n",
                    argv[0], argv[optind] + 1);
            usage();
#endif
        }
#ifndef HAVE_GETOPT
        optind++;
#endif
    }
    /* reset our option array and index to where we are after getopt */
    argv += optind;
    argc -= optind;

    if (argc == 0) {
        fprintf(stderr,"Must specify an output file\n");
        usage();
    }

    memset((void *)file, 0, PATH_MAX+1);
    strncpy(file, argv[0], PATH_MAX);

    open_ctx = dspam_create(NULL,NULL,_ds_read_attribute(agent_config, "Home"), DSM_TOOLS, 0);
    if (open_ctx == NULL) {
        fprintf(stderr, "Could not initialize context: %s\n", strerror (errno));
        exit(EXIT_FAILURE);
    }

    set_libdspam_attributes(open_ctx);
    if (dspam_attach(open_ctx, NULL)) {
        fprintf(stderr,"Failed to init link to PostgreSQL\n");
        dspam_destroy(open_ctx);
        exit(EXIT_FAILURE);
    }

    store = (struct _pgsql_drv_storage *)(open_ctx->storage);
    GenSQL(store->dbh,file);
    //PQfinish(store->dbh);

    OutputMessage(open_ctx,file);

    if (open_ctx != NULL)
        dspam_destroy (open_ctx);
    if (open_mtx != NULL)
        dspam_destroy (open_mtx);
    _ds_destroy_config(agent_config);
    exit (EXIT_SUCCESS);
}
Beispiel #15
0
char*
ldap_lookup(config_t agent_config, const char *username, char *external_uid)
{
	LDAP		*ld;
	LDAPMessage	*result = (LDAPMessage *) 0;
	LDAPMessage	*e;
	BerElement	*ber;
	char		*a, *dn;
	char		*sane_username = malloc(strlen(username)*2);
	char		*p = sane_username;
	char		**vals = NULL;
	struct		timeval	ldaptimeout = {.tv_sec = BIND_TIMEOUT, .tv_usec = 0};
	int			i, rc=0, num_entries=0;
	char		*transcoded_query = NULL;
	char		*ldap_uri = NULL;
	char		*end_ptr;
	char		*ldap_host = _ds_read_attribute(agent_config, "ExtLookupServer");
	char		*port = _ds_read_attribute(agent_config, "ExtLookupPort");
	long		lldap_port;
	int			ldap_port = 389;
	char		*ldap_binddn = _ds_read_attribute(agent_config, "ExtLookupLogin");
	char		*ldap_passwd = _ds_read_attribute(agent_config, "ExtLookupPassword");
	char		*ldap_base = _ds_read_attribute(agent_config, "ExtLookupDB");
	char		*ldap_attrs[] = {_ds_read_attribute(agent_config, "ExtLookupLDAPAttribute"),0};
	char		*version = _ds_read_attribute(agent_config, "ExtLookupLDAPVersion");
	long		lldap_version;
	int			ldap_version = 3;
	char		*ldap_filter = _ds_read_attribute(agent_config, "ExtLookupQuery");
	int			ldap_scope;

	if (port != NULL) {
		errno=0;
		lldap_port = strtol(port, &end_ptr, 0);
		if ( (errno != 0) || (lldap_port < INT_MIN) || (lldap_port > INT_MAX) || (*end_ptr != '\0')) {
			LOG(LOG_ERR, "External Lookup: bad LDAP port number");
			return NULL;
		} else
			ldap_port = (int)lldap_port;
	}

	/* set ldap protocol version */
	if (version != NULL) {
		errno=0;
		lldap_version = strtol(version, &end_ptr, 0);
		if ((errno != 0) || (lldap_version < 1) || (lldap_version > 3) || (*end_ptr != '\0')) {
			LOG(LOG_ERR, "External Lookup: bad LDAP protocol version");
			return NULL;
		} else
			ldap_version = (int)lldap_version;
	}
		
	if (_ds_match_attribute(agent_config, "ExtLookupLDAPScope", "one"))
		ldap_scope = LDAP_SCOPE_ONELEVEL;
	else /* defaults to sub */
		ldap_scope = LDAP_SCOPE_SUBTREE;

	/* set alarm handler */
	signal(SIGALRM, sig_alrm);

	/* sanitize username for filter integration */
	for (; *username != '\0'; username++) {
		switch(*username) {
			case 0x2a: /* '*' */
			case 0x28: /* '(' */
			case 0x29: /* ')' */
			case 0x5c: /* '\' */
			case 0x00: /* NUL */
				*p++ = 0x5c; /* '\' */
				*p++ = *username;
				break;

			default:
				*p++ = *username;
				break;
		}
	}

	*p = '\0';

	LOGDEBUG("External Lookup: sanitized username is %s\n", sane_username);

	/* build proper LDAP filter*/
	transcoded_query = strdup(transcode_query(ldap_filter, sane_username, transcoded_query));
	free(sane_username);
	if (transcoded_query == NULL) {
		LOG(LOG_ERR, "External Lookup: %s", ERR_EXT_LOOKUP_MISCONFIGURED); 
		return NULL;
	}

	if( ldap_host != NULL || ldap_port ) {
	/* construct URL */
		LDAPURLDesc url;
		memset( &url, 0, sizeof(url));

		url.lud_scheme = "ldap";
		url.lud_host = ldap_host;
		url.lud_port = ldap_port;
		url.lud_scope = LDAP_SCOPE_SUBTREE;

		ldap_uri = ldap_url_desc2str( &url );
	}

	rc = ldap_initialize( &ld, ldap_uri );
	if( rc != LDAP_SUCCESS ) {
		LOG(LOG_ERR, "External Lookup: Could not create LDAP session handle for URI=%s (%d): %s\n", ldap_uri, rc, ldap_err2string(rc));
		return NULL;
	}

	if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version ) != LDAP_OPT_SUCCESS ) {
		LOG(LOG_ERR, "External Lookup: Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", ldap_version );
		return NULL;
	}

	/* use TLS if configured */
	if ( _ds_match_attribute(agent_config, "ExtLookupCrypto", "tls" )) {
		if (ldap_version != 3) {
			LOG(LOG_ERR, "External Lookup: TLS only supported with LDAP protocol version 3");
			return NULL;
		}
		if ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
			LOG(LOG_ERR, "External Lookup: %s: %s (%d)", ERR_EXT_LOOKUP_INIT_FAIL, strerror(errno), errno);
			return NULL;
		}
	}

	/* schedules alarm */
	alarm(BIND_TIMEOUT);
	
	/* authenticate to the directory */
	if ( (rc = ldap_simple_bind_s( ld, ldap_binddn, ldap_passwd )) != LDAP_SUCCESS ) {
		/* cancel alarms */
		alarm(0);
		
		LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_INIT_FAIL, ldap_err2string(rc) );
		ldap_unbind(ld);
		return NULL;
	}
	/* cancel alarms */
	alarm(0);
	
	/* search for all entries matching the filter */

	if ( (rc = ldap_search_st( ld, 
				   ldap_base, 
				   ldap_scope,
				   transcoded_query,
				   ldap_attrs, 
				   0,
				   &ldaptimeout, 
				   &result )) != LDAP_SUCCESS ) {

	free(transcoded_query);

	switch(rc) {
		case LDAP_TIMEOUT:
		case LDAP_BUSY:
		case LDAP_UNAVAILABLE:
		case LDAP_UNWILLING_TO_PERFORM:
		case LDAP_SERVER_DOWN:
		case LDAP_TIMELIMIT_EXCEEDED:
			LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_SEARCH_FAIL, ldap_err2string(ldap_result2error(ld, result, 1)) );
			ldap_unbind( ld );
			return NULL;
			break;
		case LDAP_FILTER_ERROR:
			LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_SEARCH_FAIL, ldap_err2string(ldap_result2error(ld, result, 1)) );
			ldap_unbind( ld );
			return NULL;
			break;
		case LDAP_SIZELIMIT_EXCEEDED:
			if ( result == NULL ) {
				LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_SEARCH_FAIL, ldap_err2string(ldap_result2error(ld, result, 1)) );
				ldap_unbind( ld );
				return NULL;
			}
			break;
		default:		       
			LOG(LOG_ERR, "External Lookup: %s: code=%d, %s", ERR_EXT_LOOKUP_SEARCH_FAIL, rc, ldap_err2string(ldap_result2error(ld, result, 1)) );
			ldap_unbind( ld );
			return NULL;
		}
	}

	num_entries=ldap_count_entries(ld,result);

	LOGDEBUG("External Lookup: found %d LDAP entries", num_entries);

    switch (num_entries) {
				case 1: /* only one entry, let's proceed */
					break;
					
				case -1: /* an error occured */
				    LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_SEARCH_FAIL, ldap_err2string(ldap_result2error(ld, result, 1)));
					ldap_unbind( ld );
					return NULL ;
					
				case 0: /* no entries found */
					LOGDEBUG("External Lookup: %s: no entries found.", ERR_EXT_LOOKUP_SEARCH_FAIL);
					ldap_msgfree( result );
					ldap_unbind( ld );
					return NULL ;

				default: /* more than one entry returned */
					LOG(LOG_ERR, "External Lookup: %s: more than one entry returned.", ERR_EXT_LOOKUP_SEARCH_FAIL);
					ldap_msgfree( result );
					ldap_unbind( ld );
			    	return NULL;
	}

	/* for each entry print out name + all attrs and values */
	for ( e = ldap_first_entry( ld, result ); e != NULL;
	    e = ldap_next_entry( ld, e ) ) {
		if ( (dn = ldap_get_dn( ld, e )) != NULL ) {
		    ldap_memfree( dn );
		}
		for ( a = ldap_first_attribute( ld, e, &ber );
		    a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {
			if ((vals = ldap_get_values( ld, e, a)) != NULL ) {
				for ( i = 0; vals[i] != NULL; i++ ) {
					external_uid = strdup(vals[i]);
				}
				ldap_value_free( vals );
			}
			ldap_memfree( a );
		}
		if ( ber != NULL ) {
			ber_free( ber, 0 );
		}
	}
	ldap_msgfree( result );
	ldap_unbind( ld );
	return external_uid;
}
#endif

char*
program_lookup(config_t agent_config, const char *username, char *external_uid)
{
	pid_t wstatus, pid;
	int i, status;
	int fd[2];
	char *output = malloc (1024);
	char **args = malloc (1024);
	char *token;
	char *saveptr;
	char *str;
	char *command_line = 0;
	
    /* build proper command line*/
	command_line = strdup(transcode_query(_ds_read_attribute(agent_config, "ExtLookupServer"), username, command_line));

	if (command_line == NULL) {
		LOG(LOG_ERR, ERR_EXT_LOOKUP_MISCONFIGURED);
		free(output);
		free(args);
		return NULL;
	}

	LOGDEBUG("command line is %s", command_line);
	
	/* break the command line into arguments */
	for (i = 0, str = command_line; ; i++, str = NULL) {
		token = strtok_r(str, " ", &saveptr);
		if (token == NULL)
			break;
		args[i] = token;
		LOGDEBUG("args[%d] = %s",i,token);
	}
	args[i] = (char *) 0;

	if (pipe(fd) == -1) {
		LOG(LOG_ERR, "%s: errno=%i (%s)", ERR_EXT_LOOKUP_INIT_FAIL, errno, strerror(errno));
		free(output);
		free(args);
		return NULL;
	}

	switch(pid=fork()) {

		case -1: /* couldn't fork - something went wrong */
			LOG(LOG_ERR, "%s: errno=%i (%s)", ERR_EXT_LOOKUP_INIT_FAIL, errno, strerror(errno));
			free(output);
			free(args);
			return NULL;

		case 0: /* execute the command and write to fd */
			close(fd[0]);
			dup2(fd[1], fileno(stdout));
			execve(args[0], args, 0);
			exit(EXIT_FAILURE);
			
		default: /* read from fd the first output line */
			do {
				wstatus = waitpid( pid, &status, WUNTRACED | WCONTINUED);
				if (wstatus == -1) {
					LOGDEBUG("waitpid() exited with an error: %s: errno=%i", strerror(errno), errno);
					free(output);
					free(args);
					return NULL;
				}
				if (WIFEXITED(status)) {
					LOGDEBUG("exited, status=%d\n", WEXITSTATUS(status));
					if (WEXITSTATUS(status)) {
						LOGDEBUG("Error running %s. Check path and permissions.\n", args[0]);
					}
				} else if (WIFSIGNALED(status)) {
					LOGDEBUG("killed by signal %d\n", WTERMSIG(status));
				} else if (WIFSTOPPED(status)) {
					LOGDEBUG("stopped by signal %d\n", WSTOPSIG(status));
				} else if (WIFCONTINUED(status)) {
					LOGDEBUG("continued\n");
				}
			} while (!WIFEXITED(status) && !WIFSIGNALED(status));
			close(fd[1]);
			/* just in case there's no line break at the end of the return... */
			memset(output, 0, 1024);
			if (read(fd[0], output, 1024) == -1) {
				LOG(LOG_ERR, "%s: errno=%i (%s)", ERR_EXT_LOOKUP_INIT_FAIL, errno, strerror(errno));
				free(output);
				free(args);
				return NULL;
			}
			close(fd[0]);
	}

	if (strlen(output) == 0) {
		free(output);
		free(args);
		return NULL;
	}
	
	/* terminate the output string at the first \n */
	token = strchr(output, '\n');
	if (token != NULL)
		*token = '\0';
	
	external_uid = strdup(output);
	free(output);
	free(command_line);
	free(args);
	return external_uid;
}
Beispiel #16
0
int
main (int argc, char **argv)
{
#ifndef _WIN32
#ifdef TRUSTED_USER_SECURITY
  struct passwd *p = getpwuid (getuid ());
#endif
#endif
  int i, ret;

 /* Read dspam.conf */
                                                                                
  agent_config = read_config(NULL);
  if (!agent_config) {
    LOG(LOG_ERR, ERR_AGENT_READ_CONFIG);
    fprintf (stderr, ERR_AGENT_READ_CONFIG "\n");
    exit(EXIT_FAILURE);
  }
                                                                                
  if (!_ds_read_attribute(agent_config, "Home")) {
    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
    fprintf (stderr, ERR_AGENT_DSPAM_HOME "\n");
    _ds_destroy_config(agent_config);
    exit(EXIT_FAILURE);
  }

  if (libdspam_init(_ds_read_attribute(agent_config, "StorageDriver")) != 0) {
    LOG(LOG_ERR, ERR_DRV_INIT);
    fprintf (stderr, ERR_DRV_INIT "\n");
    _ds_destroy_config(agent_config);
    exit(EXIT_FAILURE);
  }
                                                                                
#ifndef _WIN32
#ifdef TRUSTED_USER_SECURITY
  if (!_ds_match_attribute(agent_config, "Trust", p->pw_name) && p->pw_uid) {
    fprintf(stderr, ERR_TRUSTED_MODE "\n");
    _ds_destroy_config(agent_config);
    goto BAIL;
  }
#endif
#endif

  for(i=0;i<argc;i++) {
                                                                                
    if (!strncmp (argv[i], "--profile=", 10))
    {
      if (!_ds_match_attribute(agent_config, "Profile", argv[i]+10)) {
        LOG(LOG_ERR, ERR_AGENT_NO_SUCH_PROFILE, argv[i]+10);
        fprintf (stderr, ERR_AGENT_NO_SUCH_PROFILE "\n", argv[i]+10);
        _ds_destroy_config(agent_config);
        goto BAIL;
      } else {
        _ds_overwrite_attribute(agent_config, "DefaultProfile", argv[i]+10);
      }
      break;
    }
  }

  open_ctx = open_mtx = NULL;

  signal (SIGINT, dieout);
  signal (SIGPIPE, dieout);
  signal (SIGTERM, dieout);

  dspam_init_driver (NULL);
  ret = process_all_users();
  dspam_shutdown_driver (NULL);
  _ds_destroy_config(agent_config);
  libdspam_shutdown();
  exit((ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE);

BAIL:
  libdspam_shutdown();
  exit(EXIT_FAILURE);
}
Beispiel #17
0
int
main (int argc, char *argv[])
{
  DSPAM_CTX *CTX = NULL, *CTX2;
  char *user;
  int do_sigs   = 0;
  int do_probs  = 0;
  int do_unused = 0;
  int age_sigs   = 14;
  int age_probs  = 30;
  int age_unused[4] = { 90, 30, 15, 15 };
  int i, help = 0;
  struct nt *users = NULL;
  struct nt_node *node = NULL;
#ifndef _WIN32
#ifdef TRUSTED_USER_SECURITY
  struct passwd *p = getpwuid (getuid ());

#endif
#endif

 /* Read dspam.conf */
                                                                                
  agent_config = read_config(NULL);
  if (!agent_config) {
    LOG(LOG_ERR, ERR_AGENT_READ_CONFIG);
    fprintf (stderr, ERR_AGENT_READ_CONFIG "\n");
    exit(EXIT_FAILURE);
  }
                                                                                
  if (!_ds_read_attribute(agent_config, "Home")) {
    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
    fprintf (stderr, ERR_AGENT_DSPAM_HOME "\n");
    goto bail;
  }
                                                                                
  if (libdspam_init(_ds_read_attribute(agent_config, "StorageDriver")) != 0) {
    LOG(LOG_ERR, ERR_DRV_INIT);
    fprintf (stderr, ERR_DRV_INIT "\n");
    _ds_destroy_config(agent_config);
    exit(EXIT_FAILURE);
  }

#ifndef _WIN32
#ifdef TRUSTED_USER_SECURITY
  if (!_ds_match_attribute(agent_config, "Trust", p->pw_name) && p->pw_uid) {
    fprintf(stderr, ERR_TRUSTED_MODE "\n");
    goto bail;
  }
#endif
#endif

  for(i=0;i<argc;i++) {
                                                                                
    if (!strncmp (argv[i], "--profile=", 10))
    {
      if (!_ds_match_attribute(agent_config, "Profile", argv[i]+10)) {
        LOG(LOG_ERR, ERR_AGENT_NO_SUCH_PROFILE, argv[i]+10);
        fprintf (stderr, ERR_AGENT_NO_SUCH_PROFILE "\n", argv[i]+10);
        goto bail;
      } else {
        _ds_overwrite_attribute(agent_config, "DefaultProfile", argv[i]+10);
      }
      break;
    }
  }

#ifdef DEBUG
  fprintf (stdout, "dspam_clean starting\n");
#endif

  if (_ds_read_attribute(agent_config, "PurgeSignatures") &&
      !_ds_match_attribute(agent_config, "PurgeSignatures", "off"))  
  {
    do_sigs = 1;
    age_sigs = atoi(_ds_read_attribute(agent_config, "PurgeSignatures"));
  }
  
  if (_ds_read_attribute(agent_config, "PurgeNeutral") &&
      !_ds_match_attribute(agent_config, "PurgeNeutral", "off"))
  {
    do_probs = 1;
    age_probs = atoi(_ds_read_attribute(agent_config, "PurgeNeutral"));
  }

  if (_ds_read_attribute(agent_config, "PurgeUnused") &&
      !_ds_match_attribute(agent_config, "PurgeUnused", "off"))
  {
    int i;

    do_unused = 1;
    age_unused[0] = atoi(_ds_read_attribute(agent_config, "PurgeUnused"));
    age_unused[1] = atoi(_ds_read_attribute(agent_config, "PurgeHapaxes"));
    age_unused[2] = atoi(_ds_read_attribute(agent_config, "PurgeHits1S"));
    age_unused[3] = atoi(_ds_read_attribute(agent_config, "PurgeHits1I"));

    for(i=0;i<4;i++) 
      if (age_unused[i]==0)
        do_unused = 0;
  }

  users = nt_create(NT_CHAR);
  if (users == NULL) {
    fprintf(stderr, "%s", ERR_MEM_ALLOC);
    goto bail;
  }

  for(i=0;i<argc;i++) {
    if (!strncmp(argv[i], "-p", 2)) {
      do_probs = 1;
      if (strlen(argv[i])>2)
        age_probs = atoi(argv[i]+2);
    }
    else if (!strncmp(argv[i], "-s", 2)) {
      do_sigs = 1;
      if (strlen(argv[i])>2)
        age_sigs = atoi(argv[i]+2);
    } else if (!strncmp(argv[i], "-u", 2)) {
      do_unused = 1;
      if (strlen(argv[i])>2) {
        char *c = strdup(argv[i]+2);
        char *d = strtok(c, ",");
        int j = 0;
        while(d != NULL && j<4) {
          age_unused[j] = atoi(d);
          j++;
          d = strtok(NULL, ",");
        }
        free(c);
      }
    }
    else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
      help = 1;
    else if (i>0) 
      nt_add(users, argv[i]);
  }

  if (help || (!do_probs && !do_sigs && !do_unused)) {
    fprintf(stderr, "%s", CLEANSYNTAX);
    _ds_destroy_config(agent_config);
    nt_destroy(users);
    libdspam_shutdown();
    if (help) {
      exit(EXIT_SUCCESS);
    }
    exit(EXIT_FAILURE);
  }
      
  open_ctx = open_mtx = NULL;

  signal (SIGINT, dieout);
  signal (SIGPIPE, dieout);
  signal (SIGTERM, dieout);

  dspam_init_driver (NULL);

  if (users->items == 0) {
    CTX = dspam_create (NULL, NULL, _ds_read_attribute(agent_config, "Home"), DSM_TOOLS, 0);
    open_ctx = CTX;
    if (CTX == NULL)
    {
      fprintf (stderr, "Could not initialize context: %s\n", strerror (errno));
      dspam_shutdown_driver (NULL);
      goto bail;
    }

    set_libdspam_attributes(CTX);
    if (dspam_attach(CTX, NULL)) {
      LOG (LOG_WARNING, "unable to attach dspam context");
      fprintf (stderr, "Unable to attach DSPAM context\n");
      goto bail;
    }

    user = _ds_get_nextuser (CTX);
  } else {
    node = users->first;
    if (node != NULL)
      user = node->ptr;
    else 
      goto bail;
  }

  while (user != NULL)
  {
#ifdef DEBUG
    printf ("PROCESSING USER: %s\n", user);
#endif
    CTX2 = dspam_create (user, NULL,  _ds_read_attribute(agent_config, "Home"), DSM_TOOLS, 0);
    open_mtx = CTX2;

    if (CTX2 == NULL)
    {
      fprintf (stderr, "Could not initialize context: %s\n",
               strerror (errno));
      return EUNKNOWN;
    }

    set_libdspam_attributes(CTX2);
    if (dspam_attach(CTX2, NULL)) {
      LOG (LOG_WARNING, "unable to attach dspam context");
      fprintf (stderr, "Unable to attach DSPAM context\n");
      goto bail;
    }

    if (do_sigs)
      process_sigs(CTX2, age_sigs);
    if (do_probs)
      process_probs(CTX2, age_probs);
    if (do_unused)
      process_unused(CTX2, age_unused[0], age_unused[1], age_unused[2], age_unused[3]);
    dspam_destroy (CTX2);
    open_mtx = NULL;

    if (users->items == 0) {
      user = _ds_get_nextuser (CTX);
    } else {
      if (node == NULL || node->next == NULL) {
        node = NULL;
        user = NULL;
      } else {
        node = node->next;
        user = node->ptr;
      }
    }
  }

  if (users->items == 0) {
    dspam_destroy (CTX);
    open_ctx = NULL;
  }

  dspam_shutdown_driver (NULL);
  _ds_destroy_config(agent_config);
  nt_destroy(users);
  libdspam_shutdown();
  exit (EXIT_SUCCESS);

bail:

  if (open_ctx)
    dspam_destroy(open_ctx);
  if (open_mtx)
    dspam_destroy(open_mtx);
  _ds_destroy_config(agent_config);
  nt_destroy(users);
  libdspam_shutdown();
  exit(EXIT_FAILURE);
}
Beispiel #18
0
int daemon_listen(DRIVER_CTX *DTX) {
    struct sockaddr_in local_addr, remote_addr;
    THREAD_CTX *TTX = NULL;
    fd_set master, read_fds;
    pthread_attr_t attr;
    struct timeval tv;
    int fdmax, yes = 1;
    int domain = 0;		/* listening on domain socket? */
    int listener;			/* listener fd */
    int i;
    int port = 24, queue = 32;	/* default port and queue size */

    signal(SIGPIPE, SIG_IGN);
    signal(SIGINT,  process_signal);
    signal(SIGTERM, process_signal);
    signal(SIGHUP,  process_signal);

    if (_ds_read_attribute(agent_config, "ServerPort"))
        port = atoi(_ds_read_attribute(agent_config, "ServerPort"));

    if (_ds_read_attribute(agent_config, "ServerQueueSize"))
        queue = atoi(_ds_read_attribute(agent_config, "ServerQueueSize"));

    if (_ds_read_attribute(agent_config, "ServerDomainSocketPath"))
        domain = 1;

    /* initialize */

    FD_ZERO(&master);
    FD_ZERO(&read_fds);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    /* Bind (domain socket) */

    if (domain) {
        struct sockaddr_un saun;
        char *address = _ds_read_attribute(agent_config, "ServerDomainSocketPath");
        mode_t mask;
        int len;

        mask = umask (000);

        listener = socket(AF_UNIX, SOCK_STREAM, 0);
        if (listener == -1) {
            LOG(LOG_CRIT, ERR_DAEMON_SOCKET, strerror(errno));
            umask (mask);
            return(EFAILURE);
        }

        memset(&saun, 0, sizeof(struct sockaddr_un));
        saun.sun_family = AF_UNIX;
        strcpy(saun.sun_path, address);

        unlink(address);
        len = sizeof(saun.sun_family) + strlen(saun.sun_path) + 1;

        LOGDEBUG(INFO_DAEMON_DOMAINSOCK, address);

        if (bind(listener, (struct sockaddr *) &saun, len)<0) {
            close(listener);
            LOG(LOG_CRIT, INFO_DAEMON_DOMAINSOCK, address, strerror(errno));
            umask (mask);
            return EFAILURE;
        }

        umask (mask);

        /* Bind to a TCP socket */

    } else {
        listener = socket(AF_INET, SOCK_STREAM, 0);
        if (listener == -1) {
            LOG(LOG_CRIT, ERR_DAEMON_SOCKET, strerror(errno));
            return(EFAILURE);
        }

        if (setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
            close(listener);
            LOG(LOG_CRIT, ERR_DAEMON_SOCKOPT, "SO_REUSEADDR", strerror(errno));
            return(EFAILURE);
        }

        memset(&local_addr, 0, sizeof(struct sockaddr_in));
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(port);
        if (_ds_read_attribute(agent_config, "ServerHost")) {
            char *host = _ds_read_attribute(agent_config, "ServerHost");
            local_addr.sin_addr.s_addr = inet_addr(host);
            LOGDEBUG(INFO_DAEMON_BIND, host, port);
        } else {
            local_addr.sin_addr.s_addr = INADDR_ANY;
            LOGDEBUG(INFO_DAEMON_BIND, "*", port);
        }

        if (bind(listener, (struct sockaddr *)&local_addr,
                 sizeof(struct sockaddr)) == -1)
        {
            close(listener);
            LOG(LOG_CRIT, ERR_DAEMON_BIND, port, strerror(errno));
            return(EFAILURE);
        }
    }

    /* Listen */

    if (listen(listener, queue) == -1) {
        close(listener);
        LOG(LOG_CRIT, ERR_DAEMON_LISTEN, strerror(errno));
        return(EFAILURE);
    }

    FD_SET(listener, &master);
    fdmax = listener;

    /* Process new connections (until death or reload) */

    for(;;) {
        read_fds = master;
        tv.tv_sec = 2;
        tv.tv_usec = 0;

        if (__daemon_run == 0) {
            close(listener);

            if (_ds_read_attribute(agent_config, "ServerDomainSocketPath"))
                unlink (_ds_read_attribute(agent_config, "ServerDomainSocketPath"));

            return 0;
        }

        if (select(fdmax+1, &read_fds, NULL, NULL, &tv)>0) {

            /* Process read-ready connections */

            for(i=0; i<=fdmax; i++) {
                if (FD_ISSET(i, &read_fds)) {

                    /* Accept new connections */

                    if (i == listener) {
                        int newfd;
                        int addrlen = sizeof(remote_addr);

                        if ((newfd = accept(listener,
                                            (struct sockaddr *)&remote_addr,
                                            (socklen_t *) &addrlen)) == -1)
                        {
                            LOG(LOG_WARNING, ERR_DAEMON_ACCEPT, strerror(errno));
                            continue;
#ifdef DEBUG
                        } else if (!domain) {
                            char buff[32];
                            LOGDEBUG("connection id %d from %s.", newfd,
#ifdef HAVE_INET_NTOA_R_2
                                     inet_ntoa_r(remote_addr.sin_addr, buff)
#else
                                     inet_ntoa_r(remote_addr.sin_addr, buff, sizeof(buff))
#endif
                                    );
#endif
                        }
                        fcntl(newfd, F_SETFL, O_RDWR);
                        setsockopt(newfd,SOL_SOCKET,TCP_NODELAY,&yes,sizeof(int));

                        /*
                         * Since processing time varies, each new connection gets its own
                         * thread, so we create a new thread context and send it on its way
                         *
                         */

                        TTX = calloc(1, sizeof(THREAD_CTX));
                        if (TTX == NULL) {
                            LOG(LOG_CRIT, ERR_MEM_ALLOC);
                            close(newfd);
                            continue;
                        } else {
                            TTX->sockfd = newfd;
                            TTX->DTX = DTX;
                            memcpy(&TTX->remote_addr, &remote_addr, sizeof(remote_addr));

                            increment_thread_count();
                            if (pthread_create(&TTX->thread,
                                               &attr, process_connection, (void *) TTX))
                            {
                                decrement_thread_count();
                                LOG(LOG_CRIT, ERR_DAEMON_THREAD, strerror(errno));
                                close(TTX->sockfd);
                                free(TTX);
                                continue;
                            }
                        }
                    } /* if i == listener */
                } /* if FD_SET else */
            } /* for(i.. */
        }  /* if (select)... */
    } /* for(;;) */

    /* Shutdown - we should never get here, but who knows */

    close(listener);
    pthread_attr_destroy(&attr);
    return 0;
}
Beispiel #19
0
void *process_connection(void *ptr) {
    char *server_ident = _ds_read_attribute(agent_config, "ServerIdent");
    THREAD_CTX *TTX = (THREAD_CTX *) ptr;
    AGENT_CTX *ATX = NULL;
    char *input, *cmdline = NULL, *token, *ptrptr;
    buffer *message = NULL;
    char *parms=NULL, *p=NULL;
    int i, locked = -1, invalid = 0;
    int server_mode = SSM_DSPAM;
    char *argv[64];
    char buf[1024];
    int tries = 0;
    int argc = 0;
    FILE *fd = 0;

    if (_ds_read_attribute(agent_config, "ServerMode") &&
            !strcasecmp(_ds_read_attribute(agent_config, "ServerMode"), "standard"))
    {
        server_mode = SSM_STANDARD;
    }

    if (_ds_read_attribute(agent_config, "ServerMode") &&
            !strcasecmp(_ds_read_attribute(agent_config, "ServerMode"), "auto"))
    {
        server_mode = SSM_AUTO;
    }

    /* Initialize a file descriptor hook for dspam to use as stdout */

    fd = fdopen(TTX->sockfd, "w");
    if (!fd) {
        close(TTX->sockfd);
        goto CLOSE;
    }
    setbuf(fd, NULL);

    TTX->packet_buffer = buffer_create(NULL);
    if (TTX->packet_buffer == NULL)
        goto CLOSE;

    /*
     *  Send greeting banner
     *  in auto mode, we want to look like a regular LMTP server so we don't
     *  cause any compatibility problems. in dspam mode, we can change this.
     */

    snprintf(buf, sizeof(buf), "%d DSPAM %sLMTP %s %s",
             LMTP_GREETING,
             (server_mode == SSM_DSPAM) ? "D" : "",
             VERSION,
             (server_mode == SSM_DSPAM) ? "Authentication Required" : "Ready");
    if (send_socket(TTX, buf)<=0)
        goto CLOSE;

    TTX->authenticated = 0;

    /* LHLO */

    input = daemon_expect(TTX, "LHLO");
    if (input == NULL)
        goto CLOSE;
    if (server_mode == SSM_AUTO && input[4]) {
        char buff[128];

        /*
         *  Auto-detect the server mode based on whether or not the ident is
         *  assigned a password in dspam.conf
         */

        snprintf(buff, sizeof(buff), "ServerPass.%s", input + 5);
        chomp(buff);
        if (_ds_read_attribute(agent_config, buff))
            server_mode = SSM_DSPAM;
        else
            server_mode = SSM_STANDARD;
    }
    free(input);

    /* Advertise extensions */

    if (daemon_extension(TTX, (server_ident) ? server_ident :
                         "localhost.localdomain")<=0)
        goto CLOSE;

    if (daemon_extension(TTX, "PIPELINING")<=0)
        goto CLOSE;

    if (daemon_extension(TTX, "ENHANCEDSTATUSCODES")<=0)
        goto CLOSE;

    if (server_mode == SSM_DSPAM)
        if (daemon_extension(TTX, "DSPAMPROCESSMODE")<=0)
            goto CLOSE;

    if (daemon_extension(TTX, "8BITMIME")<=0)
        goto CLOSE;

    if (daemon_reply(TTX, LMTP_OK, "", "SIZE")<=0)
        goto CLOSE;

    /* Main protocol loop */

    while(1) {
        char processmode[256];
        parms = NULL;

        /* Configure a new agent context for each pass */

        ATX = calloc(1, sizeof(AGENT_CTX));
        if (ATX == NULL) {
            LOG(LOG_CRIT, ERR_MEM_ALLOC);
            daemon_reply(TTX, LMTP_TEMP_FAIL, "4.3.0", ERR_MEM_ALLOC);
            goto CLOSE;
        }

        if (initialize_atx(ATX)) {
            LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
            daemon_reply(TTX, LMTP_BAD_CMD, "5.3.0", ERR_AGENT_INIT_ATX);
            goto CLOSE;
        }

        /* MAIL FROM (and authentication, if SSM_DSPAM) */

        processmode[0] = 0;
        while(!TTX->authenticated) {
            input = daemon_expect(TTX, "MAIL FROM");

            if (RSET(input))
                goto RSET;

            if (input == NULL)
                goto CLOSE;
            else {
                char *pass, *ident;
                chomp(input);

                if (server_mode == SSM_STANDARD) {
                    TTX->authenticated = 1;

                    ATX->mailfrom[0] = 0;
                    _ds_extract_address(ATX->mailfrom, input, sizeof(ATX->mailfrom));

                    if (daemon_reply(TTX, LMTP_OK, "2.1.0", "OK")<=0) {
                        free(input);
                        goto CLOSE;
                    }
                } else {
                    char id[256];
                    pass = ident = NULL;
                    id[0] = 0;
                    if (!_ds_extract_address(id, input, sizeof(id))) {
                        pass = strtok_r(id, "@", &ptrptr);
                        ident = strtok_r(NULL, "@", &ptrptr);
                    }

                    if (pass && ident) {
                        char *serverpass;
                        char *ptr, *ptr2, *ptr3;

                        snprintf(buf, sizeof(buf), "ServerPass.%s", ident);
                        serverpass = _ds_read_attribute(agent_config, buf);

                        snprintf(buf, sizeof(buf), "ServerPass.%s", ident);
                        if (serverpass && !strcmp(pass, serverpass)) {
                            TTX->authenticated = 1;

                            /* Parse PROCESSMODE service tag */

                            ptr = strstr(input, "DSPAMPROCESSMODE=\"");
                            if (ptr) {
                                char *mode;
                                int i;
                                ptr2 = strchr(ptr, '"')+1;
                                mode = ptr2;
                                while((ptr3 = strstr(ptr2, "\\\"")))
                                    ptr2 = ptr3+2;
                                ptr3 = strchr(ptr2+2, '"');
                                if (ptr3)
                                    ptr3[0] = 0;
                                strlcpy(processmode, mode, sizeof(processmode));

                                ptr = processmode;
                                for(i=0; ptr[i]; i++) {
                                    if (ptr[i] == '\\' && ptr[i+1] == '"') {
                                        strcpy(ptr+i, ptr+i+1);
                                    }
                                }
                                LOGDEBUG("process mode: '%s'", processmode);
                            }

                            if (daemon_reply(TTX, LMTP_OK, "2.1.0", "OK")<=0) {
                                free(input);
                                goto CLOSE;
                            }
                        }
                    }
                }

                free(input);
                if (!TTX->authenticated) {
                    LOGDEBUG("fd %d authentication failure.", TTX->sockfd);

                    if (daemon_reply(TTX, LMTP_AUTH_ERROR, "5.1.0",
                                     "Authentication Required")<=0)
                    {
                        free(input);
                        goto CLOSE;
                    }

                    tries++;
                    if (tries>=3) {
                        struct timeval tv;
                        tv.tv_sec = 5;
                        tv.tv_usec = 0;
                        select(0, NULL, NULL, NULL, &tv);
                        goto CLOSE;
                    }
                }
            }
        }

        /* MAIL FROM response */

        snprintf(buf, sizeof(buf), "%d OK", LMTP_OK);

        argc = 1;
        argv[0] = "dspam";
        argv[1] = 0;

        /* Load open-LMTP configuration parameters */

        if (server_mode == SSM_STANDARD) {
            parms = _ds_read_attribute(agent_config, "ServerParameters");
            if (parms) {
                p = strdup(parms);
                if (p) {
                    token = strtok_r(p, " ", &ptrptr);
                    while(token != NULL && argc<63) {
                        argv[argc] = token;
                        argc++;
                        argv[argc] = 0;
                        token = strtok_r(NULL, " ", &ptrptr);
                    }
                }
            }
        }

        /* RCPT TO */

        while(ATX->users->items == 0 || invalid) {
            free(cmdline);
            cmdline = daemon_getline(TTX, 300);

            while(cmdline &&
                    (!strncasecmp(cmdline, "RCPT TO:", 8) ||
                     !strncasecmp(cmdline, "RSET", 4)))
            {
                char username[256];
                char *at = NULL;

                if (!strncasecmp(cmdline, "RSET", 4)) {
                    snprintf(buf, sizeof(buf), "%d OK", LMTP_OK);
                    if (send_socket(TTX, buf)<=0)
                        goto CLOSE;
                    goto RSET;
                }

                if (_ds_extract_address(username, cmdline, sizeof(username)) ||
                        username[0] == 0 || username[0] == '-' || username[0] == '@')
                {
                    if ((server_mode == SSM_DSPAM) || (server_mode == SSM_STANDARD && _ds_validate_address(username) == 0)) {
                        daemon_reply(TTX, LMTP_BAD_CMD, "5.1.2", ERR_LMTP_BAD_RCPT);
                        goto GETCMD;
                    }
                }

                if (_ds_match_attribute(agent_config, "Broken", "case"))
                    lc(username, username);

                /* Chop of @.* from the recipient */
                if (_ds_match_attribute(agent_config, "StripRcptDomain", "on")) {
                    at = strchr(username, '@');
                    if (at != NULL)
                        *at = '\0';
                }

                if (server_mode == SSM_DSPAM) {
                    nt_add(ATX->users, username);
                }
                else {
                    if (!parms || !strstr(parms, "--user "))
                        nt_add(ATX->users, username);

                    if (!ATX->recipients) {
                        ATX->recipients = nt_create(NT_CHAR);
                        if (ATX->recipients == NULL) {
                            LOG(LOG_CRIT, ERR_MEM_ALLOC);
                            goto CLOSE;
                        }
                    }
                    if (at != NULL)
                        *at = '@'; /* always add complete address (user@domain) to recipient list */
                    nt_add(ATX->recipients, username);
                }

                if (daemon_reply(TTX, LMTP_OK, "2.1.5", "OK")<=0)
                    goto CLOSE;

GETCMD:
                free(cmdline);
                cmdline = daemon_getline(TTX, 300);
            }

            if (cmdline == NULL)
                goto CLOSE;

            if (!strncasecmp(cmdline, "RSET", 4)) {
                snprintf(buf, sizeof(buf), "%d OK", LMTP_OK);
                if (send_socket(TTX, buf)<=0)
                    goto CLOSE;
                goto RSET;
            }

            if (!strncasecmp(cmdline, "quit", 4)) {
                daemon_reply(TTX, LMTP_OK, "2.0.0", "OK");
                goto CLOSE;
            }

            /* Parse DSPAMPROCESSMODE input and set up process arguments */

            if (server_mode == SSM_DSPAM && processmode[0] != 0) {
                token = strtok_r(processmode, " ", &ptrptr);
                while(token != NULL && argc<63) {
                    argv[argc] = token;
                    argc++;
                    argv[argc] = 0;
                    token = strtok_r(NULL, " ", &ptrptr);
                }
            }

            invalid = 0;
            if (process_arguments(ATX, argc, argv) || apply_defaults(ATX))
            {
                LOG(LOG_ERR, ERR_AGENT_INIT_ATX);
                daemon_reply(TTX, LMTP_NO_RCPT, "5.1.0", ERR_AGENT_INIT_ATX);
                invalid = 1;
            } else if (ATX->users->items == 0) {
                daemon_reply(TTX, LMTP_NO_RCPT, "5.1.1", ERR_AGENT_USER_UNDEFINED);
            }
        }

        ATX->sockfd = fd;
        ATX->sockfd_output = 0;

        /* Something's terribly misconfigured */

        if (check_configuration(ATX)) {
            LOG(LOG_ERR, ERR_AGENT_MISCONFIGURED);
            daemon_reply(TTX, LMTP_BAD_CMD, "5.3.5", ERR_AGENT_MISCONFIGURED);
            goto CLOSE;
        }

        /* DATA */

        if (cmdline != NULL) {
            if (strncasecmp(cmdline, "DATA", 4)) {
                if (daemon_reply(TTX, LMTP_BAD_CMD, "5.0.0", "Need DATA Here")<0)
                    goto CLOSE;
                input = daemon_expect(TTX, "DATA");
                if (input == NULL)
                    goto CLOSE;
                if (RSET(input))
                    goto RSET;
            }
        }

        if (daemon_reply(TTX, LMTP_DATA, "", INFO_LMTP_DATA)<=0)
            goto CLOSE;

        /*
         *  Read in the message from a DATA. I personally like to just hang up on
         *  a client stupid enough to pass in a NULL message for DATA, but you're
         *  welcome to do whatever you want.
         */

        message = read_sock(TTX, ATX);
        if (message == NULL || message->data == NULL || message->used == 0) {
            daemon_reply(TTX, LMTP_FAILURE, "5.2.0", ERR_LMTP_MSG_NULL);
            goto CLOSE;
        }

        /*
         *  Lock a database handle. We currently use the modulus of the socket
         *  id against the number of database connections in the cache. This
         *  seems to work rather well, as we would need to lock up the entire
         *  cache to wrap back around. And if we do wrap back around, that means
         *  we're busy enough to justify spinning on the current lock (vs. seeking
         *  out a free handle, which there likely are none).
         */

        i = (TTX->sockfd % TTX->DTX->connection_cache);
        LOGDEBUG("using database handle id %d", i);
        if (TTX->DTX->flags & DRF_RWLOCK) {
            if (ATX->operating_mode == DSM_CLASSIFY ||
                    ATX->training_mode == DST_NOTRAIN   ||
                    (ATX->training_mode == DST_TOE && ATX->classification == DSR_NONE))
            {
                pthread_rwlock_rdlock(&TTX->DTX->connections[i]->rwlock);
            } else {
                pthread_rwlock_wrlock(&TTX->DTX->connections[i]->rwlock);
            }
        } else {
            pthread_mutex_lock(&TTX->DTX->connections[i]->lock);
        }
        LOGDEBUG("handle locked");
        ATX->dbh = TTX->DTX->connections[i]->dbh;
        locked = i;

        /* Process the message by tying back into the agent functions */

        ATX->results = nt_create(NT_PTR);
        if (ATX->results == NULL) {
            LOG(LOG_CRIT, ERR_MEM_ALLOC);
            goto CLOSE;
        }
        process_users(ATX, message);

        /*
         *  Unlock the database handle as soon as we're done. We also need to
         *  refresh our handle index with a new handle if for some reason we
         *  had to re-establish a dewedged connection.
         */

        if (TTX->DTX->connections[locked]->dbh != ATX->dbh)
            TTX->DTX->connections[locked]->dbh = ATX->dbh;

        if (TTX->DTX->flags & DRF_RWLOCK) {
            pthread_rwlock_unlock(&TTX->DTX->connections[locked]->rwlock);
        } else {
            pthread_mutex_unlock(&TTX->DTX->connections[locked]->lock);
        }
        locked = -1;

        /* Send a terminating '.' if --stdout in 'dspam' mode */

        if (ATX->sockfd_output) {
            if (send_socket(TTX, ".")<=0)
                goto CLOSE;

            /* Otherwise, produce standard delivery results */

        } else {
            struct nt_node *node_nt, *node_res = NULL;
            struct nt_c c_nt;
            if (ATX->recipients)
                node_nt = c_nt_first(ATX->recipients, &c_nt);
            else
                node_nt = c_nt_first(ATX->users, &c_nt);

            if (ATX->results)
                node_res = ATX->results->first;

            while(node_res && node_nt != NULL) {
                agent_result_t result = (agent_result_t) node_res->ptr;

                if (result != NULL && result->exitcode == ERC_SUCCESS)
                {
                    if (server_mode == SSM_DSPAM) {
                        snprintf(buf, sizeof(buf),
                                 "%d 2.6.0 <%s> Message accepted for delivery: %s",
                                 LMTP_OK, (char *) node_nt->ptr,
                                 (result->classification == DSR_ISSPAM) ? "SPAM" : "INNOCENT");
                    } else {
                        snprintf(buf, sizeof(buf),
                                 "%d 2.6.0 <%s> Message accepted for delivery",
                                 LMTP_OK, (char *) node_nt->ptr);
                    }
                }
                else
                {
                    if (result != NULL && result->exitcode == ERC_PERMANENT_DELIVERY) {
                        snprintf(buf, sizeof(buf), "%d 5.3.0 <%s> %s",
                                 LMTP_FAILURE, (char *) node_nt->ptr,
                                 (result->text[0]) ? result->text : "Permanent error occured");
                    } else {
                        if (result != NULL && result->text[0]) {
                            snprintf(buf, sizeof(buf),
                                     "%d 4.3.0 <%s> %s",
                                     LMTP_TEMP_FAIL, (char *) node_nt->ptr, result->text);
                        } else {
                            snprintf(buf, sizeof(buf),
                                     "%d 4.3.0 <%s> Error occured during %s",
                                     LMTP_TEMP_FAIL, (char *) node_nt->ptr,
                                     (result != NULL && result->exitcode == ERC_DELIVERY) ? "delivery" : "processing");
                        }
                    }
                }

                if (send_socket(TTX, buf)<=0)
                    goto CLOSE;
                if (ATX->recipients)
                    node_nt = c_nt_next(ATX->recipients, &c_nt);
                else
                    node_nt = c_nt_next(ATX->users, &c_nt);
                if (node_res)
                    node_res = node_res->next;
            }
        }

        /* Cleanup and get ready for another message */

RSET:
        fflush(fd);

        buffer_destroy(message);
        message = NULL;
        if (ATX != NULL) {
            nt_destroy(ATX->users);
            nt_destroy(ATX->recipients);
            nt_destroy(ATX->results);
            free(ATX);
            ATX = NULL;
            free(cmdline);
            cmdline = NULL;
            TTX->authenticated = 0;
            /* argc = 0; */
        }

        free(p);
        p = NULL;

    } /* while(1) */

    /* Close connection and return */

CLOSE:
    if (locked>=0)
        pthread_mutex_unlock(&TTX->DTX->connections[locked]->lock);
    if (fd)
        fclose(fd);
    buffer_destroy(TTX->packet_buffer);
    if (message)
        buffer_destroy(message);
    if (ATX != NULL) {
        nt_destroy(ATX->users);
        nt_destroy(ATX->recipients);
        nt_destroy(ATX->results);
    }
    free(ATX);
    free(cmdline);
    free(TTX);
    decrement_thread_count();
    pthread_exit(0);
    return 0;
}
Beispiel #20
0
int
main (int argc, char **argv)
{
#ifdef TRUSTED_USER_SECURITY
  struct passwd *p = getpwuid (getuid ());
#endif
  int i, valid = 0;

 /* Read dspam.conf */
                                                                                
  agent_config = read_config(NULL);
  if (!agent_config) {
    LOG(LOG_ERR, ERR_AGENT_READ_CONFIG);
    exit(EXIT_FAILURE);
  }
                                                                                
  if (!_ds_read_attribute(agent_config, "Home")) {
    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
    _ds_destroy_config(agent_config);
    exit(EXIT_FAILURE);
  }
                                                                                
  libdspam_init(_ds_read_attribute(agent_config, "StorageDriver"));

#ifndef _WIN32
#ifdef TRUSTED_USER_SECURITY
  if (!_ds_match_attribute(agent_config, "Trust", p->pw_name) && p->pw_uid) {
    fprintf(stderr, ERR_TRUSTED_MODE "\n");     
    _ds_destroy_config(agent_config);
    goto BAIL;
  }
#endif
#endif

  for(i=0;i<argc;i++) {
                                                                                
    if (!strncmp (argv[i], "--profile=", 10))
    {
      if (!_ds_match_attribute(agent_config, "Profile", argv[i]+10)) {
        LOG(LOG_ERR, ERR_AGENT_NO_SUCH_PROFILE, argv[i]+10);
        _ds_destroy_config(agent_config);
        goto BAIL;
      } else {
        _ds_overwrite_attribute(agent_config, "DefaultProfile", argv[i]+10);
      }
      break;
    }
  }

  signal (SIGINT, dieout);
  signal (SIGPIPE, dieout);
  signal (SIGTERM, dieout);

  dspam_init_driver (NULL);

  if (argc < 3 || !strcmp(argv[1], "help"))
  {
    usage();
  }

  /* PREFERENCE FUNCTIONS */
  if (!strncmp(argv[2], "pref", 4)) {
 
    /* Delete */
    if (!strncmp(argv[1], "d", 1)) {
      min_args(argc, 4);
      valid = 1;
      del_preference_attribute(argv[3], argv[4]);
    }

    /* Add, Change */
    if (!strncmp(argv[1], "ch", 2) || !strncmp(argv[1], "ad", 2)) {
      min_args(argc, 5);
      valid = 1; 
      set_preference_attribute(argv[3], argv[4], argv[5]); 
    }

    /* List */
    if (!strncmp(argv[1], "l", 1)) {
      min_args(argc, 3);
      valid = 1;
      list_preference_attributes(argv[3]);
    }

    /* Aggregate - Preference attr + AllowOverride attr + user prefs */
    if (!strncmp(argv[1], "ag", 2)) {
      min_args(argc, 3);
      valid = 1;
      list_aggregate_preference_attributes(argv[3]);
    }
  }

  if (!valid) 
    usage();

  dspam_shutdown_driver (NULL);
  _ds_destroy_config(agent_config);
  libdspam_shutdown();
  exit (EXIT_SUCCESS);

BAIL:
  libdspam_shutdown();
  exit(EXIT_FAILURE);
}
Beispiel #21
0
int process_unused (DSPAM_CTX *CTX, int any, int quota, int nospam, int onehit) {
  struct _ds_storage_record *sr;
  ds_diction_t del;
  time_t t = time(NULL);
  int delta, toe = 0, tum = 0;
  agent_pref_t PTX;
                                                                                
#ifdef DEBUG
  printf("Processing unused; any: %d quota: %d nospam: %d onehit: %d\n",
         any, quota, nospam, onehit);
#endif

  PTX = _ds_pref_load(agent_config, CTX->username, _ds_read_attribute(agent_config, "Home"), NULL);

  if (PTX == NULL || PTX[0] == 0) {
    if (PTX)
      _ds_pref_free(PTX);
    PTX = pref_config();
  }
                                                                                
  if (!strcasecmp(_ds_pref_val(PTX, "trainingMode"), "toe")) {
#ifdef DEBUG
    printf("Limiting unused token purges for user %s - TOE Training Mode Set\n", CTX->username);
#endif
    toe = 1;
  }

  if (!strcasecmp(_ds_pref_val(PTX, "trainingMode"), "tum")) {
#ifdef DEBUG
    printf("Limiting unused token purges for user %s - TUM Training Mode Set\n", CTX->username);
#endif
    tum = 1;
  }

  if (PTX)
    _ds_pref_free(PTX);

  del = ds_diction_create(196613);
  if (del == NULL)
    return -1;
  sr = _ds_get_nexttoken (CTX);
  while (sr != NULL)
  {
    delta = (((t - sr->last_hit) / 60) / 60) / 24;
    if (!toe && (any == 0 || delta > any))
    { 
      if (!tum || sr->innocent_hits + sr->spam_hits < 50)
        ds_diction_touch(del, sr->token, "", 0);
    }
    else if ((sr->innocent_hits*2) + sr->spam_hits < 5)
    { 
      if (quota == 0 || delta > quota)
      {
        ds_diction_touch(del, sr->token, "", 0);
      }
      else if (sr->innocent_hits == 0 && sr->spam_hits == 1 &&
          (nospam == 0 || delta > nospam))
      {
        ds_diction_touch(del, sr->token, "", 0);
      }
      else if (sr->innocent_hits == 1 && sr->spam_hits == 0 &&
          (onehit == 0 || delta > onehit))
      {
        ds_diction_touch(del, sr->token, "", 0);
      }
    }
 
    free (sr);
    sr = _ds_get_nexttoken (CTX);
  }
                                                                                
  _ds_delall_spamrecords(CTX, del);
  ds_diction_destroy(del);
                                                                                
  return 0;
}