Exemplo n.º 1
0
int acl_read2(maildir_aclt_list *l,
	      struct maildir_info *minfo,
	      char **owner)
{
	int rc;
	char *p;

	if (minfo->mailbox_type == MAILBOXTYPE_OLDSHARED)
	{
		/* Legacy shared., punt. */

		maildir_aclt_list_init(l);
		if (maildir_aclt_list_add(l, "anyone",
					  ACL_LOOKUP ACL_READ
					  ACL_SEEN ACL_WRITE
					  ACL_INSERT
					  ACL_DELETEMSGS ACL_EXPUNGE, NULL) < 0
		    || (*owner=strdup("vendor=courier.internal")) == NULL)
		{
			maildir_aclt_list_destroy(l);
			return -1;
		}
		return 0;
	}

	if (minfo->homedir == NULL || minfo->maildir == NULL)
		return -1;

	p=maildir_name2dir(".", minfo->maildir);

	if (!p)
		return -1;

	rc=maildir_acl_read(l, minfo->homedir,
			    strncmp(p, "./", 2) == 0 ? p+2:p);
	free(p);
	if (owner && rc == 0)
	{
		*owner=minfo->owner;
		minfo->owner=NULL;
	}
	return rc;
}
Exemplo n.º 2
0
static char *smap_path(const char *homedir,
		       char **words)  /* words[0] better be INBOX! */
{
	struct get_existing_folder_info gefi;
	char *n, *p;
	struct stat stat_buf;

	if ((n=smaptoUtf7(words)) == NULL)
		return NULL;

	p=maildir_name2dir(homedir, n);

	if (!p)
	{
		free(n);
		return NULL;
	}

	if (stat(p, &stat_buf) == 0)
	{
		free(p);
		return n;
	}

	gefi.fn=words;
	gefi.pathname=NULL;

	maildir_list(homedir ? homedir:".",
		     &get_existing_callback, &gefi);

	if (gefi.pathname)
	{
		free(n);
		free(p);

		return gefi.pathname;
	}

	free(p);
	return n;
}
Exemplo n.º 3
0
static void doupdate()
{
	maildir_aclt_list l;
	char *owner;
	char buf[2];
	char *p;
	struct maildir_info minfo;

	if (maildir_info_imap_find(&minfo, sqwebmail_folder,
				   login_returnaddr()) < 0)
		return;

	if (acl_read2(&l, &minfo, &owner) < 0)
	{
		maildir_info_destroy(&minfo);
		return;
	}

	strcpy(buf, ACL_ADMINISTER);
	acl_computeRights(&l, buf, owner);
	if (!*buf)
	{
		if (owner)
			free(owner);
		maildir_aclt_list_destroy(&l);
		maildir_info_destroy(&minfo);
		return;
	}

	if (*cgi("delentity"))
	{
		if (maildir_aclt_list_del(&l, cgi("delentity")))
			printf("%s", getarg("ACL_failed"));
	}

	if (*cgi("do.update"))
	{
		char *entity=NULL;
		const char *p;
		char new_acl[40];

		p=cgi("entitytype");

		if (strcmp(p, "anonymous") == 0 ||
		    strcmp(p, "owner") == 0)
			entity=strdup(p);
		else if (strcmp(p, "user") == 0)
		{
			p=cgi("entity");

			if (*p)
			{
				entity=malloc(sizeof("user="******"user="******"group") == 0)
		{
			p=cgi("entity");

			if (*p)
			{
				entity=malloc(sizeof("group=")+strlen(p));
				if (entity)
					strcat(strcpy(entity, "group="), p);
			}
		}
		else
		{
			entity=strdup(cgi("entity"));
		}

		if (*cgi("negate") == '-' && entity)
		{
			char *p=malloc(strlen(entity)+2);

			if (p)
				strcat(strcpy(p, "-"), entity);
			free(entity);
			entity=p;
		}

		if (entity)
		{
			char *val=
				unicode_convert_toutf8(entity,
							 sqwebmail_content_charset,
							 NULL);


			if (val)
			{
				free(entity);
				entity=val;
			}
		}
		p=getarg("ACL_all");

		new_acl[0]=0;

		while (*p && strlen(new_acl) < sizeof(new_acl)-2)
		{
			char b[40];

			sprintf(b, "acl_%c", *p);

			if (*cgi(b))
			{
				b[0]=*p;
				b[1]=0;
				strcat(new_acl, b);
			}
			++p;
		}

		if (!entity || !*entity ||
		    maildir_aclt_list_add(&l, entity, new_acl, NULL) < 0)
			printf("%s", getarg("ACL_failed"));

		if (entity)
			free(entity);
	}

	p=maildir_name2dir(".", minfo.maildir);

	if (p)
	{
		const char *err_ident;

		if (maildir_acl_write(&l, minfo.homedir,
				      strncmp(p, "./", 2) == 0 ? p+2:p,
				      owner, &err_ident))
			printf("%s", getarg("ACL_failed"));
		free(p);
	}

	if (owner)
		free(owner);
	maildir_aclt_list_destroy(&l);
	maildir_info_destroy(&minfo);
}
Exemplo n.º 4
0
int maildir_filter_saverules(struct maildirfilter *r, const char *filename,
		 const char *maildir,
		 const char *maildirpath, const char *fromaddr)
{
FILE	*f=fopen(filename, "w");
struct maildirfilterrule *p;

	if (!f)	return (-1);

	fprintf(f,	"#MFMAILDROP=2\n"
			"#\n"
			"# DO NOT EDIT THIS FILE.  This is an automatically"
						" generated filter.\n"
			"\n");

	for (fprintf(f, "FROM='"); *fromaddr; fromaddr++)
	{
		if (*fromaddr == '\'' || *fromaddr == '\\')
			putc('\\', f);
		putc(*fromaddr, f);
	}
	fprintf(f, "\'\n");

	for (p=r->first; p; p=p->next)
	{
	const char *fieldname=p->fieldname_utf8 ? p->fieldname_utf8:"";
	const char *fieldvalue=p->fieldvalue_utf8 ? p->fieldvalue_utf8:"";
	const char *tofolder=p->tofolder ? p->tofolder:"";

		fprintf(f, "##Op:%s\n",
			typelist[p->type].name);
		fprintf(f, "##Header:%s\n", fieldname);
		fprintf(f, "##Value:%s\n", fieldvalue);
		fprintf(f, "##Folder:%s\n",
			strcmp(tofolder, INBOX) == 0 ? ".":
			strncmp(tofolder, INBOX ".", sizeof(INBOX)) == 0
			? strchr(tofolder, '.'):tofolder);
		fprintf(f, "##From:%s\n", p->fromhdr ? p->fromhdr:"");

		if (p->flags & MFR_PLAINSTRING)
			fprintf(f, "##PlainString\n");
		if (p->flags & MFR_DOESNOT)
			fprintf(f, "##DoesNot\n");
		if (p->flags & MFR_BODY)
			fprintf(f, "##Body\n");
		if (p->flags & MFR_CONTINUE)
			fprintf(f, "##Continue\n");

		fprintf(f, "##Name:%s\n\n", p->rulename_utf8 ? p->rulename_utf8:"");

		fprintf(f, "\nif (");

		if (p->flags & MFR_DOESNOT)
			fprintf(f, "!");
		fprintf(f, "(");

		switch (p->type)	{
		case startswith:
			if (p->flags & MFR_BODY)
			{
				fprintf(f, "/^");
				print_pattern(f, p->flags, fieldvalue);
				fprintf(f, "/:b");
			}
			else
			{
				fprintf(f, "/^%s: *", fieldname);
				print_pattern(f, p->flags, fieldvalue);
				fprintf(f, "/");
			}
			break;
		case endswith:
			if (p->flags & MFR_BODY)
			{
				fprintf(f, "/");
				print_pattern(f, p->flags, fieldvalue);
				fprintf(f, "$/:b");
			}
			else
			{
				fprintf(f, "/^%s:.*", fieldname);
				print_pattern(f, p->flags, fieldvalue);
				fprintf(f, "$/");
			}
			break;
		case contains:
			if (p->flags & MFR_BODY)
			{
				fprintf(f, "/");
				print_pattern(f, p->flags, fieldvalue);
				fprintf(f, "/:b");
			}
			else
			{
				fprintf(f, "/^%s:.*", fieldname);
				print_pattern(f, p->flags, fieldvalue);
				fprintf(f, "/");
			}
			break;
		case hasrecipient:
			fprintf(f, "hasaddr(\"%s\")", fieldvalue);
			break;
		case mimemultipart:
			fprintf(f, "/^Content-Type: *multipart\\/mixed/");
			break;
		case textplain:
			fprintf(f, " (! /^Content-Type:/) || "
					"/^Content-Type: text\\/plain$/ || "
					"/^Content-Type: text\\/plain;/");
			break;
		case islargerthan:
			fprintf(f, "$SIZE > %s", fieldvalue);
			break;
		case anymessage:
			fprintf(f, "1");
			break;
		}
		fprintf(f, "))\n"
			"{\n");

		if (*tofolder == '!')
		{
			fprintf(f, "    %s \"| $SENDMAIL -f \" '\"\"' \" %s\"\n",
				p->flags & MFR_CONTINUE ? "cc":"to",
					tofolder+1);
		}
		else if (*tofolder == '*')
		{
			fprintf(f, "    echo \"%s\"\n"
				"    EXITCODE=%d\n"
				"    exit\n", tofolder+1, EX_SOFTWARE);
		}
		else if (*tofolder == '+')
		{
			struct maildir_filter_autoresp_info ai;

			if (maildir_filter_autoresp_info_init_str(&ai, tofolder+1) == 0)
			{
				if (p->fromhdr && p->fromhdr[0])
				{
					const char *cp;

					fprintf(f, "    AUTOREPLYFROM='");


					for (cp=p->fromhdr; *cp; ++cp)
					{
						if (*cp == '\'' || *cp == '\\')
							putc('\\', f);
						putc(*cp, f);
					}
					fprintf(f, "'\n");
				}
				else
					fprintf(f, "    AUTOREPLYFROM=\"$FROM\"\n"
						);

				fprintf(f, "   `%s -A \"X-Sender: $FROM\""
					" -A \"From: $AUTOREPLYFROM\"",
					MAILBOT);
				if (ai.dsnflag)
					fprintf(f, " -M \"$FROM\"");
				fprintf(f, " -m \"%s/autoresponses/%s\"",
					maildirpath, ai.name);
				if (ai.noquote)
					fprintf(f, " -N");
				if (ai.days > 0)
					fprintf(f,
						" -d \"%s/autoresponses/"
						"%s.dat\" -D %u",
					maildirpath, ai.name, ai.days);
				fprintf(f, " $SENDMAIL -t -f \"\"`\n");
				maildir_filter_autoresp_info_free(&ai);
			}
		}
		else if (strcmp(tofolder, "exit") == 0)
		{
			fprintf(f, "    exit\n");
		}
		else
		{
			char *s;

			s=maildir_name2dir(maildirpath, tofolder);

			if (!s)
				fprintf(f, "  # INTERNAL ERROR in maildir_name2dir\n");
			else
			{
				fprintf(f,
					"   %s \"%s/.\"\n",
					p->flags & MFR_CONTINUE ? "cc":"to",
					s);
				free(s);
			}
		}
		fprintf(f, "}\n\n");
	}
	fflush(f);
	if (ferror(f))
	{
		fclose(f);
		return (-1);
	}
	fprintf(f, "to \"%s/.\"\n", maildirpath);
	if (fclose(f))
		return (-1);
	if (chmod(filename, 0600))
		return (-1);

	return (0);
}
Exemplo n.º 5
0
static int maildir_filter_ruleupdate_utf8(struct maildirfilter *r,
					  struct maildirfilterrule *p,
					  const char *name,
					  enum maildirfiltertype type,
					  int flags,
					  const char *header,
					  const char *value,
					  const char *folder,
					  const char *fromhdr,
					  int *errcode)
{
	const char *c;
	struct maildirfilterrule *pom;

/*
** Before creating a new rule, validate all input.
*/

	*errcode=0;

	/* rule name: may not contain quotes or control characters. */
	*errcode=MF_ERR_BADRULENAME;
	if (!*name || strlen(name) > 200)
		return (-1);

	for (c=name; *c; c++)
		if ((unsigned char)*c < ' ' || *c == '\'' || *c == '"' ||
			*c == '`')
			return (-1);

	/* rule name: may not already exist */
	*errcode=MF_ERR_EXISTS;
	
	for (pom=r->first; pom->next; pom=pom->next) {
	    if (p!=pom && !strcmp(name, pom->rulename_utf8))
		return (-1);
	}

	/* rule type: we must know what it is */

	switch (type)	{
	case startswith:
	case endswith:
	case contains:
	case hasrecipient:
	case mimemultipart:
	case textplain:
	case islargerthan:
	case anymessage:
		break;
	default:
		*errcode=MF_ERR_BADRULETYPE;
		break;
	} ;

	/* header: */

	*errcode=MF_ERR_BADRULEHEADER;

	c=header;
	if (strlen(c) > 200)	return (-1);
	if (*c == 0)
	{
		switch (type)	{
		case hasrecipient:
		case islargerthan:
		case mimemultipart:
		case textplain:
		case anymessage:
			break;
		case contains:
		case startswith:
		case endswith:
			if (flags & MFR_BODY)
				break;
			/* FALLTHRU */
		default:
			/* required */

			return (-1);
		}
	}
	else for ( ; *c; c++)
	{
		/* no control characters */
		if ((unsigned char)*c <= ' ' || *c == MDIRSEP[0] ||
		    *c == '\'' ||
		    *c == '\\' || *c == '"' || *c == '`' || *c == '/')
			return (-1);
	}

	/* rule pattern */

	*errcode=MF_ERR_BADRULEVALUE;

	c=value;
	if (strlen(c) > 200)	return (-1);
	if (*c == 0)
	{
		switch (type)	{
		case mimemultipart:
		case textplain:
		case anymessage:
			break;
		default:
			/* required */

			return (-1);
		}
	}
	else if (!(flags & MFR_PLAINSTRING))
	{
		/*
		** Let PCRE decide if this is a valid pattern.
		**
		** One exception: the forward slash character, and some other
		** special characters, must always be escaped.
		*/

		while (*c)
		{
			if (*c == '/' || *c == '$' || *c == '!'
				|| *c == '`' || (int)(unsigned char)*c < ' '
				|| *c == '\'' || *c == '"') return (-1);
						/* must be escaped */

			if (type == islargerthan)
			{
				if (!isdigit((int)(unsigned char)*c))
					return (-1);
			}

			if (*c == '(')
			{
				if (type == hasrecipient)	return (-1);
				++c;
				if (*c == ')')	return (-1);
				continue;
			}
			if (*c == ')')
			{
				if (type == hasrecipient)	return (-1);
				++c;
				continue;
			}
			if (*c == '[')	/* This is a set */
			{
				if (type == hasrecipient)	return (-1);
				++c;
				for (;;)
				{
					if (*c == '\'' || *c == '"' ||
						*c == '`')
						return (-1); /* must be quoted*/
					if (*c == '\\')
						++c;
					if (!*c)	return (-1);
					if ((int)(unsigned char)*c < ' ')
						return (-1);
					++c;
					if (*c == ']')	break;
					if (*c != '-')	continue;
					++c;

					if (*c == '\'' || *c == '"' ||
						*c == '`')
						return (-1); /* must be quoted*/
					if (*c == '\\')
						++c;
					if ((int)(unsigned char)*c < ' ')
						return (-1);
					if (!*c)	return (-1);
					++c;
					if (*c == ']')	break;
				}
				++c;
				continue;
			}

			if (*c == '\\')
			{
				if (type == hasrecipient)	return (-1);
				++c;
			}
			if (!*c)	return (-1);
			++c;
		}

#if HAVE_PCRE_H
		switch (type) {
		case contains:
		case startswith:
		case endswith:
			{
				const char *errptr;
				int errindex;

				pcre *p=pcre_compile(value, PCRE_UTF8,
						     &errptr,
						     &errindex,
						     0);


				if (p == NULL)
					return -1;
				pcre_free(p);
			}
			break;
		default:
			break;
		}
#endif
	}

	/* validate FROM header */

	*errcode=MF_ERR_BADFROMHDR;

	while (fromhdr && *fromhdr && isspace((int)(unsigned char)*fromhdr))
		++fromhdr;

	for (c=fromhdr; *c; c++)
		if ((int)(unsigned char)*c < ' ')
			return (-1);

	*errcode=MF_ERR_BADRULEFOLDER;

	/* validate name of destination folder */

	c=folder;
	if (!c)	return (-1);
	if (strlen(c) > 200)	return (-1);

	if (*c == '*' || *c == '!')
	{
		/* Forward, or bounce with an error */

		++c;
		for ( ; *c; c++)
		{
			if (strchr("'\"$\\`;(){}#&<>~", *c) ||
				(unsigned char)*c < ' ')
				return (-1);
		}
	}
	else if (*c == '+')	/* Autorespond */
	{
		struct maildir_filter_autoresp_info ai;

		if (maildir_filter_autoresp_info_init_str(&ai, c+1))
			return (-1);

		maildir_filter_autoresp_info_free(&ai);
	}
	else if (strcmp(c, "exit") == 0)	/* Purge */
	{
	}
	else
	{
		char *s;

		if (strcmp(c, INBOX) &&
		    strncmp(c, INBOX ".", sizeof(INBOX)))
			return -1;

		s=maildir_name2dir(".", c);

		if (!s)
			return -1;
		free(s);
	}

	/* OK, we're good */

	*errcode=MF_ERR_INTERNAL;

	if (p->rulename_utf8)	free(p->rulename_utf8);
	if ((p->rulename_utf8=strdup(name)) == 0)	return (-1);
	p->type=type;
	if (p->fieldname_utf8)	free(p->fieldname_utf8);
	if ((p->fieldname_utf8=strdup(header ? header:"")) == 0)	return (-1);
	if (p->fieldvalue_utf8)	free(p->fieldvalue_utf8);
	if ((p->fieldvalue_utf8=strdup(value ? value:"")) == 0)	return (-1);
	if (p->tofolder)	free(p->tofolder);
	if ((p->tofolder=malloc(strlen(folder)+1)) == 0)	return (-1);
	strcpy(p->tofolder, folder);

	if (p->fromhdr)		free(p->fromhdr);
	if ((p->fromhdr=strdup(fromhdr ? fromhdr:"")) == NULL)
		return (-1);

	p->flags=flags;
	return (0);
}