Example #1
0
/*
 * Parse an option.
 *
 * Returns a dynamically allocated string containing the next module
 * option, or NULL if the end of the string was reached or a disallowed
 * non-whitespace character was encountered.
 *
 * If parse_option() is successful, it updates *line to point one
 * character past the end of the option.  If it reaches the end of the
 * string, it updates *line to point to the terminating NUL character.  In
 * all other cases, it leaves *line unmodified.
 *
 * If parse_option() fails to allocate memory, it will return NULL and set
 * errno to a non-zero value.
 *
 * Allowed characters for option names are all characters in the POSIX
 * portable filename character set.  Allowed characters for option values
 * are any printable non-whitespace characters.  The option value may be
 * quoted in either single or double quotes, in which case space
 * characters and whichever quote character was not used are allowed.
 * Note that the entire value must be quoted, not just part of it.
 */
static char *
parse_option(char **line)
{
	char *nb, *ne, *vb, *ve;
	unsigned char q = 0;
	char *option;
	size_t size;

	errno = 0;
	for (nb = *line; *nb && is_lws(*nb); ++nb)
		/* nothing */ ;
	if (!*nb) {
		*line = nb;
		return (NULL);
	}
	for (ne = nb; *ne && !is_lws(*ne) && *ne != '='; ++ne)
		if (!is_pfcs(*ne))
			return (NULL);
	if (ne == nb)
		return (NULL);
	if (*ne == '=') {
		vb = ne + 1;
		if (*vb == '"' || *vb == '\'')
			q = *vb++;
		for (ve = vb;
		     *ve && *ve != q && (is_p(*ve) || (q && is_lws(*ve)));
		     ++ve)
			/* nothing */ ;
		if (q && *ve != q)
			/* non-printable character or missing endquote */
			return (NULL);
		if (q && *(ve + 1) && !is_lws(*(ve + 1)))
			/* garbage after value */
			return (NULL);
	} else {
		vb = ve = ne;
	}
	size = (ne - nb) + 1;
	if (ve > vb)
		size += (ve - vb) + 1;
	if ((option = malloc(size)) == NULL)
		return (NULL);
	strncpy(option, nb, ne - nb);
	if (ve > vb) {
		option[ne - nb] = '=';
		strncpy(option + (ne - nb) + 1, vb, ve - vb);
	}
	option[size - 1] = '\0';
	*line = q ? ve + 1 : ve;
	return (option);
}
Example #2
0
/*
 * Parse the service name.
 *
 * Returns the length of the service name, or 0 if the end of the string
 * was reached or a disallowed non-whitespace character was encountered.
 *
 * If parse_service_name() is successful, it updates *service to point to
 * the first character of the service name and *line to point one
 * character past the end.  If it reaches the end of the string, it
 * updates *line to point to the terminating NUL character and leaves
 * *service unmodified.  In all other cases, it leaves both *line and
 * *service unmodified.
 *
 * Allowed characters are all characters in the POSIX portable filename
 * character set.
 */
static int
parse_service_name(char **line, char **service)
{
	char *b, *e;

	for (b = *line; *b && is_lws(*b); ++b)
		/* nothing */ ;
	if (!*b) {
		*line = b;
		return (0);
	}
	for (e = b; *e && !is_lws(*e); ++e)
		if (!is_pfcs(*e))
			return (0);
	if (e == b)
		return (0);
	*line = e;
	*service = b;
	return (e - b);
}
Example #3
0
/*
 * Parse a file name.
 *
 * Returns the length of the file name, or 0 if the end of the string was
 * reached or a disallowed non-whitespace character was encountered.
 *
 * If parse_filename() is successful, it updates *filename to point to the
 * first character of the filename and *line to point one character past
 * the end.  If it reaches the end of the string, it updates *line to
 * point to the terminating NUL character and leaves *filename unmodified.
 * In all other cases, it leaves both *line and *filename unmodified.
 *
 * Allowed characters are all characters in the POSIX portable filename
 * character set, plus the path separator (forward slash).
 */
static int
parse_filename(char **line, char **filename)
{
	char *b, *e;

	for (b = *line; *b && is_lws(*b); ++b)
		/* nothing */ ;
	if (!*b) {
		*line = b;
		return (0);
	}
	for (e = b; *e && !is_lws(*e); ++e)
		if (!is_pfcs(*e) && *e != '/')
			return (0);
	if (e == b)
		return (0);
	*line = e;
	*filename = b;
	return (e - b);
}
Example #4
0
/*
 * Parse the word "include".
 *
 * If the next word on the line is "include", parse_include() updates
 * *line to point one character past "include" and returns 1.  Otherwise,
 * it leaves *line unmodified and returns 0.
 */
