blob: db7e6c68dab408ddc195fbc7453dc7a932fe49da [file] [log] [blame]
willy tarreau9e138862006-05-14 23:06:28 +02001/*
2 * URI-based user authentication using the HTTP basic method.
3 *
Willy Tarreaubbd42122007-07-25 07:26:38 +02004 * Copyright 2006-2007 Willy Tarreau <w@1wt.eu>
willy tarreau9e138862006-05-14 23:06:28 +02005 *
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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020015
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020016#include <haproxy/api.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020017#include <haproxy/base64.h>
Willy Tarreau36979d92020-06-05 17:27:29 +020018#include <haproxy/errors.h>
19#include <haproxy/list.h>
Willy Tarreau2eec9b52020-06-04 19:58:55 +020020#include <haproxy/stats-t.h>
Willy Tarreau8c42b8a2020-06-04 19:27:34 +020021#include <haproxy/uri_auth.h>
willy tarreau9e138862006-05-14 23:06:28 +020022
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 */
28struct uri_auth *stats_check_init_uri_auth(struct uri_auth **root)
29{
30 struct uri_auth *u;
31
32 if (!root || !*root) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +020033 if ((u = calloc(1, sizeof (*u))) == NULL)
willy tarreau9e138862006-05-14 23:06:28 +020034 goto out_u;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +010035
Willy Tarreauff011f22011-01-06 17:51:27 +010036 LIST_INIT(&u->http_req_rules);
Cyril Bonté474be412010-10-12 00:14:36 +020037 LIST_INIT(&u->admin_rules);
willy tarreau9e138862006-05-14 23:06:28 +020038 } 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
willy tarreau9e138862006-05-14 23:06:28 +020047 if (root && !*root)
48 *root = u;
49
50 return u;
51
willy tarreau9e138862006-05-14 23:06:28 +020052 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 */
63struct 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
Willy Tarreaua534fea2008-08-03 12:19:50 +020076 free(u->uri_prefix);
willy tarreau9e138862006-05-14 23:06:28 +020077 u->uri_prefix = uri_copy;
Willy Tarreaua534fea2008-08-03 12:19:50 +020078 u->uri_len = uri_len;
willy tarreau9e138862006-05-14 23:06:28 +020079 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 */
91struct 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
Willy Tarreaua534fea2008-08-03 12:19:50 +0200102 free(u->auth_realm);
willy tarreau9e138862006-05-14 23:06:28 +0200103 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/*
Willy Tarreau708c4162019-10-09 10:19:16 +0200113 * Returns a default uri_auth with STAT_SHNODE flag enabled and
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200114 * <node> set as the name if it is not empty.
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200115 * Uses the pointer provided if not NULL and not initialized.
116 */
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200117struct uri_auth *stats_set_node(struct uri_auth **root, char *name)
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200118{
119 struct uri_auth *u;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200120 char *node_copy = NULL;
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200121
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200122 if (name && *name) {
123 node_copy = strdup(name);
124 if (node_copy == NULL)
125 goto out_realm;
126 }
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200127
128 if ((u = stats_check_init_uri_auth(root)) == NULL)
129 goto out_u;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200130
Willy Tarreau708c4162019-10-09 10:19:16 +0200131 if (!stats_set_flag(root, STAT_SHNODE))
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200132 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/*
Willy Tarreau708c4162019-10-09 10:19:16 +0200148 * Returns a default uri_auth with STAT_SHDESC flag enabled and
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200149 * <description> set as the desc if it is not empty.
150 * Uses the pointer provided if not NULL and not initialized.
151 */
152struct 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 }
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200162
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200163 if ((u = stats_check_init_uri_auth(root)) == NULL)
164 goto out_u;
165
Willy Tarreau708c4162019-10-09 10:19:16 +0200166 if (!stats_set_flag(root, STAT_SHDESC))
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200167 goto out_u;
168
169 if (desc_copy) {
170 free(u->desc);
171 u->desc = desc_copy;
172 }
173
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200174 return u;
175
176 out_u:
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200177 free(desc_copy);
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200178 out_realm:
179 return NULL;
180}
181
182/*
Willy Tarreaubbd42122007-07-25 07:26:38 +0200183 * Returns a default uri_auth with the <refresh> refresh interval.
184 * Uses the pointer provided if not NULL and not initialized.
185 */
186struct 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/*
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +0200196 * Returns a default uri_auth with the <flag> set.
197 * Uses the pointer provided if not NULL and not initialized.
198 */
199struct 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/*
willy tarreau9e138862006-05-14 23:06:28 +0200209 * 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 */
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100213struct uri_auth *stats_add_auth(struct uri_auth **root, char *user)
willy tarreau9e138862006-05-14 23:06:28 +0200214{
215 struct uri_auth *u;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100216 struct auth_users *newuser;
217 char *pass;
willy tarreau9e138862006-05-14 23:06:28 +0200218
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100219 pass = strchr(user, ':');
220 if (pass)
221 *pass++ = '\0';
222 else
223 pass = "";
willy tarreau9e138862006-05-14 23:06:28 +0200224
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100225 if ((u = stats_check_init_uri_auth(root)) == NULL)
226 return NULL;
willy tarreau9e138862006-05-14 23:06:28 +0200227
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100228 if (!u->userlist)
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200229 u->userlist = calloc(1, sizeof(*u->userlist));
willy tarreau9e138862006-05-14 23:06:28 +0200230
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100231 if (!u->userlist)
232 return NULL;
willy tarreau9e138862006-05-14 23:06:28 +0200233
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100234 if (!u->userlist->name)
235 u->userlist->name = strdup(".internal-stats-userlist");
willy tarreau9e138862006-05-14 23:06:28 +0200236
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100237 if (!u->userlist->name)
238 return NULL;
willy tarreau9e138862006-05-14 23:06:28 +0200239
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100240 for (newuser = u->userlist->users; newuser; newuser = newuser->next)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100241 if (strcmp(newuser->user, user) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100242 ha_warning("uri auth: ignoring duplicated user '%s'.\n",
243 user);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100244 return u;
245 }
246
Vincent Bernat02779b62016-04-03 13:48:43 +0200247 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100248 if (!newuser)
249 return NULL;
250
251 newuser->user = strdup(user);
Willy Tarreau0b291bd2013-01-24 02:26:43 +0100252 if (!newuser->user) {
253 free(newuser);
254 return NULL;
255 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100256
Willy Tarreau0b291bd2013-01-24 02:26:43 +0100257 newuser->pass = strdup(pass);
258 if (!newuser->pass) {
259 free(newuser->user);
260 free(newuser);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100261 return NULL;
Willy Tarreau0b291bd2013-01-24 02:26:43 +0100262 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100263
Willy Tarreau0b291bd2013-01-24 02:26:43 +0100264 newuser->flags |= AU_O_INSECURE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100265 newuser->next = u->userlist->users;
266 u->userlist->users = newuser;
267
268 return u;
willy tarreau9e138862006-05-14 23:06:28 +0200269}
270
willy tarreau1f431b52006-05-21 14:46:15 +0200271/*
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 */
276struct 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)) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100287 if (strcmp(old_scope->px_id, scope) == 0)
willy tarreau1f431b52006-05-21 14:46:15 +0200288 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
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200296 if ((old_scope = calloc(1, sizeof(*old_scope))) == NULL)
willy tarreau1f431b52006-05-21 14:46:15 +0200297 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
Willy Tarreaubbd42122007-07-25 07:26:38 +0200313/*
314 * Local variables:
315 * c-indent-level: 8
316 * c-basic-offset: 8
317 * End:
318 */