Exemple #1
0
int setactive(struct protstream *conn, mystring_t *name)
{
    int result;
    char filename[1024];

    /* if string name is empty, disable active script */
    if (!strlen(string_DATAPTR(name))) {
	if (deleteactive(conn) != TIMSIEVE_OK)
	    return TIMSIEVE_FAIL;

	prot_printf(conn,"OK\r\n");
	return TIMSIEVE_OK;
    }

    result = scriptname_valid(name);
    if (result!=TIMSIEVE_OK)
    {
	prot_printf(conn,"NO \"Invalid script name\"\r\n");
	return result;
    }

    if (exists(string_DATAPTR(name))==FALSE)
    {
	prot_printf(conn,"NO \"Script does not exist\"\r\n");
	return TIMSIEVE_NOEXIST;
    }

    /* if script already is the active one just say ok */
    if (isactive(string_DATAPTR(name))==TRUE) {
	prot_printf(conn,"OK\r\n");
	return TIMSIEVE_OK;  
    }

    /* get the name of the active sieve script */
    snprintf(filename, sizeof(filename), "%s.bc", string_DATAPTR(name));

    /* ok we want to do this atomically so let's
       - make <activesieve>.NEW as a hard link
       - rename it to <activesieve>
    */
    result = symlink(filename, "defaultbc.NEW");
    if (result) {
	syslog(LOG_ERR, "symlink(%s, defaultbc.NEW): %m", filename);
	prot_printf(conn, "NO \"Can't make link\"\r\n");    
	return TIMSIEVE_FAIL;
    }

    result = rename("defaultbc.NEW", "defaultbc");
    if (result) {
	unlink("defaultbc.NEW");
	syslog(LOG_ERR, "rename(defaultbc.NEW, defaultbc): %m");
	prot_printf(conn,"NO \"Error renaming\"\r\n");
	return TIMSIEVE_FAIL;
    }
    sync_log_sieve(sieved_userid);

    prot_printf(conn,"OK\r\n");
    return TIMSIEVE_OK;
}
Exemple #2
0
static int deleteactive(struct protstream *conn)
{
    if (unlink("defaultbc") != 0) {
	prot_printf(conn,"NO \"Unable to unlink active script\"\r\n");
	return TIMSIEVE_FAIL;
    }
    sync_log_sieve(sieved_userid);

    return TIMSIEVE_OK;
}
Exemple #3
0
static int deleteactive(struct protstream *conn)
{
    if (unlink("defaultbc") != 0) {
        if (errno == ENOENT) {
            /* RFC 5804, 2.8 SETACTIVE Command:
             * Disabling an active script when there is no script active is
             * not an error and MUST result in an OK reply. */
            return TIMSIEVE_OK;
        }
        prot_printf(conn,"NO \"Unable to unlink active script\"\r\n");
        return TIMSIEVE_FAIL;
    }
    sync_log_sieve(sieved_userid);

    return TIMSIEVE_OK;
}
Exemple #4
0
/* delete a sieve script */
int deletescript(struct protstream *conn, const struct buf *name)
{
  int result;
  char path[1024];

  result = scriptname_valid(name);
  if (result!=TIMSIEVE_OK)
  {
      prot_printf(conn,"NO \"Invalid script name\"\r\n");
      return result;
  }

  snprintf(path, 1023, "%s.script", name->s);

  if (isactive(name->s)) {
    prot_printf(conn, "NO (ACTIVE) \"Active script cannot be deleted\"\r\n");
    return TIMSIEVE_FAIL;
  }

  result = unlink(path);

  if (result != 0) {
      if (result == ENOENT)
          prot_printf(conn, "NO (NONEXISTENT) \"Script %s does not exist.\"\r\n", name->s);
      else
          prot_printf(conn,"NO \"Error deleting script\"\r\n");
      return TIMSIEVE_FAIL;
  }

  snprintf(path, 1023, "%s.bc", name->s);

  result = unlink(path);

  if (result != 0) {
      prot_printf(conn,"NO \"Error deleting bytecode\"\r\n");
      return TIMSIEVE_FAIL;
  }
  sync_log_sieve(sieved_userid);

  prot_printf(conn,"OK\r\n");
  return TIMSIEVE_OK;
}
Exemple #5
0
/* delete a sieve script */
int deletescript(struct protstream *conn, mystring_t *name)
{
  int result;
  char path[1024];

  result = scriptname_valid(name);
  if (result!=TIMSIEVE_OK)
  {
      prot_printf(conn,"NO \"Invalid script name\"\r\n");
      return result;
  }

  snprintf(path, 1023, "%s.script", string_DATAPTR(name));

  if (isactive(string_DATAPTR(name)) && (deleteactive(conn)!=TIMSIEVE_OK)) {
      return TIMSIEVE_FAIL;
  }

  result = unlink(path);

  if (result != 0) {
      prot_printf(conn,"NO \"Error deleting script\"\r\n");
      return TIMSIEVE_FAIL;
  }

  snprintf(path, 1023, "%s.bc", string_DATAPTR(name));

  result = unlink(path);

  if (result != 0) {
      prot_printf(conn,"NO \"Error deleting bytecode\"\r\n");
      return TIMSIEVE_FAIL;
  }
  sync_log_sieve(sieved_userid);

  prot_printf(conn,"OK\r\n");
  return TIMSIEVE_OK;
}
Exemple #6
0
/* save name as a sieve script */
int putscript(struct protstream *conn, mystring_t *name, mystring_t *data,
	      int verify_only)
{
  FILE *stream;
  char *dataptr;
  char *errstr;
  int lup;
  int result;
  char path[1024], p2[1024];
  char bc_path[1024], bc_p2[1024];
  int maxscripts;
  sieve_script_t *s;

  result = scriptname_valid(name);
  if (result!=TIMSIEVE_OK)
  {
      prot_printf(conn,"NO \"Invalid script name\"\r\n");
      return result;
  }

  if (verify_only)
      stream = tmpfile();

  else {
      /* see if this would put the user over quota */
      maxscripts = config_getint(IMAPOPT_SIEVE_MAXSCRIPTS);

      if (countscripts(string_DATAPTR(name))+1 > maxscripts)
      {
	  prot_printf(conn,
		      "NO (\"QUOTA\") \"You are only allowed %d scripts on this server\"\r\n",
		      maxscripts);
	  return TIMSIEVE_FAIL;
      }

      snprintf(path, 1023, "%s.script.NEW", string_DATAPTR(name));

      stream = fopen(path, "w+");
  }


  if (stream == NULL) {
      prot_printf(conn, "NO \"Unable to open script for writing (%s)\"\r\n",
		  path);
      return TIMSIEVE_NOEXIST;
  }

  dataptr = string_DATAPTR(data);

  for (lup=0;lup<= data->len / BLOCKSIZE; lup++) {
      int amount = BLOCKSIZE;

      if (lup*BLOCKSIZE+BLOCKSIZE > data->len)
	  amount=data->len % BLOCKSIZE;

      fwrite(dataptr, 1, amount, stream);
      
      dataptr += amount;
  }

  /* let's make sure this is a valid script
     (no parse errors)
  */
  result = is_script_parsable(stream, &errstr, &s);

  if (result != TIMSIEVE_OK) {
      if (errstr && *errstr) { 
	  prot_printf(conn, "NO {" SIZE_T_FMT "}\r\n%s\r\n",
		      strlen(errstr), errstr);
	  free(errstr);
      } else {
	  if (errstr) free(errstr);
	  prot_printf(conn, "NO \"parse failed\"\r\n");
      }
      fclose(stream);
      unlink(path);
      return result;
  }

  fflush(stream);
  fclose(stream);
  
  if (!verify_only) {
      int fd;
      bytecode_info_t *bc;
      
      /* Now, generate the bytecode */
      if(sieve_generate_bytecode(&bc, s) == -1) {
	  unlink(path);
	  sieve_script_free(&s);
	  prot_printf(conn, "NO \"bytecode generate failed\"\r\n");
	  return TIMSIEVE_FAIL;
      }

      /* Now, open the new file */
      snprintf(bc_path, 1023, "%s.bc.NEW", string_DATAPTR(name));
      fd = open(bc_path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
      if(fd < 0) {
	  unlink(path);
	  sieve_free_bytecode(&bc);
	  sieve_script_free(&s);
	  prot_printf(conn, "NO \"couldn't open bytecode file\"\r\n");
	  return TIMSIEVE_FAIL;
      }
	  
      /* Now, emit the bytecode */
      if(sieve_emit_bytecode(fd, bc) == -1) {
	  close(fd);
	  unlink(path);
	  unlink(bc_path);
	  sieve_free_bytecode(&bc);
	  sieve_script_free(&s);
	  prot_printf(conn, "NO \"bytecode emit failed\"\r\n");
	  return TIMSIEVE_FAIL;
      }

      sieve_free_bytecode(&bc);
      sieve_script_free(&s);

      close(fd);

      /* Now, rename! */
      snprintf(p2, 1023, "%s.script", string_DATAPTR(name));
      snprintf(bc_p2, 1023, "%s.bc", string_DATAPTR(name));
      rename(path, p2);
      rename(bc_path, bc_p2);

  }

  prot_printf(conn, "OK\r\n");
  sync_log_sieve(sieved_userid);

  return TIMSIEVE_OK;
}
Exemple #7
0
/* save name as a sieve script */
int putscript(struct protstream *conn, const struct buf *name,
              const struct buf *data, int verify_only)
{
  FILE *stream;
  const char *dataptr;
  char *errstr;
  unsigned int i;
  int last_was_r = 0;
  int result;
  char path[1024], p2[1024];
  char bc_path[1024], bc_p2[1024];
  int maxscripts;
  sieve_script_t *s;

  result = scriptname_valid(name);
  if (result!=TIMSIEVE_OK)
  {
      prot_printf(conn,"NO \"Invalid script name\"\r\n");
      return result;
  }

  if (verify_only)
      stream = tmpfile();

  else {
      /* see if this would put the user over quota */
      maxscripts = config_getint(IMAPOPT_SIEVE_MAXSCRIPTS);

      if (countscripts(name->s)+1 > maxscripts)
      {
          prot_printf(conn,
                      "NO (QUOTA/MAXSCRIPTS) \"You are only allowed %d scripts on this server\"\r\n",
                      maxscripts);
          return TIMSIEVE_FAIL;
      }

      snprintf(path, 1023, "%s.script.NEW", name->s);

      stream = fopen(path, "w+");
  }


  if (stream == NULL) {
      prot_printf(conn, "NO \"Unable to open script for writing (%s)\"\r\n",
                  path);
      return TIMSIEVE_NOEXIST;
  }

  dataptr = data->s;

  /* copy data to file - replacing any lone \r or \n with the
   * \r\n pair so notify messages are SMTP compatible */
  for (i = 0; i < data->len; i++) {
      if (last_was_r) {
          if (dataptr[i] != '\n')
              putc('\n', stream);
      }
      else {
          if (dataptr[i] == '\n')
              putc('\r', stream);
      }
      putc(dataptr[i], stream);
      last_was_r = (dataptr[i] == '\r');
  }
  if (last_was_r)
      putc('\n', stream);


  /* let's make sure this is a valid script
     (no parse errors)
  */
  result = is_script_parsable(stream, &errstr, &s);

  if (result != TIMSIEVE_OK) {
      if (errstr && *errstr) {
          prot_printf(conn, "NO ");
          prot_printstring(conn, errstr);
          prot_printf(conn, "\r\n");
      } else {
          prot_printf(conn, "NO \"parse failed\"\r\n");
      }
      free(errstr);
      fclose(stream);
      unlink(path);
      return result;
  }

  fflush(stream);
  fclose(stream);

  if (!verify_only) {
      int fd;
      bytecode_info_t *bc;

      /* Now, generate the bytecode */
      if(sieve_generate_bytecode(&bc, s) == -1) {
          unlink(path);
          sieve_script_free(&s);
          prot_printf(conn, "NO \"bytecode generate failed\"\r\n");
          return TIMSIEVE_FAIL;
      }

      /* Now, open the new file */
      snprintf(bc_path, 1023, "%s.bc.NEW", name->s);
      fd = open(bc_path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
      if(fd < 0) {
          unlink(path);
          sieve_free_bytecode(&bc);
          sieve_script_free(&s);
          prot_printf(conn, "NO \"couldn't open bytecode file\"\r\n");
          return TIMSIEVE_FAIL;
      }

      /* Now, emit the bytecode */
      if(sieve_emit_bytecode(fd, bc) == -1) {
          close(fd);
          unlink(path);
          unlink(bc_path);
          sieve_free_bytecode(&bc);
          sieve_script_free(&s);
          prot_printf(conn, "NO \"bytecode emit failed\"\r\n");
          return TIMSIEVE_FAIL;
      }

      sieve_free_bytecode(&bc);
      sieve_script_free(&s);

      close(fd);

      /* Now, rename! */
      snprintf(p2, 1023, "%s.script", name->s);
      snprintf(bc_p2, 1023, "%s.bc", name->s);
      rename(path, p2);
      rename(bc_path, bc_p2);

  }

  prot_printf(conn, "OK\r\n");
  sync_log_sieve(sieved_userid);

  return TIMSIEVE_OK;
}
Exemple #8
0
int main(int argc, char *argv[])
{
    char *alt_config = NULL;
    char cmd = '\0';
    int opt;

    if ((geteuid()) == 0 && (become_cyrus(/*is_master*/0) != 0)) {
        fatal("must run as the Cyrus user", EC_USAGE);
    }

    while ((opt = getopt(argc, argv, "C:uUvmMacqnsb")) != EOF) {
        switch (opt) {
        case 'C': /* alt config file */
            alt_config = optarg;
            break;
        case 'u': /* User */
            cmd = 'u';
            break;
        case 'U': /* UnUser */
            cmd = 'U';
            break;
        case 'v': /* sieVe */
            cmd = 'v';
            break;
        case 'm': /* Mailbox */
            cmd = 'm';
            break;
        case 'M': /* UnMailbox */
            cmd = 'M';
            break;
        case 'a': /* Append */
            cmd = 'a';
            break;
        case 'c': /* aCl */
            cmd = 'c';
            break;
        case 'q': /* Quota */
            cmd = 'q';
            break;
        case 'n': /* aNnotation */
            cmd = 'n';
            break;
        case 's': /* Seen */
            cmd = 's';
            break;
        case 'b': /* suBscription */
            cmd = 'b';
            break;
        }
    }

    /* need at least one value */
    if ((argc - optind) < 1) usage(argv[0]);
    /* and not an empty string */
    if (!argv[optind][0]) usage(argv[0]);

    if (cmd == 's' || cmd == 'b') {
	/* need a second value */
	if ((argc - optind) < 2) usage(argv[0]);
	/* and not an empty string */
	if (!argv[optind+1][0]) usage(argv[0]);
    }

    cyrus_init(alt_config, "cyr_synclog", 0, 0);
    sync_log_init();

    switch(cmd) {
        case 'u': /* User */
            sync_log_user(argv[optind]);
            break;
        case 'U': /* UnUser */
            sync_log_unuser(argv[optind]);
            break;
        case 'v': /* sieVe */
            sync_log_sieve(argv[optind]);
            break;
        case 'm': /* Mailbox */
            sync_log_mailbox(argv[optind]);
            break;
        case 'M': /* UnMailbox */
            sync_log_unmailbox(argv[optind]);
            break;
        case 'q': /* Quota */
            sync_log_quota(argv[optind]);
            break;
        case 'n': /* aNnotation */
            sync_log_annotation(argv[optind]);
            break;
        case 's': /* Seen */
            sync_log_seen(argv[optind], argv[optind+1]);
            break;
        case 'b': /* suBscription */
            sync_log_subscribe(argv[optind], argv[optind+1]);
            break;
        default:
            /* just as is! */
            sync_log(argv[optind]);
            break;
    }

    sync_log_done();

    cyrus_done();

    return 0;
}