static int
parse_include(char **line)
{
	char *b, *e;

	for (b = *line; *b && is_lws(*b); ++b)
		/* nothing */ ;
	if (!*b) {
		*line = b;
		return (-1);
	}
	for (e = b; *e && !is_lws(*e); ++e)
		/* nothing */ ;
	if (e == b)
		return (0);
	if (strlcmp("include", b, e - b) != 0)
		return (0);
	*line = e;
	return (1);
}
Example #5
0
/*
 * Consume trailing whitespace.
 *
 * If there are no non-whitespace characters left on the line, parse_eol()
 * updates *line to point at the terminating NUL character and returns 0.
 * Otherwise, it leaves *line unmodified and returns a non-zero value.
 */
static int
parse_eol(char **line)
{
	char *p;

	for (p = *line; *p && is_lws(*p); ++p)
		/* nothing */ ;
	if (*p)
		return ((unsigned char)*p);
	*line = p;
	return (0);
}
Example #6
0
/*
 * Parse the control flag.
 *
 * Returns the corresponding pam_control_t value, or -1 if the end of the
 * string was reached, a disallowed non-whitespace character was
 * encountered, or the first word was not a recognized control flag.
 *
 * If parse_control_flag() is successful, it updates *line to point one
 * character past the end of the control flag.  If it reaches the end of
 * the string, it updates *line to point to the terminating NUL character.
 * In all other cases, it leaves *line unmodified.
 */
static pam_control_t
parse_control_flag(char **line)
{
	char *b, *e;
	int i;

	for (b = *line; *b && is_lws(*b); ++b)
		/* nothing */ ;
	if (!*b) {
		*line = b;
		return ((pam_control_t)-1);
	}
	for (e = b; *e && !is_lws(*e); ++e)
		/* nothing */ ;
	if (e == b)
		return ((pam_control_t)-1);
	for (i = 0; i < PAM_NUM_CONTROL_FLAGS; ++i)
		if (strlcmp(pam_control_flag_name[i], b, e - b) == 0)
			break;
	if (i == PAM_NUM_CONTROL_FLAGS)
		return ((pam_control_t)-1);
	*line = e;
	return (i);
}
Example #7
0
/*
 * Parse the facility name.
 *
 * Returns the corresponding pam_facility_t value, or -1 if the end of the
 * string was reached, a disallowed non-whitespace character was
 * encountered, or the first word was not a recognized facility name.
 *
 * If parse_facility_name() is successful, it updates *line to point one
 * character past the end of the facility name.  If it reaches the end of
 * the string, it updates *line to point to the terminating NUL character.
 * In all other cases, it leaves *line unmodified.
 */
