Commit a642cac5 authored by Philipp Schafft's avatar Philipp Schafft 🦁

Wow. Mega patch!

This patch *replaces* the authentication system completly.

What is new:
 - <authentication> in mount section is now a container object.
 - <authentication> in root and mount section may hold any number of <role>-Tags.
 - <role> tags:
   Those tags define a 'role' and it's ACL rules.
   A role is a instance of an authentication module (see below).
   <role> takes the following options. All but type are optional.
   - authentication related:
     - type: Type of the authentication module (values: anonymous, static, legacy-password, url or htpasswd;
             symbolic constants in auth.h)
     - name: Name for the role. For later matching. (values: any string; default: (none))
     - method: This rule is only active on the given list of HTTP methods.
               (list of enum values: methods as recognized by httpp/ (e.g: get,post); default: *)
   - ACL related:
     - allow-method: Allowed HTTP methods.
       (list of enum values: methods as recognized by httpp/ (e.g: get,post); default: get)
     - deny-method: Rejected HTTP methods.
       (list of enum values: methods as recognized by httpp/ (e.g: get,post); default: *)
     - allow-admin: Allowed admin commands. (list of enum values: admin command; default: buildm3u)
     - deny-admin: Rejected admin commands. (list of enum values: admin command; default: *)
     - allow-web: Allowed web pages. (values: empty or *; default: *)
     - deny-web: Rejected web pages. (values: empty or *; default: (empty))
     - connections-per-user: maximum number of simultaneous connections per role and username.
       This is only active on active sources.  (values: unlimited or number of connections; default: unlimited)
     - connection-duration: maximum time of a connection. This is only active on active sources.
       (values: unlimited or number of secounds; default: unlimited)
   <role> takes <option> child tags. <option> tags contain a name and a value option.
   Meaning of <option> tags is up to the authentication module.
 - <role>s are considered to build a stack. If a role returns with AUTH_NOMATCH the next one will be tried.
 - <role>s are tested in this order: mount specific, default mount specific, global, internal fallback.
   Internal fallback is set to allow web/ access via GET, POST and HEAD (only GET supported by this time)
   and rejects all other requests.
 - New authentication module: anonymous
   This module matches all requests. No options taken.
 - New authentication module: static
   This module matches with a static username and password.
   It takes two <option>s. One with name="username" and one with name="password" to set username and password.
   This replaces old style <*-username> and <*-password> tags.
 - New authentication module: legacy-password
   This module matches with a statich password.
   It takes one <option> with name="password" to set password.
   This replaces old ICE and ICY (shoutcast compat mode) authentication.
 - Parsing <authentication> in <mount> with a type set in a special way to allow 100% backward compatibility.
 - Parsing of <source-password>, <admin-password>, <admin-user>, <relay-password> and <relay-user> in global
   <authentication> for 100% backward compatibility.
 - <alias> is now proccessed very early. This enables them to be used for all kinds of requests.

To Do List & What does not yet work:
 - type="url" auth: mount_add and mount_remove.
   This should be replaced by an unique feature I would call '<event>'.
 - Admin commands manageauth and manageauth.xsl are disabled as they need more review:
   This code needs to be ported to support multiple <role>s per <mount>.
 - url authentication module can not yet return AUTH_NOMATCH.
   This needs to be reviewed and discussed on how to handle this case best way.
 - Default config files needs to be updated to reflect the changes.
   As this is quite some political act it should be done in dicussion with the whole team
   and permission of the release manager.
 - Docs need to be updated to reflect the changes.

How does it work:
 Code has been changed so that authentification is done early for all clients.
 This allows accessing the ACL data (client->acl) from nearly everywhere in the code.

 After accept() and initial client setup the request is parsed. In the next step
 all <alias>es are resolved. After this the client is passed for authentication.
 After authentication it is passed to the corresponding subsystem depending on kind of request.

 All authentication instances have a thread running for doing the authentication.
 This thread works on a queue of clients.

Hints for testers:
 - Test with default config.
 - Test with diffrent authentication modules in <mount>.
 - Test shoutcast compatibility mode.
 - Test with new style <authentication> and any amount of <role> (zero to quite some).
 - Test <alias> lookup on all kinds of objects.
 - Test source level credential login into the admin interface.
 - Test shoucast style meta data updates.
 - Test playlist generation.

