Line data Source code
1 : /*
2 : SSSD
3 :
4 : Authors:
5 : Stephen Gallagher <sgallagh@redhat.com>
6 :
7 : Copyright (C) 2012 Red Hat
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "providers/ldap/sdap_range.h"
24 : #include "util/util.h"
25 : #include "util/strtonum.h"
26 :
27 : #define SDAP_RANGE_STRING "range="
28 :
29 12 : errno_t sdap_parse_range(TALLOC_CTX *mem_ctx,
30 : const char *attr_desc,
31 : char **base_attr,
32 : uint32_t *range_offset,
33 : bool disable_range_retrieval)
34 : {
35 : errno_t ret;
36 : TALLOC_CTX *tmp_ctx;
37 : char *endptr;
38 : char *end_range;
39 : char *base;
40 12 : size_t rangestringlen = sizeof(SDAP_RANGE_STRING) - 1;
41 :
42 12 : *range_offset = 0;
43 :
44 12 : tmp_ctx = talloc_new(NULL);
45 12 : if (!tmp_ctx) return ENOMEM;
46 :
47 : /* The base_attr is the portion before the semicolon (if it exists) */
48 12 : endptr = strchr(attr_desc, ';');
49 12 : if (endptr == NULL) {
50 : /* Not a ranged attribute. Just copy the attribute desc */
51 12 : *base_attr = talloc_strdup(mem_ctx, attr_desc);
52 12 : if (!*base_attr) {
53 0 : ret = ENOMEM;
54 : } else {
55 12 : ret = EOK;
56 : }
57 12 : DEBUG(SSSDBG_TRACE_INTERNAL,
58 : "No sub-attributes for [%s]\n", attr_desc);
59 12 : goto done;
60 : }
61 :
62 : /* This is a complex attribute. First get the base attribute name */
63 0 : base = talloc_strndup(tmp_ctx, attr_desc,
64 0 : endptr - attr_desc);
65 0 : if (!base) {
66 0 : ret = ENOMEM;
67 0 : goto done;
68 : }
69 0 : DEBUG(SSSDBG_TRACE_LIBS,
70 : "Base attribute of [%s] is [%s]\n",
71 : attr_desc, base);
72 :
73 : /* Next, determine if this is a ranged attribute */
74 0 : if (strncmp(endptr+1, SDAP_RANGE_STRING, rangestringlen) != 0) {
75 : /* This is some other sub-attribute. We'll just return the whole
76 : * thing in case it's dealt with elsewhere.
77 : */
78 0 : *base_attr = talloc_strdup(mem_ctx, attr_desc);
79 0 : if (!*base_attr) {
80 0 : ret = ENOMEM;
81 : } else {
82 0 : ret = EOK;
83 : }
84 0 : DEBUG(SSSDBG_TRACE_LIBS,
85 : "[%s] contains sub-attribute other than a range, returning whole\n",
86 : attr_desc);
87 0 : goto done;
88 0 : } else if (disable_range_retrieval) {
89 : /* This is range sub-attribute, but we want to ignore it.
90 : */
91 0 : *base_attr = talloc_strdup(mem_ctx, attr_desc);
92 0 : if (!*base_attr) {
93 0 : ret = ENOMEM;
94 : } else {
95 0 : ret = ECANCELED;
96 : }
97 0 : goto done;
98 : }
99 :
100 : /* Get the end of the range */
101 0 : end_range = strchr(endptr + rangestringlen +1, '-');
102 0 : if (!end_range) {
103 0 : ret = EINVAL;
104 0 : DEBUG(SSSDBG_MINOR_FAILURE,
105 : "Cannot find hyphen in [%s]\n",
106 : endptr + rangestringlen +1);
107 0 : goto done;
108 : }
109 0 : end_range++; /* advance past the hyphen */
110 :
111 0 : if (*end_range == '*') {
112 : /* this was the last iteration of range retrievals */
113 0 : *base_attr = talloc_steal(mem_ctx, base);
114 0 : *range_offset = 0;
115 0 : DEBUG(SSSDBG_TRACE_LIBS,
116 : "[%s] contained the last set of values for this attribute\n",
117 : attr_desc);
118 0 : ret = EOK;
119 0 : goto done;
120 : }
121 :
122 0 : *range_offset = strtouint32(end_range, &endptr, 10);
123 0 : if (*endptr != '\0') {
124 0 : *range_offset = 0;
125 0 : ret = errno;
126 0 : DEBUG(SSSDBG_MINOR_FAILURE,
127 : "[%s] did not parse as an unsigned integer: [%s]\n",
128 : end_range, strerror(ret));
129 0 : goto done;
130 : }
131 0 : (*range_offset)++;
132 :
133 0 : *base_attr = talloc_steal(mem_ctx, base);
134 0 : DEBUG(SSSDBG_TRACE_LIBS,
135 : "Parsed range values: [%s][%d]\n",
136 : base, *range_offset);
137 :
138 0 : ret = EAGAIN;
139 : done:
140 12 : talloc_free(tmp_ctx);
141 12 : return ret;
142 : }
|