Esempio n. 1
0
/* Returns TRUE if we are done */
int parser(struct protstream *sieved_out, struct protstream *sieved_in)
{
  int token = EOL;
  const char *error_msg = "Generic Error";

  mystring_t *mechanism_name = NULL;
  mystring_t *initial_challenge = NULL;
  mystring_t *sieve_name = NULL;
  mystring_t *sieve_data = NULL;
  unsigned long num;
  int ret = FALSE;

  /* get one token from the lexer */
  while(token == EOL) 
      token = timlex(NULL, NULL, sieved_in);

  if (!authenticated && (token > 255) && (token!=AUTHENTICATE) &&
      (token!=LOGOUT) && (token!=CAPABILITY) &&
      (token!=NOOP) && (token!=CHECKSCRIPT) &&
      (!tls_enabled() || (token!=STARTTLS)))
  {
    error_msg = "Authenticate first";
    if (token!=EOL)
      lex_setrecovering();

    goto error;
  }

  if (verify_only && (token > 255) && (token!=CHECKSCRIPT)
    && (token!=PUTSCRIPT) && (token!=LOGOUT))
  {
    error_msg = "Script verification only";
    if (token!=EOL)
      lex_setrecovering();

    goto error;
  }

  switch (token)
  {
  case EOF:
      /* timlex() will return EOF when the remote disconnects badly */
      syslog(LOG_WARNING, "Lost connection to client -- exiting");
      ret = TRUE;
      goto done;
      break;

  case AUTHENTICATE:
    if (timlex(NULL, NULL, sieved_in)!=SPACE)
    {
      error_msg = "SPACE must occur after AUTHENTICATE";
      goto error;
    }

    if (timlex(&mechanism_name, NULL, sieved_in)!=STRING)
    {
      error_msg = "Did not specify mechanism name";
      goto error;
    }

    token = timlex(NULL, NULL, sieved_in);

    if (token != EOL)
    {
      /* optional client first challenge */
      if (token!=SPACE)
      {
	error_msg = "Expected SPACE";
	goto error;
      }

      if (timlex(&initial_challenge, NULL, sieved_in)!=STRING)
      {
	error_msg = "Expected string";
	goto error;
      }

      token = timlex(NULL, NULL, sieved_in);      
    }

    if (token != EOL)
    {
      error_msg = "Expected EOL";
      goto error;
    }

    if (authenticated)
	prot_printf(sieved_out, "NO \"Already authenticated\"\r\n");
    else if (cmd_authenticate(sieved_out, sieved_in, mechanism_name,
			      initial_challenge, &error_msg)==FALSE)
    {
	error_msg = "Authentication Error";
	goto error;
    }

#if 0 /* XXX - not implemented in sieveshell*/
    /* referral_host is non-null only once we are authenticated */
    if(referral_host)
	goto do_referral;
#endif
    break;

  case CAPABILITY:
      if (timlex(NULL, NULL, sieved_in)!=EOL)
      {
	  error_msg = "Expected EOL";
	  goto error;
      }

      if(referral_host)
	  goto do_referral;

      capabilities(sieved_out, sieved_saslconn, starttls_done, authenticated,
		   sasl_ssf);
      break;

  case CHECKSCRIPT:
      if (timlex(NULL, NULL, sieved_in)!=SPACE)
      {
          error_msg = "SPACE must occur after CHECKSCRIPT";
          goto error;
      }

      if (timlex(&sieve_data, NULL, sieved_in)!=STRING)
      {
          error_msg = "Did not specify legal script data length";
          goto error;
      }

      if (timlex(NULL, NULL, sieved_in)!=EOL)
      {
        error_msg = "Expected EOL";
        goto error;
      }

      /* f stands for "f"aked name, it could be any valid script name */
      string_allocate(1, "f", &sieve_name);
      putscript(sieved_out, sieve_name, sieve_data, /* verify_only */ 1);
      break;

  case HAVESPACE:
      if (timlex(NULL, NULL, sieved_in)!=SPACE)
      {
	  error_msg = "SPACE must occur after HAVESPACE";
	  goto error;
      }
      
      if (timlex(&sieve_name, NULL, sieved_in)!=STRING)
      {
	  error_msg = "Did not specify script name";
	  goto error;
      }
      
      if (timlex(NULL, NULL, sieved_in)!=SPACE)
      {
	  error_msg = "Expected SPACE";
	  goto error;
      }
      
      if (timlex(NULL, &num, sieved_in)!=NUMBER)
      {
	  error_msg = "Expected Number";
	  goto error;
      }

      if (timlex(NULL, NULL, sieved_in)!=EOL)
      {
	  error_msg = "Expected EOL";
	  goto error;
      }

      if(referral_host)
	  goto do_referral;

      cmd_havespace(sieved_out, sieve_name, num);

      break;

  case LOGOUT:
      token = timlex(NULL, NULL, sieved_in);
      
      /* timlex() will return LOGOUT when the remote disconnects badly */
      if (token!=EOL && token!=EOF && token!=LOGOUT)
      {
	  error_msg = "Garbage after logout command";
	  goto error;
      }

      /* no referral for logout */

      cmd_logout(sieved_out, sieved_in);
      
      ret = TRUE;
      goto done;
      break;

  case GETSCRIPT:
    if (timlex(NULL, NULL, sieved_in)!=SPACE)
    {
      error_msg = "SPACE must occur after GETSCRIPT";
      goto error;
    }

    if (timlex(&sieve_name, NULL, sieved_in)!=STRING)
    {
      error_msg = "Did not specify script name";
      goto error;
    }

    if (timlex(NULL, NULL, sieved_in)!=EOL)
    {
      error_msg = "Expected EOL";
      goto error;
    }

    if(referral_host)
	goto do_referral;

    getscript(sieved_out, sieve_name);
    
    break;


  case PUTSCRIPT:
    if (timlex(NULL, NULL, sieved_in)!=SPACE)
    {
      error_msg = "SPACE must occur after PUTSCRIPT";
      goto error;
    }

    if (timlex(&sieve_name, NULL, sieved_in)!=STRING)
    {
      error_msg = "Did not specify script name";
      goto error;
    }

    if (timlex(NULL, NULL, sieved_in)!=SPACE)
    {
      error_msg = "Expected SPACE";
      goto error;
    }

    if (timlex(&sieve_data, NULL, sieved_in)!=STRING)
    {
      error_msg = "Did not specify legal script data length";
      goto error;
    }

    if (timlex(NULL, NULL, sieved_in)!=EOL)
    {
      error_msg = "Expected EOL";
      goto error;
    }

    if(referral_host)
	goto do_referral;

    putscript(sieved_out, sieve_name, sieve_data, verify_only);
    
    break;

  case SETACTIVE:
    if (timlex(NULL, NULL, sieved_in)!=SPACE)
    {
      error_msg = "SPACE must occur after SETACTIVE";
      goto error;
    }

    if (timlex(&sieve_name, NULL, sieved_in)!=STRING)
    {
      error_msg = "Did not specify script name";
      goto error;
    }

    if (timlex(NULL, NULL, sieved_in)!=EOL)
    {
      error_msg = "Expected EOL";
      goto error;
    }

    if(referral_host)
	goto do_referral;

    setactive(sieved_out, sieve_name);
    
    break;

  case DELETESCRIPT:
    if (timlex(NULL, NULL, sieved_in)!=SPACE)
    {
      error_msg = "SPACE must occur after DELETESCRIPT";
      goto error;
    }

    if (timlex(&sieve_name, NULL, sieved_in)!=STRING)
    {
      error_msg = "Did not specify script name";
      goto error;
    }

    if (timlex(NULL, NULL, sieved_in)!=EOL)
    {
      error_msg = "Expected EOL";
      goto error;
    }

    if(referral_host)
	goto do_referral;

    deletescript(sieved_out, sieve_name);
    
    break;

  case LISTSCRIPTS:

    if (timlex(NULL, NULL, sieved_in)!=EOL)
    {
      error_msg = "Expected EOL";
      goto error;
    }

    if(referral_host)
	goto do_referral;
    
    listscripts(sieved_out);
    
    break;

  case STARTTLS:

    if (timlex(NULL, NULL, sieved_in)!=EOL)
    {
      error_msg = "Expected EOL";
      goto error;
    }

    /* XXX  discard any input pipelined after STARTTLS */
    prot_flush(sieved_in);

    if(referral_host)
	goto do_referral;

    cmd_starttls(sieved_out, sieved_in);
    
    break;

  case NOOP:

    token = timlex(NULL, NULL, sieved_in);
    mystring_t *noop_param = NULL;
    if (token != EOL)
    {
      /* optional string parameter */
      if (token!=SPACE)
      {
	error_msg = "Expected SPACE";
	goto error;
      }

      if (timlex(&noop_param, NULL, sieved_in)!=STRING)
      {
	error_msg = "Expected string";
	free(noop_param);
	goto error;
      }

      token = timlex(NULL, NULL, sieved_in);      
    }

    if (token != EOL)
    {
      error_msg = "Expected EOL";
      free(noop_param);
      goto error;
    }

    if (noop_param != NULL) {
      int temp;
      char* dataptr = string_DATAPTR(noop_param);
      prot_printf(sieved_out, "OK (TAG {%d}\r\n", noop_param->len);
      for (temp = 0; temp < noop_param->len; temp++)
      prot_putc(dataptr[temp], sieved_out);
      prot_printf(sieved_out, ") \"Done\"\r\n");
      free(noop_param);
    } else
      prot_printf(sieved_out, "OK \"Done\"\r\n");
    break;

  case UNAUTHENTICATE:
      if (timlex(NULL, NULL, sieved_in)!=EOL)
      {
	  error_msg = "Expected EOL";
	  goto error;
      }
      cmd_unauthenticate(sieved_out, sieved_in);
      break;

  default:
    error_msg="Expected a command. Got something else.";
    goto error;
    break;

  }

 done: 
  /* free memory */
  free(mechanism_name);
  free(initial_challenge);
  free(sieve_name);
  free(sieve_data);
 
  prot_flush(sieved_out);

  return ret;

 error:

  /* free memory */
  free(mechanism_name);
  free(initial_challenge);
  free(sieve_name);
  free(sieve_data);

  prot_printf(sieved_out, "NO \"%s\"\r\n",error_msg);
  prot_flush(sieved_out);

  return FALSE;

 do_referral:
  {
      char buf[4096];
      char *c;

      /* Truncate the hostname if necessary */
      strlcpy(buf, referral_host, sizeof(buf));
      c = strchr(buf, '!');
      if(c) *c = '\0';
      
      prot_printf(sieved_out, "BYE (REFERRAL \"sieve://%s\") \"Try Remote.\"\r\n",
		  buf);
      ret = TRUE;
      goto done;
  }

}
Esempio n. 2
0
static int fetch(char *msgid, int bymsgid,
	  struct protstream *pin, struct protstream *pout,
	  struct protstream *sin, struct protstream *sout,
	  int *rejected, int *accepted, int *failed)
{
    char buf[4096];

    /* see if we want this article */
    prot_printf(sout, "IHAVE %s\r\n", msgid);
    if (!prot_fgets(buf, sizeof(buf), sin)) {
	syslog(LOG_ERR, "IHAVE terminated abnormally");
	return -1;
    }
    else if (strncmp("335", buf, 3)) {
	/* don't want it */
	(*rejected)++;
	return 0;
    }

    /* fetch the article */
    if (bymsgid)
	prot_printf(pout, "ARTICLE %s\r\n", msgid);
    else
	prot_printf(pout, "ARTICLE\r\n");

    if (!prot_fgets(buf, sizeof(buf), pin)) {
	syslog(LOG_ERR, "ARTICLE terminated abnormally");
	return -1;
    }
    else if (strncmp("220", buf, 3)) {
	/* doh! the article doesn't exist, terminate IHAVE */
	prot_printf(sout, ".\r\n");
    }
    else {
	/* store the article */
	while (prot_fgets(buf, sizeof(buf), pin)) {
	    if (buf[0] == '.') {
		if (buf[1] == '\r' && buf[2] == '\n') {
		    /* End of message */
		    prot_printf(sout, ".\r\n");
		    break;
		}
		else if (buf[1] != '.') {
		    /* Add missing dot-stuffing */
		    prot_putc('.', sout);
		}
	    }

	    do {
		/* look for malformed lines with NUL CR LF */
		if (buf[strlen(buf)-1] != '\n' &&
		    strlen(buf)+2 < sizeof(buf)-1 &&
		    buf[strlen(buf)+2] == '\n') {
		    strlcat(buf, "\r\n", sizeof(buf));
		}
		prot_printf(sout, "%s", buf);
	    } while (buf[strlen(buf)-1] != '\n' &&
		     prot_fgets(buf, sizeof(buf), pin));
	}

	if (buf[0] != '.') {
	    syslog(LOG_ERR, "ARTICLE terminated abnormally");
	    return -1;
	}
    }

    /* see how we did */
    if (!prot_fgets(buf, sizeof(buf), sin)) {
	syslog(LOG_ERR, "IHAVE terminated abnormally");
	return -1;
    }
    else if (!strncmp("235", buf, 3))
	(*accepted)++;
    else
	(*failed)++;

    return 0;
}
Esempio n. 3
0
EXPORTED void dlist_print(const struct dlist *dl, int printkeys,
                 struct protstream *out)
{
    struct dlist *di;

