Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2011 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include <stdlib.h>
24 : #include <errno.h>
25 : #include <string.h>
26 : #include <stdint.h>
27 :
28 : #include "sss_client/sss_cli.h"
29 : #include "sss_client/sudo/sss_sudo.h"
30 : #include "sss_client/sudo/sss_sudo_private.h"
31 :
32 : static int sss_sudo_parse_rule(const char *message,
33 : size_t message_len,
34 : size_t *_cursor,
35 : struct sss_sudo_rule *_rule);
36 :
37 : static int sss_sudo_parse_attr(const char *message,
38 : size_t message_len,
39 : size_t *_cursor,
40 : struct sss_sudo_attr *_attr);
41 :
42 : static int sss_sudo_parse_uint32(const char *message,
43 : size_t message_len,
44 : size_t *_cursor,
45 : uint32_t *_number);
46 :
47 : static int sss_sudo_parse_string(const char *message,
48 : size_t message_len,
49 : size_t *_cursor,
50 : char **_str);
51 :
52 0 : int sss_sudo_parse_response(const char *message,
53 : size_t message_len,
54 : char **_domainname,
55 : struct sss_sudo_result **_result,
56 : uint32_t *_error)
57 : {
58 0 : struct sss_sudo_result *result = NULL;
59 0 : char *domainname = NULL;
60 0 : size_t cursor = 0;
61 0 : int ret = EOK;
62 0 : int i = 0;
63 :
64 : /* error code */
65 0 : ret = sss_sudo_parse_uint32(message, message_len, &cursor, _error);
66 0 : if (ret != EOK || *_error != SSS_SUDO_ERROR_OK) {
67 0 : return ret;
68 : }
69 :
70 : /* domain name - deprecated
71 : * it won't be used, but we will read it anyway to ease parsing
72 : * TODO: when possible change the protocol */
73 0 : ret = sss_sudo_parse_string(message, message_len, &cursor, &domainname);
74 0 : if (ret != EOK) {
75 0 : return ret;
76 : }
77 :
78 0 : free(domainname);
79 0 : if (_domainname != NULL) {
80 0 : *_domainname = NULL;
81 : }
82 :
83 : /* result */
84 0 : result = malloc(sizeof(struct sss_sudo_result));
85 0 : if (result == NULL) {
86 0 : return ENOMEM;
87 : }
88 :
89 0 : memset(result, 0, sizeof(struct sss_sudo_result));
90 :
91 : /* rules_num */
92 0 : ret = sss_sudo_parse_uint32(message, message_len,
93 0 : &cursor, &result->num_rules);
94 0 : if (ret != EOK) {
95 0 : goto fail;
96 : }
97 :
98 : /* rules */
99 0 : result->rules = calloc(result->num_rules, sizeof(struct sss_sudo_rule));
100 0 : if (result->rules == NULL) {
101 0 : ret = ENOMEM;
102 0 : goto fail;
103 : }
104 :
105 0 : for (i = 0; i < result->num_rules; i++) {
106 0 : ret = sss_sudo_parse_rule(message, message_len,
107 0 : &cursor, &result->rules[i]);
108 0 : if (ret != EOK) {
109 0 : goto fail;
110 : }
111 : }
112 :
113 0 : *_result = result;
114 :
115 0 : return EOK;
116 :
117 : fail:
118 0 : sss_sudo_free_result(result);
119 0 : return ret;
120 : }
121 :
122 0 : int sss_sudo_parse_rule(const char *message,
123 : size_t message_len,
124 : size_t *_cursor,
125 : struct sss_sudo_rule *_rule)
126 : {
127 0 : int ret = EOK;
128 0 : int i = 0;
129 :
130 : /* attrs_num */
131 0 : ret = sss_sudo_parse_uint32(message, message_len,
132 0 : _cursor, &_rule->num_attrs);
133 0 : if (ret != EOK) {
134 0 : return ret;
135 : }
136 :
137 : /* attrs */
138 0 : _rule->attrs = calloc(_rule->num_attrs, sizeof(struct sss_sudo_attr));
139 0 : if (_rule->attrs == NULL) {
140 0 : return ENOMEM;
141 : }
142 :
143 0 : for (i = 0; i < _rule->num_attrs; i++) {
144 0 : ret = sss_sudo_parse_attr(message, message_len,
145 0 : _cursor, &_rule->attrs[i]);
146 0 : if (ret != EOK) {
147 0 : return ret;
148 : }
149 : }
150 :
151 0 : return EOK;
152 : }
153 :
154 0 : int sss_sudo_parse_attr(const char *message,
155 : size_t message_len,
156 : size_t *_cursor,
157 : struct sss_sudo_attr *_attr)
158 : {
159 0 : char *str = NULL;
160 0 : int ret = EOK;
161 0 : int i = 0;
162 :
163 : /* name */
164 0 : ret = sss_sudo_parse_string(message, message_len, _cursor, &str);
165 0 : if (ret != EOK) {
166 0 : return ret;
167 : }
168 0 : _attr->name = str;
169 :
170 : /* values_num */
171 0 : ret = sss_sudo_parse_uint32(message, message_len,
172 0 : _cursor, &_attr->num_values);
173 0 : if (ret != EOK) {
174 0 : return ret;
175 : }
176 :
177 : /* values */
178 0 : _attr->values = calloc(_attr->num_values, sizeof(const char*));
179 0 : if (_attr->values == NULL) {
180 0 : return ENOMEM;
181 : }
182 :
183 0 : for (i = 0; i < _attr->num_values; i++) {
184 0 : ret = sss_sudo_parse_string(message, message_len, _cursor, &str);
185 0 : if (ret != EOK) {
186 0 : return ret;
187 : }
188 0 : _attr->values[i] = str;
189 : }
190 :
191 0 : return EOK;
192 : }
193 :
194 0 : int sss_sudo_parse_uint32(const char *message,
195 : size_t message_len,
196 : size_t *_cursor,
197 : uint32_t *_number)
198 : {
199 0 : size_t start_pos = 0;
200 :
201 0 : if (_cursor == NULL) {
202 0 : return EINVAL;
203 : }
204 :
205 0 : start_pos = *_cursor;
206 :
207 0 : if (start_pos + sizeof(uint32_t) > message_len) {
208 0 : return EINVAL;
209 : }
210 :
211 : /* expanded SAFEALIGN_COPY_UINT32 macro from util.h */
212 0 : memcpy(_number, message + start_pos, sizeof(uint32_t));
213 0 : *_cursor = start_pos + sizeof(uint32_t);
214 :
215 0 : return EOK;
216 : }
217 :
218 0 : int sss_sudo_parse_string(const char *message,
219 : size_t message_len,
220 : size_t *_cursor,
221 : char **_str)
222 : {
223 0 : const char *current = NULL;
224 0 : char *str = NULL;
225 0 : size_t start_pos = 0;
226 0 : size_t len = 0;
227 0 : size_t maxlen = 0;
228 :
229 0 : if (_cursor == NULL) {
230 0 : return EINVAL;
231 : }
232 :
233 0 : start_pos = *_cursor;
234 0 : maxlen = message_len - start_pos;
235 :
236 0 : if (start_pos >= message_len ) {
237 0 : return EINVAL;
238 : }
239 :
240 0 : current = message + start_pos;
241 0 : len = strnlen(current, maxlen);
242 0 : if (len == maxlen) {
243 : /* the string exceeds message length */
244 0 : return EINVAL;
245 : }
246 :
247 0 : str = strndup(current, len);
248 0 : if (str == NULL) {
249 0 : return ENOMEM;
250 : }
251 :
252 : /* go after \0 */
253 0 : *_cursor = start_pos + len + 1;
254 0 : *_str = str;
255 :
256 0 : return EOK;
257 : }
|