1 /*
2  * URI-based user authentication using the HTTP basic method.
3  *
4  * Copyright 2006-2007 Willy Tarreau <w@1wt.eu>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  *
11  */
12 
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include <haproxy/api.h>
17 #include <haproxy/base64.h>
18 #include <haproxy/errors.h>
19 #include <haproxy/list.h>
20 #include <haproxy/stats-t.h>
21 #include <haproxy/uri_auth.h>
22 
23 
24 /*
25  * Initializes a basic uri_auth structure header and returns a pointer to it.
26  * Uses the pointer provided if not NULL and not initialized.
27  */
stats_check_init_uri_auth(struct uri_auth ** root)28 struct uri_auth *stats_check_init_uri_auth(struct uri_auth **root)
29 {
30 	struct uri_auth *u;
31 
32 	if (!root || !*root) {
33 		if ((u = calloc(1, sizeof (*u))) == NULL)
34 			goto out_u;
35 
36 		LIST_INIT(&u->http_req_rules);
37 		LIST_INIT(&u->admin_rules);
38 	} else
39 		u = *root;
40 
41 	if (!u->uri_prefix) {
42 		u->uri_len = strlen(STATS_DEFAULT_URI);
43 		if ((u->uri_prefix = strdup(STATS_DEFAULT_URI)) == NULL)
44 			goto out_uri;
45 	}
46 
47 	if (root && !*root)
48 		*root = u;
49 
50 	return u;
51 
52  out_uri:
53 	if (!root || !*root)
54 		free(u);
55  out_u:
56 	return NULL;
57 }
58 
59 /*
60  * Returns a default uri_auth with <uri> set as the uri_prefix.
61  * Uses the pointer provided if not NULL and not initialized.
62  */
stats_set_uri(struct uri_auth ** root,char * uri)63 struct uri_auth *stats_set_uri(struct uri_auth **root, char *uri)
64 {
65 	struct uri_auth *u;
66 	char *uri_copy;
67 	int uri_len;
68 
69 	uri_len  = strlen(uri);
70 	if ((uri_copy = strdup(uri)) == NULL)
71 		goto out_uri;
72 
73 	if ((u = stats_check_init_uri_auth(root)) == NULL)
74 		goto out_u;
75 
76 	free(u->uri_prefix);
77 	u->uri_prefix = uri_copy;
78 	u->uri_len = uri_len;
79 	return u;
80 
81  out_u:
82 	free(uri_copy);
83  out_uri:
84 	return NULL;
85 }
86 
87 /*
88  * Returns a default uri_auth with <realm> set as the realm.
89  * Uses the pointer provided if not NULL and not initialized.
90  */
stats_set_realm(struct uri_auth ** root,char * realm)91 struct uri_auth *stats_set_realm(struct uri_auth **root, char *realm)
92 {
93 	struct uri_auth *u;
94 	char *realm_copy;
95 
96 	if ((realm_copy = strdup(realm)) == NULL)
97 		goto out_realm;
98 
99 	if ((u = stats_check_init_uri_auth(root)) == NULL)
100 		goto out_u;
101 
102 	free(u->auth_realm);
103 	u->auth_realm = realm_copy;
104 	return u;
105 
106  out_u:
107 	free(realm_copy);
108  out_realm:
109 	return NULL;
110 }
111 
112 /*
113  * Returns a default uri_auth with STAT_SHNODE flag enabled and
114  * <node> set as the name if it is not empty.
115  * Uses the pointer provided if not NULL and not initialized.
116  */
stats_set_node(struct uri_auth ** root,char * name)117 struct uri_auth *stats_set_node(struct uri_auth **root, char *name)
118 {
119 	struct uri_auth *u;
120 	char *node_copy = NULL;
121 
122 	if (name && *name) {
123 		node_copy = strdup(name);
124 		if (node_copy == NULL)
125 			goto out_realm;
126 	}
127 
128 	if ((u = stats_check_init_uri_auth(root)) == NULL)
129 		goto out_u;
130 
131 	if (!stats_set_flag(root, STAT_SHNODE))
132 		goto out_u;
133 
134 	if (node_copy) {
135 		free(u->node);
136 		u->node = node_copy;
137 	}
138 
139 	return u;
140 
141  out_u:
142 	free(node_copy);
143  out_realm:
144 	return NULL;
145 }
146 
147 /*
148  * Returns a default uri_auth with STAT_SHDESC flag enabled and
149  * <description> set as the desc if it is not empty.
150  * Uses the pointer provided if not NULL and not initialized.
151  */
stats_set_desc(struct uri_auth ** root,char * desc)152 struct uri_auth *stats_set_desc(struct uri_auth **root, char *desc)
153 {
154 	struct uri_auth *u;
155 	char *desc_copy = NULL;
156 
157 	if (desc && *desc) {
158 		desc_copy = strdup(desc);
159 		if (desc_copy == NULL)
160 			goto out_realm;
161 	}
162 
163 	if ((u = stats_check_init_uri_auth(root)) == NULL)
164 		goto out_u;
165 
166 	if (!stats_set_flag(root, STAT_SHDESC))
167 		goto out_u;
168 
169 	if (desc_copy) {
170 		free(u->desc);
171 		u->desc = desc_copy;
172 	}
173 
174 	return u;
175 
176  out_u:
177 	free(desc_copy);
178  out_realm:
179 	return NULL;
180 }
181 
182 /*
183  * Returns a default uri_auth with the <refresh> refresh interval.
184  * Uses the pointer provided if not NULL and not initialized.
185  */
stats_set_refresh(struct uri_auth ** root,int interval)186 struct uri_auth *stats_set_refresh(struct uri_auth **root, int interval)
187 {
188 	struct uri_auth *u;
189 
190 	if ((u = stats_check_init_uri_auth(root)) != NULL)
191 		u->refresh = interval;
192 	return u;
193 }
194 
195 /*
196  * Returns a default uri_auth with the <flag> set.
197  * Uses the pointer provided if not NULL and not initialized.
198  */
stats_set_flag(struct uri_auth ** root,int flag)199 struct uri_auth *stats_set_flag(struct uri_auth **root, int flag)
200 {
201 	struct uri_auth *u;
202 
203 	if ((u = stats_check_init_uri_auth(root)) != NULL)
204 		u->flags |= flag;
205 	return u;
206 }
207 
208 /*
209  * Returns a default uri_auth with a <user:passwd> entry added to the list of
210  * authorized users. If a matching entry is found, no update will be performed.
211  * Uses the pointer provided if not NULL and not initialized.
212  */
stats_add_auth(struct uri_auth ** root,char * user)213 struct uri_auth *stats_add_auth(struct uri_auth **root, char *user)
214 {
215 	struct uri_auth *u;
216 	struct auth_users *newuser;
217 	char *pass;
218 
219 	pass = strchr(user, ':');
220 	if (pass)
221 		*pass++ = '\0';
222 	else
223 		pass = "";
224 
225 	if ((u = stats_check_init_uri_auth(root)) == NULL)
226 		return NULL;
227 
228 	if (!u->userlist)
229 		u->userlist = calloc(1, sizeof(struct userlist));
230 
231 	if (!u->userlist)
232 		return NULL;
233 
234 	if (!u->userlist->name)
235 		u->userlist->name = strdup(".internal-stats-userlist");
236 
237 	if (!u->userlist->name)
238 		return NULL;
239 
240 	for (newuser = u->userlist->users; newuser; newuser = newuser->next)
241 		if (!strcmp(newuser->user, user)) {
242 			ha_warning("uri auth: ignoring duplicated user '%s'.\n",
243 				   user);
244 			return u;
245 		}
246 
247 	newuser = calloc(1, sizeof(*newuser));
248 	if (!newuser)
249 		return NULL;
250 
251 	newuser->user = strdup(user);
252 	if (!newuser->user) {
253 		free(newuser);
254 		return NULL;
255 	}
256 
257 	newuser->pass = strdup(pass);
258 	if (!newuser->pass) {
259 		free(newuser->user);
260 		free(newuser);
261 		return NULL;
262 	}
263 
264 	newuser->flags |= AU_O_INSECURE;
265 	newuser->next = u->userlist->users;
266 	u->userlist->users = newuser;
267 
268 	return u;
269 }
270 
271 /*
272  * Returns a default uri_auth with a <scope> entry added to the list of
273  * allowed scopes. If a matching entry is found, no update will be performed.
274  * Uses the pointer provided if not NULL and not initialized.
275  */
stats_add_scope(struct uri_auth ** root,char * scope)276 struct uri_auth *stats_add_scope(struct uri_auth **root, char *scope)
277 {
278 	struct uri_auth *u;
279 	char *new_name;
280 	struct stat_scope *old_scope, **scope_list;
281 
282 	if ((u = stats_check_init_uri_auth(root)) == NULL)
283 		goto out;
284 
285 	scope_list = &u->scope;
286 	while ((old_scope = *scope_list)) {
287 		if (!strcmp(old_scope->px_id, scope))
288 			break;
289 		scope_list = &old_scope->next;
290 	}
291 
292 	if (!old_scope) {
293 		if ((new_name = strdup(scope)) == NULL)
294 			goto out_u;
295 
296 		if ((old_scope = calloc(1, sizeof(*old_scope))) == NULL)
297 			goto out_name;
298 
299 		old_scope->px_id = new_name;
300 		old_scope->px_len = strlen(new_name);
301 		*scope_list = old_scope;
302 	}
303 	return u;
304 
305  out_name:
306 	free(new_name);
307  out_u:
308 	free(u);
309  out:
310 	return NULL;
311 }
312 
313 /*
314  * Local variables:
315  *  c-indent-level: 8
316  *  c-basic-offset: 8
317  * End:
318  */
319