    if (printkeys) {
        prot_printastring(out, dl->name);
        prot_putc(' ', out);
    }

    switch (dl->type) {
    case DL_NIL:
        prot_printf(out, "NIL");
        break;
    case DL_ATOM:
        prot_printastring(out, dl->sval);
        break;
    case DL_FLAG:
        prot_printf(out, "%s", dl->sval);
        break;
    case DL_NUM:
    case DL_DATE: /* for now, we will format it later */
        prot_printf(out, "%llu", dl->nval);
        break;
    case DL_FILE:
        printfile(out, dl);
        break;
    case DL_BUF:
        if (strlen(dl->sval) == dl->nval)
            prot_printastring(out, dl->sval);
        else
            prot_printliteral(out, dl->sval, dl->nval);
        break;
    case DL_GUID:
        prot_printf(out, "%s", message_guid_encode(dl->gval));
        break;
    case DL_HEX:
        {
            char buf[17];
            snprintf(buf, 17, "%016llx", dl->nval);
            prot_printf(out, "%s", buf);
        }
        break;
    case DL_KVLIST:
        prot_printf(out, "%%(");
        for (di = dl->head; di; di = di->next) {
            dlist_print(di, 1, out);
            if (di->next) {
                prot_printf(out, " ");
            }
        }
        prot_printf(out, ")");
        break;
    case DL_ATOMLIST:
        prot_printf(out, "(");
        for (di = dl->head; di; di = di->next) {
            dlist_print(di, dl->nval, out);
            if (di->next)
                prot_printf(out, " ");
        }
        prot_printf(out, ")");
        break;
    }
}