Thank you for reading this long commit message. Have fun reading the full patch!

svn path=/icecast/trunk/icecast/; revision=19358
parent 637af17f
......@@ -9,7 +9,7 @@ bin_PROGRAMS = icecast
noinst_HEADERS = admin.h cfgfile.h logging.h sighandler.h connection.h \
global.h util.h slave.h source.h stats.h refbuf.h client.h \
compat.h fserve.h xslt.h yp.h event.h md5.h \
auth.h auth_htpasswd.h auth_url.h \
acl.h auth.h auth_htpasswd.h auth_url.h auth_anonymous.h auth_static.h \
format.h format_ogg.h format_mp3.h format_ebml.h \
format_vorbis.h format_theora.h format_flac.h format_speex.h format_midi.h \
format_kate.h format_skeleton.h format_opus.h
......@@ -17,7 +17,7 @@ icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c
util.c slave.c source.c stats.c refbuf.c client.c \
xslt.c fserve.c event.c admin.c md5.c \
format.c format_ogg.c format_mp3.c format_midi.c format_flac.c format_ebml.c \
auth.c auth_htpasswd.c format_kate.c format_skeleton.c format_opus.c
acl.c auth.c auth_htpasswd.c auth_anonymous.c auth_static.c format_kate.c format_skeleton.c format_opus.c
EXTRA_icecast_SOURCES = yp.c \
auth_url.c \
format_vorbis.c format_theora.c format_speex.c
......@@ -36,4 +36,3 @@ debug:
profile:
$(MAKE) all CFLAGS="@PROFILE@"
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2014, Philipp Schafft <lion@lion.leolix.org>
*/
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include "acl.h"
#include "admin.h"
#include <stdio.h>
#define MAX_ADMIN_COMMANDS 32
/* define internal structure */
struct acl_tag {
/* reference counter */
size_t refcount;
/* allowed methods */
acl_policy_t method[httpp_req_unknown+1];
/* admin/ interface */
struct {
int command;
acl_policy_t policy;
} admin_commands[MAX_ADMIN_COMMANDS];
size_t admin_commands_len;
acl_policy_t admin_command_policy;
/* web/ interface */
acl_policy_t web_policy;
/* mount specific functons */
time_t max_connection_duration;
size_t max_connections_per_user;
};
/* some string util functions */
static inline void __skip_spaces(const char **str) {
register const char * p;
for (p = *str; *p == ' '; p++);
*str = p;
}
int acl_set_ANY_str(acl_t * acl, acl_policy_t policy, const char * str, int (*callback)(acl_t *, acl_policy_t, const char *)) {
const char * end;
size_t len;
char buf[64];
int ret;
if (!acl || !str || !callback || (policy != ACL_POLICY_ALLOW && policy != ACL_POLICY_DENY))
return -1;
do {
__skip_spaces(&str);
end = strstr(str, ",");
if (end) {
len = end - str;
} else {
len = strlen(str);
}
if (len > (sizeof(buf) - 1))
return -1;
memcpy(buf, str, len);
buf[len] = 0;
ret = callback(acl, policy, buf);
if (ret)
return ret;
str += len + 1;
} while (end);
return 0;
}
/* basic functions to work with ACLs */
acl_t * acl_new(void) {
acl_t * ret = calloc(1, sizeof(*ret));
if (!ret)
return NULL;
ret->refcount = 1;
acl_set_method_str(ret, ACL_POLICY_DENY, "*");
acl_set_method_str(ret, ACL_POLICY_ALLOW, "get");
acl_set_admin_str(ret, ACL_POLICY_DENY, "*");
acl_set_admin_str(ret, ACL_POLICY_ALLOW, "buildm3u");
acl_set_web_policy(ret, ACL_POLICY_ALLOW);
acl_set_max_connection_duration(ret, -1);
acl_set_max_connections_per_user(ret, 0);
return ret;
}
acl_t * acl_new_from_xml_node(xmlNodePtr node) {
acl_t * ret;
char * tmp;
xmlAttrPtr prop;
if (!node)
return NULL;
ret = acl_new();
if (!ret)
return NULL;
prop = node->properties;
while (prop) {
tmp = (char*)xmlGetProp(node, prop->name);
if (tmp) {
if (strcmp((const char*)prop->name, "allow-method") == 0) {
acl_set_method_str(ret, ACL_POLICY_ALLOW, tmp);
} else if (strcmp((const char*)prop->name, "deny-method") == 0) {
acl_set_method_str(ret, ACL_POLICY_DENY, tmp);
} else if (strcmp((const char*)prop->name, "allow-admin") == 0) {
acl_set_admin_str(ret, ACL_POLICY_ALLOW, tmp);
} else if (strcmp((const char*)prop->name, "deny-admin") == 0) {
acl_set_admin_str(ret, ACL_POLICY_DENY, tmp);
} else if (strcmp((const char*)prop->name, "allow-web") == 0) {
if (strstr(tmp, "*"))
acl_set_web_policy(ret, ACL_POLICY_ALLOW);
} else if (strcmp((const char*)prop->name, "deny-web") == 0) {
if (strstr(tmp, "*"))
acl_set_web_policy(ret, ACL_POLICY_DENY);
} else if (strcmp((const char*)prop->name, "connections-per-user") == 0) {
if (strcmp(tmp, "*") == 0 || strcmp(tmp, "unlimited") == 0) {
acl_set_max_connections_per_user(ret, 0);
} else {
acl_set_max_connections_per_user(ret, atoi(tmp));
}
} else if (strcmp((const char*)prop->name, "connection-duration") == 0) {
if (strcmp(tmp, "*") == 0 || strcmp(tmp, "unlimited") == 0) {
acl_set_max_connection_duration(ret, 0);
} else {
acl_set_max_connection_duration(ret, atoi(tmp));
}
}
xmlFree(tmp);
}
prop = prop->next;
}
return ret;
}
void acl_addref(acl_t * acl) {
if (!acl)
return;
acl->refcount++;
}
void acl_release(acl_t * acl) {
if (!acl)
return;
acl->refcount--;
if (acl->refcount)
return;
free(acl);
}
/* HTTP Method specific functions */
int acl_set_method_str__callback(acl_t * acl, acl_policy_t policy, const char * str) {
httpp_request_type_e method;
size_t i;
if (strcmp(str, "*") == 0) {
for (i = 0; i < (sizeof(acl->method)/sizeof(*acl->method)); i++)
acl->method[i] = policy;
} else {
method = httpp_str_to_method(str);
if (method == httpp_req_unknown)
return -1;
acl->method[method] = policy;
}
return 0;
}
acl_policy_t acl_test_method(acl_t * acl, httpp_request_type_e method) {
if (!acl || method < httpp_req_none || method > httpp_req_unknown)
return ACL_POLICY_ERROR;
return acl->method[method];
}
/* admin/ interface specific functions */
int acl_set_admin_str__callbck(acl_t * acl, acl_policy_t policy, const char * str) {
size_t read_i, write_i;
int command = admin_get_command(str);
if (command == ADMIN_COMMAND_ERROR)
return -1;
if (command == ADMIN_COMMAND_ANY) {
acl->admin_command_policy = policy;
for (read_i = write_i = 0; read_i < acl->admin_commands_len; read_i++) {
if (acl->admin_commands[read_i].policy == policy)
continue;
acl->admin_commands[write_i] = acl->admin_commands[read_i];
write_i++; /* no need to check bounds here as this loop can only compress the array */
}
acl->admin_commands_len = write_i;
return 0;
}
if (acl->admin_commands_len == MAX_ADMIN_COMMANDS)
return -1;
acl->admin_commands[acl->admin_commands_len].command = command;
acl->admin_commands[acl->admin_commands_len].policy = policy;
acl->admin_commands_len++;
return 0;
}
acl_policy_t acl_test_admin(acl_t * acl, int command) {
size_t i;
if (!acl)
return ACL_POLICY_ERROR;
for (i = 0; i < acl->admin_commands_len; i++)
if (acl->admin_commands[i].command == command)
return acl->admin_commands[i].policy;
return acl->admin_command_policy;
}
/* web/ interface specific functions */
int acl_set_web_policy(acl_t * acl, acl_policy_t policy) {
if (!acl || (policy != ACL_POLICY_ALLOW && policy != ACL_POLICY_DENY))
return -1;
acl->web_policy = policy;
return 0;
}
acl_policy_t acl_test_web(acl_t * acl) {
if (!acl)
return ACL_POLICY_ERROR;
return acl->web_policy;
}
/* mount specific functons */
int acl_set_max_connection_duration(acl_t * acl, time_t duration) {
if (!acl)
return -1;
acl->max_connection_duration = duration;
return 0;
}
time_t acl_get_max_connection_duration(acl_t * acl) {
if (!acl)
return -1;
return acl->max_connection_duration;
}
int acl_set_max_connections_per_user(acl_t * acl, size_t limit) {
if (!acl)
return -1;
acl->max_connections_per_user = limit;
return 0;
}
ssize_t acl_get_max_connections_per_user(acl_t * acl) {
if (!acl)
return -1;
return acl->max_connections_per_user;
}
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2014, Philipp Schafft <lion@lion.leolix.org>
*/
#ifndef __ACL_H__
#define __ACL_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include "httpp/httpp.h"
typedef enum acl_policy_tag {
/* Error on function call */
ACL_POLICY_ERROR = -1,
/* Client is allowed to do operation, go ahead! */
ACL_POLICY_ALLOW = 0,
/* Client is not allowed to do so, send error! */
ACL_POLICY_DENY = 1
} acl_policy_t;
struct acl_tag;
typedef struct acl_tag acl_t;
/* basic functions to work with ACLs */
acl_t * acl_new(void);
acl_t * acl_new_from_xml_node(xmlNodePtr node);
void acl_addref(acl_t * acl);
void acl_release(acl_t * acl);
/* special functions */
int acl_set_ANY_str(acl_t * acl, acl_policy_t policy, const char * str, int (*callback)(acl_t *, acl_policy_t, const char *));
/* HTTP Method specific functions */
int acl_set_method_str__callback(acl_t * acl, acl_policy_t policy, const char * str);
#define acl_set_method_str(acl,policy,str) acl_set_ANY_str((acl), (policy), (str), acl_set_method_str__callback)
acl_policy_t acl_test_method(acl_t * acl, httpp_request_type_e method);
/* admin/ interface specific functions */
int acl_set_admin_str__callbck(acl_t * acl, acl_policy_t policy, const char * str);
#define acl_set_admin_str(acl,policy,str) acl_set_ANY_str((acl), (policy), (str), acl_set_admin_str__callbck)
acl_policy_t acl_test_admin(acl_t * acl, int command);
/* web/ interface specific functions */
int acl_set_web_policy(acl_t * acl, acl_policy_t policy);
acl_policy_t acl_test_web(acl_t * acl);
/* mount specific functons */
int acl_set_max_connection_duration(acl_t * acl, time_t duration);
time_t acl_get_max_connection_duration(acl_t * acl);
int acl_set_max_connections_per_user(acl_t * acl, size_t limit);
ssize_t acl_get_max_connections_per_user(acl_t * acl);
#endif
This diff is collapsed.
......@@ -20,6 +20,13 @@
#include "client.h"
#include "source.h"
/* types */
#define ADMINTYPE_ERROR (-1)
#define ADMINTYPE_GENERAL 1
#define ADMINTYPE_MOUNT 2
#define ADMINTYPE_HYBRID (ADMINTYPE_GENERAL|ADMINTYPE_MOUNT)
/* formats */
#define RAW 1
#define TRANSFORMED 2
#define PLAINTEXT 3
......@@ -35,5 +42,6 @@ void admin_send_response(xmlDocPtr doc, client_t *client,
void admin_add_listeners_to_mount(source_t *source, xmlNodePtr parent);
int admin_get_command(const char *command);
int admin_get_command_type(int command);
#endif /* __ADMIN_H__ */
This diff is collapsed.
......@@ -8,6 +8,7 @@
* oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details).
* Copyright 2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifndef __AUTH_H__
......@@ -27,6 +28,13 @@ struct auth_tag;
#include "client.h"
#include "thread/thread.h"
/* implemented */
#define AUTH_TYPE_ANONYMOUS "anonymous"
#define AUTH_TYPE_STATIC "static"
#define AUTH_TYPE_LEGACY_PASSWORD "legacy-password"
#define AUTH_TYPE_URL "url"
#define AUTH_TYPE_HTPASSWD "htpasswd"
typedef enum
{
/* XXX: ??? */
......@@ -35,6 +43,8 @@ typedef enum
AUTH_OK,
/* user authed failed */
AUTH_FAILED,
/* session got terminated */
AUTH_RELEASED,
/* XXX: ??? */
AUTH_FORBIDDEN,
/* No match for given username or other identifier found */
......@@ -47,9 +57,11 @@ typedef enum
typedef struct auth_client_tag
{
char *mount;
client_t *client;
void (*process)(struct auth_tag *auth, struct auth_client_tag *auth_user);
client_t *client;
auth_result (*process)(struct auth_tag *auth, struct auth_client_tag *auth_user);
void (*on_no_match)(client_t *client, void (*on_result)(client_t *client, void *userdata, auth_result result), void *userdata);
void (*on_result)(client_t *client, void *userdata, auth_result result);
void *userdata;
struct auth_client_tag *next;
} auth_client;
......@@ -58,18 +70,12 @@ typedef struct auth_tag
{
char *mount;
/* Authenticate using the given username and password */
auth_result (*authenticate)(auth_client *aclient);
auth_result (*release_listener)(auth_client *auth_user);
/* auth handler for authenicating a connecting source client */
void (*stream_auth)(auth_client *auth_user);
/* filters */
int method[httpp_req_unknown+1];
/* auth handler for source startup, no client passed as it may disappear */
void (*stream_start)(auth_client *auth_user);
/* auth handler for source exit, no client passed as it may disappear */
void (*stream_end)(auth_client *auth_user);
/* Authenticate using the given username and password */
auth_result (*authenticate_client)(auth_client *aclient);
auth_result (*release_client)(auth_client *auth_user);
/* auth state-specific free call */
void (*free)(struct auth_tag *self);
......@@ -80,8 +86,7 @@ typedef struct auth_tag
mutex_t lock;
int running;
int refcount;
int allow_duplicate_users;
size_t refcount;
thread_type *thread;
......@@ -91,30 +96,33 @@ typedef struct auth_tag
void *state;
char *type;
char *unique_tag;
/* acl to set on succsessful auth */
acl_t *acl;
/* role name for later matching, may be NULL if no role name was given in config */
char *role;
} auth_t;
void auth_add_listener (const char *mount, client_t *client);
int auth_release_listener (client_t *client);
typedef struct auth_stack_tag auth_stack_t;
void auth_initialise (void);
void auth_shutdown (void);
auth_t *auth_get_authenticator (xmlNodePtr node);
void auth_release (auth_t *authenticator);
void auth_addref (auth_t *authenticator);
/* call to trigger an event when a stream starts */
void auth_stream_start (struct _mount_proxy *mountinfo, const char *mount);
/* call to trigger an event when a stream ends */
void auth_stream_end (struct _mount_proxy *mountinfo, const char *mount);
int auth_release_client(client_t *client);
/* call to trigger an event to authenticate a source client */
int auth_stream_authenticate (client_t *client, const char *mount, struct _mount_proxy *mountinfo);
void auth_stack_add_client(auth_stack_t *stack, client_t *client, void (*on_result)(client_t *client, void *userdata, auth_result result), void *userdata);
/* called from auth thread, after the client has successfully authenticated
* and requires adding to source or fserve. */
int auth_postprocess_listener (auth_client *auth_user);
void auth_stack_release(auth_stack_t *stack);
void auth_stack_addref(auth_stack_t *stack);
int auth_stack_next(auth_stack_t **stack); /* returns -1 on error, 0 on success, +1 if no next element is present */
int auth_stack_push(auth_stack_t **stack, auth_t *auth);
int auth_stack_append(auth_stack_t *stack, auth_stack_t *tail);
auth_t *auth_stack_get(auth_stack_t *stack);
acl_t *auth_stack_get_anonymous_acl(auth_stack_t *stack);
#endif
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
/**
* Client authentication functions
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "auth.h"
#include "client.h"
#include "logging.h"
#define CATMODULE "auth_anonymous"
static auth_result anonymous_auth (auth_client *auth_user) {
return AUTH_OK;
}
int auth_get_anonymous_auth (auth_t *authenticator, config_options_t *options) {
authenticator->authenticate_client = anonymous_auth;
return 0;
}
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifndef __AUTH_ANONYMOUS_H__
#define __AUTH_ANONYMOUS_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
int auth_get_anonymous_auth (auth_t *auth, config_options_t *options);
#endif
......@@ -8,6 +8,7 @@
* oddsock <oddsock@xiph.org>,
* Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details).
* Copyright 2012-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
/**
......@@ -184,13 +185,12 @@ static auth_result htpasswd_auth (auth_client *auth_user)
htpasswd_user entry;
void *result;
if (client->username == NULL || client->password == NULL)
return AUTH_FAILED;
if (!client->username || !client->password)
return AUTH_NOMATCH;
if (htpasswd->filename == NULL)
{
if (!htpasswd->filename) {
ICECAST_LOG_ERROR("No filename given in options for authenticator.");
return AUTH_FAILED;
return AUTH_NOMATCH;
}
htpasswd_recheckfile (htpasswd);
......@@ -214,15 +214,14 @@ static auth_result htpasswd_auth (auth_client *auth_user)
}
ICECAST_LOG_DEBUG("no such username: %s", client->username);
thread_rwlock_unlock (&htpasswd->file_rwlock);
return AUTH_FAILED;
return AUTH_NOMATCH;
}
int auth_get_htpasswd_auth (auth_t *authenticator, config_options_t *options)
{
htpasswd_auth_state *state;
authenticator->authenticate = htpasswd_auth;
authenticator->authenticate_client = htpasswd_auth;
authenticator->free = htpasswd_clear;
authenticator->adduser = htpasswd_adduser;
authenticator->deleteuser = htpasswd_deleteuser;
......@@ -408,4 +407,3 @@ static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode)
return AUTH_OK;
}
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
/**
* Client authentication functions
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "auth.h"
#include "client.h"
#include "logging.h"
#define CATMODULE "auth_static"
typedef struct auth_static {
char *username;
char *password;
} auth_static_t;
static auth_result static_auth (auth_client *auth_user) {
client_t *client = auth_user->client;
auth_t *auth = client->auth;
auth_static_t *auth_info = auth->state;
if (auth_info->username) {
if (!client->username)
return AUTH_NOMATCH;
if (strcmp(auth_info->username, client->username) != 0)
return AUTH_NOMATCH;
}
if (!client->password)
return AUTH_NOMATCH;
if (strcmp(auth_info->password, client->password) == 0)
return AUTH_OK;
return AUTH_FAILED;
}
static void clear_auth (auth_t *auth) {
auth_static_t *auth_info = auth->state;
if (auth_info->username) free(auth_info->username);
if (auth_info->password) free(auth_info->password);
free(auth_info);
auth->state = NULL;
}
int auth_get_static_auth (auth_t *authenticator, config_options_t *options) {
auth_static_t *auth_info;
int need_user;
if (strcmp(authenticator->type, AUTH_TYPE_STATIC) == 0) {
need_user = 1;
} else if (strcmp(authenticator->type, AUTH_TYPE_LEGACY_PASSWORD) == 0) {
need_user = 0;
} else {
ICECAST_LOG_ERROR("Type is not known.");
return -1;
}
auth_info = calloc(1, sizeof(auth_static_t));
if (!auth_info)
return -1;
authenticator->authenticate_client = static_auth;
authenticator->free = clear_auth;
authenticator->state = auth_info;
while (options) {
if (strcmp(options->name, "username") == 0) {
if (auth_info->username) free(auth_info->username);
auth_info->username = strdup(options->value);
} else if (strcmp(options->name, "password") == 0) {
if (auth_info->password) free(auth_info->password);
auth_info->password = strdup(options->value);
} else {
ICECAST_LOG_ERROR("Unknown option: %s", options->name);
}
options = options->next;
}
if (need_user && !auth_info->username) {
ICECAST_LOG_ERROR("No Username given but needed.");
clear_auth(authenticator);
return -1;
} else if (!auth_info->password) {
ICECAST_LOG_ERROR("No password given but needed.");
clear_auth(authenticator);
return -1;
}
return 0;
}
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifndef __AUTH_STATIC_H__
#define __AUTH_STATIC_H__