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