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