Exemple #1
0
int rfc822_parse_phrase(struct rfc822_parser_context *ctx, string_t *str)
{
    int ret;

    /*
       phrase     = 1*word / obs-phrase
       word       = atom / quoted-string
       obs-phrase = word *(word / "." / CFWS)
    */

    if (ctx->data == ctx->end)
        return 0;
    if (*ctx->data == '.')
        return -1;

    for (;;) {
        if (*ctx->data == '"')
            ret = rfc822_parse_quoted_string(ctx, str);
        else
            ret = rfc822_parse_atom_or_dot(ctx, str);

        if (ret <= 0)
            return ret;

        if (!IS_ATEXT(*ctx->data) && *ctx->data != '"'
                && *ctx->data != '.')
            break;
        str_append_c(str, ' ');
    }
    return rfc822_skip_lwsp(ctx);
}
Exemple #2
0
/*
 * [RFC2822]
 * atext = ALPHA / DIGIT / ; Any character except controls,
 *         "!" / "#" /     ;  SP, and specials.
 *         "$" / "%" /     ;  Used for atoms
 *         "&" / "'" /
 *         "*" / "+" /
 *         "-" / "/" /
 *         "=" / "?" /
 *         "^" / "_" /
 *         "`" / "{" /
 *         "|" / "}" /
 *         "~"
 */
