/** Parses the buffer to extract the attribute-value pairs
 *
 * @param rh a handle to parsed configuration.
 * @param buffer the buffer to be parsed.
 * @param first_pair an allocated array of values.
 * @return 0 on successful parse of attribute-value pair, or -1 on syntax (or other) error detected.
 */
int rc_avpair_parse (rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
{
	int             mode;
	char            attrstr[AUTH_ID_LEN];
	char            valstr[AUTH_STRING_LEN + 1], *p;
	DICT_ATTR      *attr = NULL;
	DICT_VALUE     *dval;
	VALUE_PAIR     *pair;
	VALUE_PAIR     *link;
	struct tm      *tm;
	time_t          timeval;

	mode = PARSE_MODE_NAME;
	while (*buffer != '\n' && *buffer != '\0')
	{
		if (*buffer == ' ' || *buffer == '\t')
		{
			buffer++;
			continue;
		}

		switch (mode)
		{
		    case PARSE_MODE_NAME:		/* Attribute Name */
			rc_fieldcpy (attrstr, &buffer, " \t\n=,", sizeof(attrstr));
			if ((attr =
				rc_dict_findattr (rh, attrstr)) == NULL)
			{
				rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute");
				if (*first_pair) {
					rc_avpair_free(*first_pair);
					*first_pair = NULL;
				}
				return -1;
			}
			mode = PARSE_MODE_EQUAL;
			break;

		    case PARSE_MODE_EQUAL:		/* Equal sign */
			if (*buffer == '=')
			{
				mode = PARSE_MODE_VALUE;
				buffer++;
			}
			else
			{
				rc_log(LOG_ERR, "rc_avpair_parse: missing or misplaced equal sign");
				if (*first_pair) {
					rc_avpair_free(*first_pair);
					*first_pair = NULL;
				}
				return -1;
			}
			break;

		    case PARSE_MODE_VALUE:		/* Value */
			rc_fieldcpy (valstr, &buffer, " \t\n,", sizeof(valstr));

			if ((pair = malloc (sizeof (VALUE_PAIR))) == NULL)
			{
				rc_log(LOG_CRIT, "rc_avpair_parse: out of memory");
				if (*first_pair) {
					rc_avpair_free(*first_pair);
					*first_pair = NULL;
				}
				return -1;
			}
			strcpy (pair->name, attr->name);
			pair->attribute = attr->value;
			pair->type = attr->type;

			switch (pair->type)
			{

			    case PW_TYPE_STRING:
				strcpy (pair->strvalue, valstr);
				pair->lvalue = (uint32_t)strlen(valstr);
				break;

			    case PW_TYPE_INTEGER:
				if (isdigit (*valstr))
				{
					pair->lvalue = atoi (valstr);
				}
				else
				{
					if ((dval = rc_dict_findval (rh, valstr))
							== NULL)
					{
						rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute value: %s", valstr);
						if (*first_pair) {
							rc_avpair_free(*first_pair);
							*first_pair = NULL;
						}
						free (pair);
						return -1;
					}
					else
					{
						pair->lvalue = dval->value;
					}
				}
				break;

			    case PW_TYPE_IPADDR:
			    	if (inet_pton(AF_INET, valstr, &pair->lvalue) == 0) {
			    		rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv4 address %s", valstr);
			    		free(pair);
			    		return -1;
			    	}

                                pair->lvalue = ntohl(pair->lvalue);
				break;

			    case PW_TYPE_IPV6ADDR:
			    	if (inet_pton(AF_INET6, valstr, pair->strvalue) == 0) {
			    		rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 address %s", valstr);
			    		free(pair);
			    		return -1;
			    	}
				pair->lvalue = 16;
				break;

			    case PW_TYPE_IPV6PREFIX:
			    	p = strchr(valstr, '/');
			    	if (p == NULL) {
			    		rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
			    		free(pair);
			    		return -1;
			    	}
			    	*p = 0;
			    	p++;
			    	pair->strvalue[0] = 0;
			    	pair->strvalue[1] = atoi(p);

			    	if (inet_pton(AF_INET6, valstr, pair->strvalue+2) == 0) {
			    		rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
			    		free(pair);
			    		return -1;
			    	}
				pair->lvalue = 2+16;
				break;

			    case PW_TYPE_DATE:
				timeval = time (0);
				tm = localtime (&timeval);
				tm->tm_hour = 0;
				tm->tm_min = 0;
				tm->tm_sec = 0;
				rc_str2tm (valstr, tm);
#ifdef TIMELOCAL
				pair->lvalue = (uint32_t) timelocal (tm);
#else	/* TIMELOCAL */
				pair->lvalue = (uint32_t) mktime (tm);
#endif	/* TIMELOCAL */
				break;

			    default:
				rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute type %d", pair->type);
				if (*first_pair) {
					rc_avpair_free(*first_pair);
					*first_pair = NULL;
				}
				free (pair);
				return -1;
			}

			/* XXX: Fix up Digest-Attributes */
			switch (pair->attribute) {
			case PW_DIGEST_REALM:
			case PW_DIGEST_NONCE:
			case PW_DIGEST_METHOD:
			case PW_DIGEST_URI:
			case PW_DIGEST_QOP:
			case PW_DIGEST_ALGORITHM:
			case PW_DIGEST_BODY_DIGEST:
			case PW_DIGEST_CNONCE:
			case PW_DIGEST_NONCE_COUNT:
			case PW_DIGEST_USER_NAME:
				/* overlapping! */
				if (pair->lvalue > AUTH_STRING_LEN - 2)
					pair->lvalue = AUTH_STRING_LEN - 2;
				memmove(&pair->strvalue[2], &pair->strvalue[0], pair->lvalue);
				pair->strvalue[0] = pair->attribute - PW_DIGEST_REALM + 1;
				pair->lvalue += 2;
				pair->strvalue[1] = pair->lvalue;
				pair->strvalue[pair->lvalue] = '\0';
				pair->attribute = PW_DIGEST_ATTRIBUTES;
			}

			pair->next = NULL;

			if (*first_pair == NULL)
			{
				*first_pair = pair;
			}
			else
			{
				link = *first_pair;
				while (link->next != NULL)
				{
					link = link->next;
				}
				link->next = pair;
			}

			mode = PARSE_MODE_NAME;
			break;

		    default:
			mode = PARSE_MODE_NAME;
			break;
		}
	}
	return 0;
}
示例#2
0
int rc_avpair_parse (char *buffer, VALUE_PAIR **first_pair)
{
	int             mode;
	char            attrstr[AUTH_ID_LEN];
	char            valstr[AUTH_ID_LEN];
	DICT_ATTR      *attr = NULL;
	DICT_VALUE     *dval;
	VALUE_PAIR     *pair;
	VALUE_PAIR     *link;
	struct tm      *tm;
	time_t          timeval;

	mode = PARSE_MODE_NAME;
	while (*buffer != '\n' && *buffer != '\0')
	{
		if (*buffer == ' ' || *buffer == '\t')
		{
			buffer++;
			continue;
		}

		switch (mode)
		{
		    case PARSE_MODE_NAME:		/* Attribute Name */
			rc_fieldcpy (attrstr, &buffer);
			if ((attr =
				rc_dict_findattr (attrstr)) == (DICT_ATTR *) NULL)
			{
				error("rc_avpair_parse: unknown attribute");
				if (*first_pair) {
					rc_avpair_free(*first_pair);
					*first_pair = (VALUE_PAIR *) NULL;
				}
				return (-1);
			}
			mode = PARSE_MODE_EQUAL;
			break;

		    case PARSE_MODE_EQUAL:		/* Equal sign */
			if (*buffer == '=')
			{
				mode = PARSE_MODE_VALUE;
				buffer++;
			}
			else
			{
				error("rc_avpair_parse: missing or misplaced equal sign");
				if (*first_pair) {
					rc_avpair_free(*first_pair);
					*first_pair = (VALUE_PAIR *) NULL;
				}
				return (-1);
			}
			break;

		    case PARSE_MODE_VALUE:		/* Value */
			rc_fieldcpy (valstr, &buffer);

			if ((pair =
				(VALUE_PAIR *) malloc (sizeof (VALUE_PAIR)))
							== (VALUE_PAIR *) NULL)
			{
				novm("rc_avpair_parse");
				if (*first_pair) {
					rc_avpair_free(*first_pair);
					*first_pair = (VALUE_PAIR *) NULL;
				}
				return (-1);
			}
			strcpy (pair->name, attr->name);
			pair->attribute = attr->value;
			pair->type = attr->type;
			pair->vendorcode = attr->vendorcode;

			switch (pair->type)
			{

			    case PW_TYPE_STRING:
				strcpy ((char *)pair->strvalue, valstr);
				pair->lvalue = strlen(valstr);
				break;

			    case PW_TYPE_INTEGER:
				if (isdigit (*valstr))
				{
					pair->lvalue = atoi (valstr);
				}
				else
				{
					if ((dval = rc_dict_findval (valstr))
							== (DICT_VALUE *) NULL)
					{
						error("rc_avpair_parse: unknown attribute value: %s", valstr);
						if (*first_pair) {
							rc_avpair_free(*first_pair);
							*first_pair = (VALUE_PAIR *) NULL;
						}
						free (pair);
						return (-1);
					}
					else
					{
						pair->lvalue = dval->value;
					}
				}
				break;

			    case PW_TYPE_IPADDR:
				pair->lvalue = rc_get_ipaddr(valstr);
				break;

			    case PW_TYPE_DATE:
				timeval = time (0);
				tm = localtime (&timeval);
				tm->tm_hour = 0;
				tm->tm_min = 0;
				tm->tm_sec = 0;
				rc_str2tm (valstr, tm);
#ifdef TIMELOCAL
				pair->lvalue = (UINT4) timelocal (tm);
#else	/* TIMELOCAL */
				pair->lvalue = (UINT4) mktime (tm);
#endif	/* TIMELOCAL */
				break;

			    default:
				error("rc_avpair_parse: unknown attribute type %d", pair->type);
				if (*first_pair) {
					rc_avpair_free(*first_pair);
					*first_pair = (VALUE_PAIR *) NULL;
				}
				free (pair);
				return (-1);
			}
			pair->next = (VALUE_PAIR *) NULL;

			if (*first_pair == (VALUE_PAIR *) NULL)
			{
				*first_pair = pair;
			}
			else
			{
				link = *first_pair;
				while (link->next != (VALUE_PAIR *) NULL)
				{
					link = link->next;
				}
				link->next = pair;
			}

			mode = PARSE_MODE_NAME;
			break;

		    default:
			mode = PARSE_MODE_NAME;
			break;
		}
	}
	return (0);
}