static pam_facility_t
parse_facility_name(char **line)
{
	char *b, *e;
	int i;

	for (b = *line; *b && is_lws(*b); ++b)
		/* nothing */ ;
	if (!*b) {
		*line = b;
		return ((pam_facility_t)-1);
	}
	for (e = b; *e && !is_lws(*e); ++e)
		/* nothing */ ;
	if (e == b)
		return ((pam_facility_t)-1);
	for (i = 0; i < PAM_NUM_FACILITIES; ++i)
		if (strlcmp(pam_facility_name[i], b, e - b) == 0)
			break;
	if (i == PAM_NUM_FACILITIES)
		return ((pam_facility_t)-1);
	*line = e;
	return (i);
}
Example #8
0
char *
openpam_readword(FILE *f, int *lineno, size_t *lenp)
{
	char *word;
	size_t size, len;
	int ch, comment, escape, quote;
	int serrno;

	errno = 0;

	/* skip initial whitespace */
	comment = 0;
	while ((ch = getc(f)) != EOF && ch != '\n') {
		if (ch == '#')
			comment = 1;
		if (!is_lws(ch) && !comment)
			break;
	}
	if (ch == EOF)
		return (NULL);
	ungetc(ch, f);
	if (ch == '\n')
		return (NULL);

	word = NULL;
	size = len = 0;
	escape = quote = 0;
	while ((ch = fgetc(f)) != EOF && (!is_ws(ch) || quote || escape)) {
		if (ch == '\\' && !escape && quote != '\'') {
			/* escape next character */
			escape = ch;
		} else if ((ch == '\'' || ch == '"') && !quote && !escape) {
			/* begin quote */
			quote = ch;
			/* edge case: empty quoted string */
			if (openpam_straddch(&word, &size, &len, 0) != 0)
				return (NULL);
		} else if (ch == quote && !escape) {
			/* end quote */
			quote = 0;
		} else if (ch == '\n' && escape && quote != '\'') {
			/* line continuation */
			escape = 0;
		} else {
			if (escape && quote && ch != '\\' && ch != quote &&
			    openpam_straddch(&word, &size, &len, '\\') != 0) {
				free(word);
				errno = ENOMEM;
				return (NULL);
			}
			if (openpam_straddch(&word, &size, &len, ch) != 0) {
				free(word);
				errno = ENOMEM;
				return (NULL);
			}
			escape = 0;
		}
		if (lineno != NULL && ch == '\n')
			++*lineno;
	}
	if (ch == EOF && ferror(f)) {
		serrno = errno;
		free(word);
		errno = serrno;
		return (NULL);
	}
	if (ch == EOF && (escape || quote)) {
		/* Missing escaped character or closing quote. */
		openpam_log(PAM_LOG_ERROR, "unexpected end of file");
		free(word);
		errno = EINVAL;
		return (NULL);
	}
	ungetc(ch, f);
	if (lenp != NULL)
		*lenp = len;
	return (word);
}
Example #9
0
Result ws::http_request_parser::consume(char c)
{
	switch(state_)
	{
		case METHOD_GET_1:
			return require_char(c, 'G', METHOD_GET_2);
			break;
		
		case METHOD_GET_2:
			return require_char(c, 'E', METHOD_GET_3);
			break;
		
		case METHOD_GET_3:
			return require_char(c, 'T', METHOD_GET_SP);
			break;
		
		case METHOD_GET_SP:
			return require_char(c, ' ', URI);
			break;
		
		case URI:
			if (c == ' ')
				state_ = HTTP_1;
			else if (!is_ctl(c))
				request.uri.push_back(c);
			else
				return BAD_REQUEST;
			return INDETERMINATE;
			break;
		
		case HTTP_1:
			return require_char(c, 'H', HTTP_2);
			break;
		
		case HTTP_2:
			return require_char(c, 'T', HTTP_3);
			break;
		
		case HTTP_3:
			return require_char(c, 'T', HTTP_4);
			break;
		
		case HTTP_4:
			return require_char(c, 'P', HTTP_SLASH);
			break;
		
		case HTTP_SLASH:
			return require_char(c, '/', HTTP_VERSION_MAJOR);
			break;
		
		case HTTP_VERSION_MAJOR:
			return require_char(c, '1', HTTP_VERSION_POINT);
			break;
		
		case HTTP_VERSION_POINT:
			return require_char(c, '.', HTTP_VERSION_MINOR);
			break;
		
		case HTTP_VERSION_MINOR:
			return require_char(c, '1', REQUEST_LINE_CR);
			break;
		
		case REQUEST_LINE_CR:
			return require_char(c, CR, REQUEST_LINE_LF);
			break;
		
		case REQUEST_LINE_LF:
			return require_char(c, LF, HEADER_START);
			break;
		
		case HEADER_START:
			if (c == CR)
			{
				state_ = FINAL_LF;
				return INDETERMINATE;
			}
			state_ = HEADER_NAME;
			return process_header_name_char(c);
			break;
		
		case HEADER_NAME:
			if (c == ':')
			{
				state_ = HEADER_VALUE_START;
				return INDETERMINATE;
			}
			return process_header_name_char(c);
			break;
		
		case HEADER_VALUE_START:
			if (is_lws(c))
				return INDETERMINATE;
			state_ = HEADER_VALUE;
			return process_header_value_char(c);
			break;
		
		case HEADER_VALUE:
			if (c == CR)
			{
				header_value_complete();
				state_ = HEADER_LF;
				return INDETERMINATE;
			}
			return process_header_value_char(c);
			break;
		
		case HEADER_LF:
			return require_char(c, LF, HEADER_START);
			break;
		
		case FINAL_LF:
			if (c == LF)
			{
				state_ = AFTER_FINAL_LF;
				return GOOD;
			}
			else
				return BAD_REQUEST;
			break;
		
		case AFTER_FINAL_LF:
			return BAD_REQUEST;
			break;
	}
	return BAD_REQUEST;
}