int
XSkip_atextBlock(const char *head, const char *tail, const char **nextp)
{
    const char *p;
    for (p = head; p < tail && IS_ATEXT(*p); ++p);
    *nextp = p;
    return *nextp - head;
}   // end function : XSkip_atextBlock
Exemple #3
0
int rfc822_parse_dot_atom(struct rfc822_parser_context *ctx, string_t *str)
{
	const unsigned char *start;
	int ret;

	/*
	   dot-atom        = [CFWS] dot-atom-text [CFWS]
	   dot-atom-text   = 1*atext *("." 1*atext)

	   atext           =
	     ; Any character except controls, SP, and specials.

	   For RFC-822 compatibility allow LWSP around '.'
	*/
	if (ctx->data == ctx->end || !IS_ATEXT(*ctx->data))
		return -1;

	for (start = ctx->data++; ctx->data != ctx->end; ) {
		if (IS_ATEXT(*ctx->data)) {
			ctx->data++;
			continue;
		}

		str_append_n(str, start, ctx->data - start);

		if ((ret = rfc822_skip_lwsp(ctx)) <= 0)
			return ret;

		if (*ctx->data != '.')
			return 1;

		ctx->data++;
		str_append_c(str, '.');

		if ((ret = rfc822_skip_lwsp(ctx)) <= 0)
			return ret;
		start = ctx->data;
	}

	str_append_n(str, start, ctx->data - start);
	return 0;
}
Exemple #4
0
int
valid_localpart(const char *s)
{
#define IS_ATEXT(c) (isalnum((unsigned char)(c)) || strchr(MAILADDR_ALLOWED, (c)))
nextatom:
	if (!IS_ATEXT(*s) || *s == '\0')
		return 0;
	while (*(++s) != '\0') {
		if (*s == '.')
			break;
		if (IS_ATEXT(*s))
			continue;
		return 0;
	}
	if (*s == '.') {
		s++;
		goto nextatom;
	}
	return 1;
}
Exemple #5
0
int
valid_localpart(char *s)
{
#define IS_ATEXT(c)     (isalnum((int)(c)) || strchr("!#$%&'*+-/=?^_`{|}~", (c)))
nextatom:
        if (! IS_ATEXT(*s) || *s == '\0')
                return 0;
        while (*(++s) != '\0') {
                if (*s == '.')
                        break;
                if (IS_ATEXT(*s))
                        continue;
                return 0;
        }
        if (*s == '.') {
                s++;
                goto nextatom;
        }
        return 1;
}
Exemple #6
0
int rfc822_parse_atom(struct rfc822_parser_context *ctx, string_t *str)
{
    const unsigned char *start;

    /*
       atom            = [CFWS] 1*atext [CFWS]
       atext           =
         ; Any character except controls, SP, and specials.
    */
    if (ctx->data == ctx->end || !IS_ATEXT(*ctx->data))
        return -1;

    for (start = ctx->data++; ctx->data != ctx->end; ctx->data++) {
        if (IS_ATEXT(*ctx->data))
            continue;

        str_append_n(str, start, ctx->data - start);
        return rfc822_skip_lwsp(ctx);
    }

    str_append_n(str, start, ctx->data - start);
    return 0;
}
Exemple #7
0
int
valid_localpart(const char *s)
{
/*
 * RFC 5322 defines theses characters as valid: !#$%&'*+-/=?^_`{|}~
 * some of them are potentially dangerous, and not so used after all.
 */
#define IS_ATEXT(c)     (isalnum((int)(c)) || strchr("*!%+-/=_", (c)))
nextatom:
	if (! IS_ATEXT(*s) || *s == '\0')
		return 0;
	while (*(++s) != '\0') {
		if (*s == '.')
			break;
		if (IS_ATEXT(*s))
			continue;
		return 0;
	}
	if (*s == '.') {
		s++;
		goto nextatom;
	}
	return 1;
}
Exemple #8
0
static int
rfc822_parse_atom_or_dot(struct rfc822_parser_context *ctx, string_t *str)
{
    const unsigned char *start;

    /*
       atom            = [CFWS] 1*atext [CFWS]
       atext           =
         ; Any character except controls, SP, and specials.

       The difference between this function and rfc822_parse_dot_atom()
       is that this doesn't just silently skip over all the whitespace.
    */
    for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
        if (IS_ATEXT(*ctx->data) || *ctx->data == '.')
            continue;

        str_append_n(str, start, ctx->data - start);
        return rfc822_skip_lwsp(ctx);
    }

    str_append_n(str, start, ctx->data - start);
    return 0;
}
Exemple #9
0
static bool
DkimWildcard_matchPubkeyGranularityImpl(const char *pattern_head, const char *pattern_tail,
                                        const char *target_head, const char *target_tail,
                                        bool accept_wildcard)
{
    /*
     * the ABNF of key-g-tag-lpart says only one wildcard is acceptable.
     * But '*' itself is included in dot-atom-text.
     * So this function treats the first occurrence of '*' as wildcard,
     * and next or later occurrence of '*' as character.
     *
     * [RFC4871] 3.6.1.
     * key-g-tag       = %x67 [FWS] "=" [FWS] key-g-tag-lpart
     * key-g-tag-lpart = [dot-atom-text] ["*" [dot-atom-text] ]
     */

    const char *pattern;
    const char *target;

    for (pattern = pattern_head, target = target_head; pattern < pattern_tail; ++pattern, ++target) {
        if ('*' == *pattern) {
            if (accept_wildcard) {
                // treat '*' as wildcard
                ++pattern;
                for (const char *bq = target_tail; target <= bq; --bq) {
                    if (DkimWildcard_matchPubkeyGranularityImpl
                        (pattern, pattern_tail, bq, target_tail, false)) {
                        return true;
                    }   // end if
                }   // end for
                return false;
            } else {
                // treat '*' as (not wildcard but) character
                if (target_tail <= target || '*' != *target) {
                    return false;
                }   // end if
            }   // end if
        } else if (IS_ATEXT(*pattern) || '.' == *pattern) {
            /*
             * compare case-sensitively.
             *
             * [RFC6376] 3.2.
             * Values MUST be
             * processed as case sensitive unless the specific tag description of
             * semantics specifies case insensitivity.
             *
             * And the local-part of mailbox is essentially treated as case-sensitive.
             *
             * [RFC5321] 2.4.
             * ... The
             * local-part of a mailbox MUST BE treated as case sensitive.
             */
            if (target_tail <= target || *pattern != *target) {
                return false;
            }   // end if
        } else {
            // neither atext nor '.' (included in dot-atom-text)
            return false;
        }   // end if
    }   // end for
    return bool_cast(pattern == pattern_tail && target == target_tail);
}   // end function: DkimWildcard_matchPubkeyGranularityImpl