blob: 236f578725506065d6434e4e62e9f56b88014eef [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 Tarreau8c42b8a2020-06-04 19:27:34 +020018#include <haproxy/uri_auth.h>
willy tarreau9e138862006-05-14 23:06:28 +020019
Willy Tarreau708c4162019-10-09 10:19:16 +020020#include <types/stats.h>
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +010021#include <proto/log.h>
willy tarreau9e138862006-05-14 23:06:28 +020022
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 */
27struct uri_auth *stats_check_init_uri_auth(struct uri_auth **root)
28{
29 struct uri_auth *u;
30
31 if (!root || !*root) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +020032 if ((u = calloc(1, sizeof (*u))) == NULL)
willy tarreau9e138862006-05-14 23:06:28 +020033 goto out_u;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +010034
Willy Tarreauff011f22011-01-06 17:51:27 +010035 LIST_INIT(&u->http_req_rules);
Cyril Bonté474be412010-10-12 00:14:36 +020036 LIST_INIT(&u->admin_rules);
willy tarreau9e138862006-05-14 23:06:28 +020037 } 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
willy tarreau9e138862006-05-14 23:06:28 +020046 if (root && !*root)
47 *root = u;
48
49 return u;
50
willy tarreau9e138862006-05-14 23:06:28 +020051 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 */
62struct 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
Willy Tarreaua534fea2008-08-03 12:19:50 +020075 free(u->uri_prefix);
willy tarreau9e138862006-05-14 23:06:28 +020076 u->uri_prefix = uri_copy;
Willy Tarreaua534fea2008-08-03 12:19:50 +020077 u->uri_len = uri_len;
willy tarreau9e138862006-05-14 23:06:28 +020078 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 */
90struct 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
Willy Tarreaua534fea2008-08-03 12:19:50 +0200101 free(u->auth_realm);
willy tarreau9e138862006-05-14 23:06:28 +0200102 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/*
Willy Tarreau708c4162019-10-09 10:19:16 +0200112 * Returns a default uri_auth with STAT_SHNODE flag enabled and
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200113 * <node> set as the name if it is not empty.
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200114 * Uses the pointer provided if not NULL and not initialized.
115 */
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200116struct uri_auth *stats_set_node(struct uri_auth **root, char *name)
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200117{
118 struct uri_auth *u;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200119 char *node_copy = NULL;
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200120
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200121 if (name && *name) {
122 node_copy = strdup(name);
123 if (node_copy == NULL)
124 goto out_realm;
125 }
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200126
127 if ((u = stats_check_init_uri_auth(root)) == NULL)
128 goto out_u;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200129
Willy Tarreau708c4162019-10-09 10:19:16 +0200130 if (!stats_set_flag(root, STAT_SHNODE))
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200131 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/*
Willy Tarreau708c4162019-10-09 10:19:16 +0200147 * Returns a default uri_auth with STAT_SHDESC flag enabled and
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200148 * <description> set as the desc if it is not empty.
149 * Uses the pointer provided if not NULL and not initialized.
150 */
151struct 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 }
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200161
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200162 if ((u = stats_check_init_uri_auth(root)) == NULL)
163 goto out_u;
164
Willy Tarreau708c4162019-10-09 10:19:16 +0200165 if (!stats_set_flag(root, STAT_SHDESC))
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200166 goto out_u;
167
168 if (desc_copy) {
169 free(u->desc);
170 u->desc = desc_copy;
171 }
172
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200173 return u;
174
175 out_u:
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200176 free(desc_copy);
Willy Tarreau1d45b7c2009-08-16 10:29:18 +0200177 out_realm:
178 return NULL;
179}
180
181/*
Willy Tarreaubbd42122007-07-25 07:26:38 +0200182 * Returns a default uri_auth with the <refresh> refresh interval.
183 * Uses the pointer provided if not NULL and not initialized.
184 */
185struct 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/*
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +0200195 * Returns a default uri_auth with the <flag> set.
196 * Uses the pointer provided if not NULL and not initialized.
197 */
198struct 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/*
willy tarreau9e138862006-05-14 23:06:28 +0200208 * 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 */
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100212struct uri_auth *stats_add_auth(struct uri_auth **root, char *user)
willy tarreau9e138862006-05-14 23:06:28 +0200213{
214 struct uri_auth *u;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100215 struct auth_users *newuser;
216 char *pass;
willy tarreau9e138862006-05-14 23:06:28 +0200217
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100218 pass = strchr(user, ':');
219 if (pass)
220 *pass++ = '\0';
221 else
222 pass = "";
willy tarreau9e138862006-05-14 23:06:28 +0200223
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100224 if ((u = stats_check_init_uri_auth(root)) == NULL)
225 return NULL;
willy tarreau9e138862006-05-14 23:06:28 +0200226
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100227 if (!u->userlist)
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200228 u->userlist = calloc(1, sizeof(struct userlist));
willy tarreau9e138862006-05-14 23:06:28 +0200229
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100230 if (!u->userlist)
231 return NULL;
willy tarreau9e138862006-05-14 23:06:28 +0200232
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100233 if (!u->userlist->name)
234 u->userlist->name = strdup(".internal-stats-userlist");
willy tarreau9e138862006-05-14 23:06:28 +0200235
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100236 if (!u->userlist->name)
237 return NULL;
willy tarreau9e138862006-05-14 23:06:28 +0200238
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100239 for (newuser = u->userlist->users; newuser; newuser = newuser->next)
240 if (!strcmp(newuser->user, user)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100241 ha_warning("uri auth: ignoring duplicated user '%s'.\n",
242 user);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100243 return u;
244 }
245
Vincent Bernat02779b62016-04-03 13:48:43 +0200246 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100247 if (!newuser)
248 return NULL;
249
250 newuser->user = strdup(user);
Willy Tarreau0b291bd2013-01-24 02:26:43 +0100251 if (!newuser->user) {
252 free(newuser);
253 return NULL;
254 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100255
Willy Tarreau0b291bd2013-01-24 02:26:43 +0100256 newuser->pass = strdup(pass);
257 if (!newuser->pass) {
258 free(newuser->user);
259 free(newuser);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100260 return NULL;
Willy Tarreau0b291bd2013-01-24 02:26:43 +0100261 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100262
Willy Tarreau0b291bd2013-01-24 02:26:43 +0100263 newuser->flags |= AU_O_INSECURE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +0100264 newuser->next = u->userlist->users;
265 u->userlist->users = newuser;
266
267 return u;
willy tarreau9e138862006-05-14 23:06:28 +0200268}
269
willy tarreau1f431b52006-05-21 14:46:15 +0200270/*
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 */
275struct 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
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200295 if ((old_scope = calloc(1, sizeof(*old_scope))) == NULL)
willy tarreau1f431b52006-05-21 14:46:15 +0200296 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
Willy Tarreaubbd42122007-07-25 07:26:38 +0200312/*
313 * Local variables:
314 * c-indent-level: 8
315 * c-basic-offset: 8
316 * End:
317 */