ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher/*
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher SSSD
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher Authors:
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher Stephen Gallagher <sgallagh@redhat.com>
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher Copyright (C) 2012 Red Hat
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher This program is free software; you can redistribute it and/or modify
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher it under the terms of the GNU General Public License as published by
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher the Free Software Foundation; either version 3 of the License, or
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher (at your option) any later version.
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher This program is distributed in the hope that it will be useful,
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher but WITHOUT ANY WARRANTY; without even the implied warranty of
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher GNU General Public License for more details.
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher You should have received a copy of the GNU General Public License
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher along with this program. If not, see <http://www.gnu.org/licenses/>.
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher*/
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher#include "providers/ldap/sdap_range.h"
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher#include "util/util.h"
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher#include "util/strtonum.h"
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher#define SDAP_RANGE_STRING "range="
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallaghererrno_t sdap_parse_range(TALLOC_CTX *mem_ctx,
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher const char *attr_desc,
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher char **base_attr,
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik uint32_t *range_offset,
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik bool disable_range_retrieval)
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher{
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher errno_t ret;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher TALLOC_CTX *tmp_ctx;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher char *endptr;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher char *end_range;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher char *base;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher size_t rangestringlen = sizeof(SDAP_RANGE_STRING) - 1;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher *range_offset = 0;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher tmp_ctx = talloc_new(NULL);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (!tmp_ctx) return ENOMEM;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher /* The base_attr is the portion before the semicolon (if it exists) */
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher endptr = strchr(attr_desc, ';');
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (endptr == NULL) {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher /* Not a ranged attribute. Just copy the attribute desc */
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher *base_attr = talloc_strdup(mem_ctx, attr_desc);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (!*base_attr) {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher ret = ENOMEM;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher } else {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher ret = EOK;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher }
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "No sub-attributes for [%s]\n", attr_desc);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher goto done;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher }
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher /* This is a complex attribute. First get the base attribute name */
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher base = talloc_strndup(tmp_ctx, attr_desc,
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher endptr - attr_desc);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (!base) {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher ret = ENOMEM;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher goto done;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher }
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher DEBUG(SSSDBG_TRACE_LIBS,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Base attribute of [%s] is [%s]\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov attr_desc, base);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher /* Next, determine if this is a ranged attribute */
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (strncmp(endptr+1, SDAP_RANGE_STRING, rangestringlen) != 0) {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher /* This is some other sub-attribute. We'll just return the whole
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher * thing in case it's dealt with elsewhere.
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher */
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher *base_attr = talloc_strdup(mem_ctx, attr_desc);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (!*base_attr) {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher ret = ENOMEM;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher } else {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher ret = EOK;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher }
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher DEBUG(SSSDBG_TRACE_LIBS,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "[%s] contains sub-attribute other than a range, returning whole\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov attr_desc);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher goto done;
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik } else if (disable_range_retrieval) {
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik /* This is range sub-attribute, but we want to ignore it.
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik */
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik *base_attr = talloc_strdup(mem_ctx, attr_desc);
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik if (!*base_attr) {
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik ret = ENOMEM;
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik } else {
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik ret = ECANCELED;
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik }
6263578b03a52b3ec3a2e33e097554241780fc20Lukas Slebodnik goto done;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher }
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher /* Get the end of the range */
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher end_range = strchr(endptr + rangestringlen +1, '-');
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (!end_range) {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher ret = EINVAL;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher DEBUG(SSSDBG_MINOR_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Cannot find hyphen in [%s]\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov endptr + rangestringlen +1);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher goto done;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher }
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher end_range++; /* advance past the hyphen */
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (*end_range == '*') {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher /* this was the last iteration of range retrievals */
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher *base_attr = talloc_steal(mem_ctx, base);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher *range_offset = 0;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher DEBUG(SSSDBG_TRACE_LIBS,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "[%s] contained the last set of values for this attribute\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov attr_desc);
6270c10037cd0b5ea59567aaf423dcb1205e5683Jan Zeleny ret = EOK;
6270c10037cd0b5ea59567aaf423dcb1205e5683Jan Zeleny goto done;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher }
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher *range_offset = strtouint32(end_range, &endptr, 10);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (*endptr != '\0') {
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher *range_offset = 0;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher ret = errno;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher DEBUG(SSSDBG_MINOR_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "[%s] did not parse as an unsigned integer: [%s]\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov end_range, strerror(ret));
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher goto done;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher }
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher (*range_offset)++;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher *base_attr = talloc_steal(mem_ctx, base);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher DEBUG(SSSDBG_TRACE_LIBS,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Parsed range values: [%s][%d]\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov base, *range_offset);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher ret = EAGAIN;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagherdone:
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher talloc_free(tmp_ctx);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher return ret;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher}