/*
 * URI-based user authentication using the HTTP basic method.
 *
 * Copyright 2006 Willy Tarreau <willy@w.ods.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 */

#include <stdlib.h>
#include <string.h>
#include <include/uri_auth.h>
#include <include/base64.h>


/*
 * Initializes a basic uri_auth structure header and returns a pointer to it.
 * Uses the pointer provided if not NULL and not initialized.
 */
struct uri_auth *stats_check_init_uri_auth(struct uri_auth **root)
{
	struct uri_auth *u;

	if (!root || !*root) {
		if ((u = (struct uri_auth *)calloc(1, sizeof (*u))) == NULL)
			goto out_u;
	} else
		u = *root;

	if (!u->uri_prefix) {
		u->uri_len = strlen(STATS_DEFAULT_URI);
		if ((u->uri_prefix = strdup(STATS_DEFAULT_URI)) == NULL)
			goto out_uri;
	}

	if (!u->auth_realm)
		if ((u->auth_realm = strdup(STATS_DEFAULT_REALM)) == NULL)
			goto out_realm;

	if (root && !*root)
		*root = u;

	return u;

 out_realm:
	free(u->uri_prefix);
 out_uri:
	if (!root || !*root)
		free(u);
 out_u:
	return NULL;
}

/*
 * Returns a default uri_auth with <uri> set as the uri_prefix.
 * Uses the pointer provided if not NULL and not initialized.
 */
struct uri_auth *stats_set_uri(struct uri_auth **root, char *uri)
{
	struct uri_auth *u;
	char *uri_copy;
	int uri_len;

	uri_len  = strlen(uri);
	if ((uri_copy = strdup(uri)) == NULL)
		goto out_uri;
	
	if ((u = stats_check_init_uri_auth(root)) == NULL)
		goto out_u;
	
	if (u->uri_prefix)
		free(u->uri_prefix);

	u->uri_len = uri_len;
	u->uri_prefix = uri_copy;
	return u;

 out_u:
	free(uri_copy);
 out_uri:
	return NULL;
}

/*
 * Returns a default uri_auth with <realm> set as the realm.
 * Uses the pointer provided if not NULL and not initialized.
 */
struct uri_auth *stats_set_realm(struct uri_auth **root, char *realm)
{
	struct uri_auth *u;
	char *realm_copy;

	if ((realm_copy = strdup(realm)) == NULL)
		goto out_realm;
	
	if ((u = stats_check_init_uri_auth(root)) == NULL)
		goto out_u;
	
	if (u->auth_realm)
		free(u->auth_realm);

	u->auth_realm = realm_copy;
	return u;

 out_u:
	free(realm_copy);
 out_realm:
	return NULL;
}

/*
 * Returns a default uri_auth with a <user:passwd> entry added to the list of
 * authorized users. If a matching entry is found, no update will be performed.
 * Uses the pointer provided if not NULL and not initialized.
 */
struct uri_auth *stats_add_auth(struct uri_auth **root, char *auth)
{
	struct uri_auth *u;
	char *auth_base64;
	int alen, blen;
	struct user_auth *users, **ulist;

	alen = strlen(auth);
	blen = ((alen + 2) / 3) * 4;

	if ((auth_base64 = (char *)calloc(1, blen + 1)) == NULL)
		goto out_ubase64;

	/* convert user:passwd to base64. It should return exactly blen */
	if (a2base64(auth, alen, auth_base64, blen + 1) != blen)
		goto out_base64;

	if ((u = stats_check_init_uri_auth(root)) == NULL)
		goto out_base64;

	ulist = &u->users;
	while ((users = *ulist)) {
		if (!strcmp(users->user_pwd, auth_base64))
			break;
		ulist = &users->next;
	}

	if (!users) {
		if ((users = (struct user_auth *)calloc(1, sizeof(*users))) == NULL)
			goto out_u;
		*ulist = users;
		users->user_pwd = auth_base64;
		users->user_len = blen;
	}
	return u;

 out_u:
	free(u);
 out_base64:
	free(auth_base64);
 out_ubase64:
	return NULL;
}

/*
 * Returns a default uri_auth with a <scope> entry added to the list of
 * allowed scopes. If a matching entry is found, no update will be performed.
 * Uses the pointer provided if not NULL and not initialized.
 */
struct uri_auth *stats_add_scope(struct uri_auth **root, char *scope)
{
	struct uri_auth *u;
	char *new_name;
	struct stat_scope *old_scope, **scope_list;

	if ((u = stats_check_init_uri_auth(root)) == NULL)
		goto out;

	scope_list = &u->scope;
	while ((old_scope = *scope_list)) {
		if (!strcmp(old_scope->px_id, scope))
			break;
		scope_list = &old_scope->next;
	}

	if (!old_scope) {
		if ((new_name = strdup(scope)) == NULL)
			goto out_u;

		if ((old_scope = (struct stat_scope *)calloc(1, sizeof(*old_scope))) == NULL)
			goto out_name;

		old_scope->px_id = new_name;
		old_scope->px_len = strlen(new_name);
		*scope_list = old_scope;
	}
	return u;

 out_name:
	free(new_name);
 out_u:
	free(u);
 out:
	return NULL;
}

