[xiph-commits] r9583 - icecast/branches/kh/icecast/src
karl at svn.xiph.org
karl at svn.xiph.org
Mon Jul 18 07:27:43 PDT 2005
Author: karl
Date: 2005-07-18 07:27:39 -0700 (Mon, 18 Jul 2005)
New Revision: 9583
Modified:
icecast/branches/kh/icecast/src/auth.c
icecast/branches/kh/icecast/src/auth_htpasswd.c
icecast/branches/kh/icecast/src/auth_url.c
Log:
auth update. make htpasswd use an in-memory avl tree with checks on the
file mtime to identify changes made externally. Add useragent field to
auth url.
Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c 2005-07-18 00:36:00 UTC (rev 9582)
+++ icecast/branches/kh/icecast/src/auth.c 2005-07-18 14:27:39 UTC (rev 9583)
@@ -63,14 +63,14 @@
{
WARN1("Base64 decode of Authorization header \"%s\" failed",
header+6);
- return;
+ break;
}
tmp = strchr(userpass, ':');
if (tmp == NULL)
{
free (userpass);
- return;
+ break;
}
*tmp = 0;
@@ -401,7 +401,7 @@
*/
int release_client (client_t *client)
{
- if (client->auth && client->auth->release_client)
+ if (client->auth)
{
auth_client *auth_user = calloc (1, sizeof (auth_client));
if (auth_user == NULL)
Modified: icecast/branches/kh/icecast/src/auth_htpasswd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_htpasswd.c 2005-07-18 00:36:00 UTC (rev 9582)
+++ icecast/branches/kh/icecast/src/auth_htpasswd.c 2005-07-18 14:27:39 UTC (rev 9583)
@@ -42,15 +42,26 @@
static auth_result htpasswd_adduser (auth_t *auth, const char *username, const char *password);
static auth_result htpasswd_deleteuser(auth_t *auth, const char *username);
static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode);
+static int _free_user (void *key);
+typedef struct
+{
+ char *name;
+ char *pass;
+} htpasswd_user;
+
typedef struct {
char *filename;
rwlock_t file_rwlock;
+ avl_tree *users;
+ time_t mtime;
} htpasswd_auth_state;
static void htpasswd_clear(auth_t *self) {
htpasswd_auth_state *state = self->state;
free(state->filename);
+ if (state->users)
+ avl_tree_free (state->users, _free_user);
thread_rwlock_destroy(&state->file_rwlock);
free(state);
}
@@ -86,61 +97,127 @@
#define MAX_LINE_LEN 512
-/* Not efficient; opens and scans the entire file for every request */
-static auth_result htpasswd_auth (auth_client *auth_user)
+
+static int compare_users (void *arg, void *a, void *b)
{
- auth_t *auth = auth_user->client->auth;
- htpasswd_auth_state *state = auth->state;
- client_t *client = auth_user->client;
+ htpasswd_user *user1 = (htpasswd_user *)a;
+ htpasswd_user *user2 = (htpasswd_user *)b;
+
+ return strcmp (user1->name, user2->name);
+}
+
+
+static int _free_user (void *key)
+{
+ htpasswd_user *user = (htpasswd_user *)key;
+
+ free (user->name); /* ->pass is part of same buffer */
+ free (user);
+ return 1;
+}
+
+
+static void htpasswd_recheckfile (htpasswd_auth_state *htpasswd)
+{
FILE *passwdfile;
- char line[MAX_LINE_LEN];
+ avl_tree *new_users;
+ int num = 0;
+ struct stat file_stat;
char *sep;
+ char line [MAX_LINE_LEN];
- if (client->username == NULL || client->password == NULL)
- return AUTH_FAILED;
-
- passwdfile = fopen(state->filename, "rb");
- thread_rwlock_rlock(&state->file_rwlock);
- if(passwdfile == NULL) {
+ if (stat (htpasswd->filename, &file_stat) < 0)
+ {
+ WARN1 ("failed to check status of %s", htpasswd->filename);
+ return;
+ }
+ if (file_stat.st_mtime == htpasswd->mtime)
+ {
+ /* common case, no update to file */
+ return;
+ }
+ INFO1 ("re-reading htpasswd file \"%s\"", htpasswd->filename);
+ passwdfile = fopen (htpasswd->filename, "rb");
+ if (passwdfile == NULL)
+ {
WARN2("Failed to open authentication database \"%s\": %s",
- state->filename, strerror(errno));
- thread_rwlock_unlock(&state->file_rwlock);
- return AUTH_FAILED;
+ htpasswd->filename, strerror(errno));
+ return;
}
+ htpasswd->mtime = file_stat.st_mtime;
- while(get_line(passwdfile, line, MAX_LINE_LEN)) {
+ new_users = avl_tree_new (compare_users, NULL);
+
+ while (get_line(passwdfile, line, MAX_LINE_LEN))
+ {
+ int len;
+ htpasswd_user *entry;
+
+ num++;
if(!line[0] || line[0] == '#')
continue;
- sep = strchr(line, ':');
- if(sep == NULL) {
- DEBUG0("No separator in line");
+ sep = strrchr (line, ':');
+ if (sep == NULL)
+ {
+ WARN2("No separator on line %d (%s)", num, htpasswd->filename);
continue;
}
-
+ entry = calloc (1, sizeof (htpasswd_user));
+ len = strlen (line) + 1;
+ entry->name = malloc (len);
*sep = 0;
- if(!strcmp(client->username, line)) {
- /* Found our user, now: does the hash of password match hash? */
- char *hash = sep+1;
- char *hashed_password = get_hash(client->password, strlen(client->password));
- if(!strcmp(hash, hashed_password)) {
- fclose(passwdfile);
- free(hashed_password);
- thread_rwlock_unlock(&state->file_rwlock);
- return AUTH_OK;
- }
- free(hashed_password);
- /* We don't keep searching through the file */
- break;
- }
+ memcpy (entry->name, line, len);
+ entry->pass = entry->name + (sep-line) + 1;
+ avl_insert (new_users, entry);
}
+ fclose (passwdfile);
- fclose(passwdfile);
+ thread_rwlock_wlock (&htpasswd->file_rwlock);
+ if (htpasswd->users)
+ avl_tree_free (htpasswd->users, _free_user);
+ htpasswd->users = new_users;
+ thread_rwlock_unlock (&htpasswd->file_rwlock);
+}
- thread_rwlock_unlock(&state->file_rwlock);
+
+static auth_result htpasswd_auth (auth_client *auth_user)
+{
+ auth_t *auth = auth_user->client->auth;
+ htpasswd_auth_state *htpasswd = auth->state;
+ client_t *client = auth_user->client;
+ htpasswd_user entry;
+ void *result;
+
+ if (client->username == NULL || client->password == NULL)
+ return AUTH_FAILED;
+
+ htpasswd_recheckfile (htpasswd);
+
+ thread_rwlock_rlock (&htpasswd->file_rwlock);
+ entry.name = client->username;
+ if (avl_get_by_key (htpasswd->users, &entry, &result) == 0)
+ {
+ htpasswd_user *found = result;
+ char *hashed_pw;
+
+ thread_rwlock_unlock (&htpasswd->file_rwlock);
+ hashed_pw = get_hash (client->password, strlen (client->password));
+ if (strcmp (found->pass, hashed_pw) == 0)
+ {
+ free (hashed_pw);
+ return AUTH_OK;
+ }
+ free (hashed_pw);
+ DEBUG0 ("incorrect password for client");
+ return AUTH_FAILED;
+ }
+ DEBUG1 ("no such username: %s", client->username);
+ thread_rwlock_unlock (&htpasswd->file_rwlock);
return AUTH_FAILED;
}
+
int auth_get_htpasswd_auth (auth_t *authenticator, config_options_t *options)
{
htpasswd_auth_state *state;
@@ -170,61 +247,36 @@
state->filename);
thread_rwlock_create(&state->file_rwlock);
+ htpasswd_recheckfile (state);
return 0;
}
-int auth_htpasswd_existing_user(auth_t *auth, const char *username)
+
+static auth_result htpasswd_adduser (auth_t *auth, const char *username, const char *password)
{
FILE *passwdfile;
- htpasswd_auth_state *state;
- int ret = AUTH_OK;
- char line[MAX_LINE_LEN];
- char *sep;
+ char *hashed_password = NULL;
+ htpasswd_auth_state *state = auth->state;
+ htpasswd_user entry;
+ void *result;
- state = auth->state;
- passwdfile = fopen(state->filename, "rb");
+ htpasswd_recheckfile (state);
- if(passwdfile == NULL) {
- WARN2("Failed to open authentication database \"%s\": %s",
- state->filename, strerror(errno));
- return AUTH_FAILED;
- }
- while(get_line(passwdfile, line, MAX_LINE_LEN)) {
- if(!line[0] || line[0] == '#')
- continue;
- sep = strchr(line, ':');
- if(sep == NULL) {
- DEBUG0("No separator in line");
- continue;
- }
- *sep = 0;
- if (!strcmp(username, line)) {
- /* We found the user, break out of the loop */
- ret = AUTH_USEREXISTS;
- break;
- }
- }
+ thread_rwlock_wlock (&state->file_rwlock);
- fclose(passwdfile);
- return ret;
-
-}
-
-
-static int _auth_htpasswd_adduser(auth_t *auth, const char *username, const char *password)
-{
- FILE *passwdfile;
- char *hashed_password = NULL;
- htpasswd_auth_state *state;
-
- if (auth_htpasswd_existing_user(auth, username) == AUTH_USEREXISTS) {
+ entry.name = (char*)username;
+ if (avl_get_by_key (state->users, &entry, &result) == 0)
+ {
+ thread_rwlock_unlock (&state->file_rwlock);
return AUTH_USEREXISTS;
}
- state = auth->state;
+
passwdfile = fopen(state->filename, "ab");
- if(passwdfile == NULL) {
+ if (passwdfile == NULL)
+ {
+ thread_rwlock_unlock (&state->file_rwlock);
WARN2("Failed to open authentication database \"%s\": %s",
state->filename, strerror(errno));
return AUTH_FAILED;
@@ -237,21 +289,9 @@
}
fclose(passwdfile);
- return AUTH_USERADDED;
-}
-
-
-static auth_result htpasswd_adduser (auth_t *auth, const char *username, const char *password)
-{
- auth_result ret = 0;
- htpasswd_auth_state *state;
-
- state = auth->state;
- thread_rwlock_wlock (&state->file_rwlock);
- ret = _auth_htpasswd_adduser (auth, username, password);
thread_rwlock_unlock (&state->file_rwlock);
- return ret;
+ return AUTH_USERADDED;
}
@@ -267,11 +307,13 @@
struct stat file_info;
state = auth->state;
+ thread_rwlock_wlock (&state->file_rwlock);
passwdfile = fopen(state->filename, "rb");
if(passwdfile == NULL) {
WARN2("Failed to open authentication database \"%s\": %s",
state->filename, strerror(errno));
+ thread_rwlock_unlock (&state->file_rwlock);
return AUTH_FAILED;
}
tmpfile_len = strlen(state->filename) + 6;
@@ -282,6 +324,7 @@
WARN1 ("temp file \"%s\" exists, rejecting operation", tmpfile);
free (tmpfile);
fclose (passwdfile);
+ thread_rwlock_unlock (&state->file_rwlock);
return AUTH_FAILED;
}
@@ -292,6 +335,7 @@
tmpfile, strerror(errno));
fclose(passwdfile);
free(tmpfile);
+ thread_rwlock_unlock (&state->file_rwlock);
return AUTH_FAILED;
}
@@ -332,6 +376,8 @@
}
}
free(tmpfile);
+ thread_rwlock_unlock (&state->file_rwlock);
+ htpasswd_recheckfile (state);
return AUTH_USERDELETED;
}
@@ -340,40 +386,25 @@
static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode)
{
htpasswd_auth_state *state;
- FILE *passwdfile;
- char line[MAX_LINE_LEN];
- char *sep;
- char *passwd;
xmlNodePtr newnode;
+ avl_node *node;
state = auth->state;
- passwdfile = fopen(state->filename, "rb");
+ htpasswd_recheckfile (state);
- if(passwdfile == NULL) {
- WARN2("Failed to open authentication database \"%s\": %s",
- state->filename, strerror(errno));
- return AUTH_FAILED;
+ thread_rwlock_rlock (&state->file_rwlock);
+ node = avl_get_first (state->users);
+ while (node)
+ {
+ htpasswd_user *user = (htpasswd_user *)node->key;
+ newnode = xmlNewChild (srcnode, NULL, "User", NULL);
+ xmlNewChild(newnode, NULL, "username", user->name);
+ xmlNewChild(newnode, NULL, "password", user->pass);
+ node = avl_get_next (node);
}
+ thread_rwlock_unlock (&state->file_rwlock);
- while(get_line(passwdfile, line, MAX_LINE_LEN)) {
- if(!line[0] || line[0] == '#')
- continue;
-
- sep = strchr(line, ':');
- if(sep == NULL) {
- DEBUG0("No separator in line");
- continue;
- }
-
- *sep = 0;
- newnode = xmlNewChild(srcnode, NULL, "User", NULL);
- xmlNewChild(newnode, NULL, "username", line);
- passwd = sep+1;
- xmlNewChild(newnode, NULL, "password", passwd);
- }
-
- fclose(passwdfile);
return AUTH_OK;
}
Modified: icecast/branches/kh/icecast/src/auth_url.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.c 2005-07-18 00:36:00 UTC (rev 9582)
+++ icecast/branches/kh/icecast/src/auth_url.c 2005-07-18 14:27:39 UTC (rev 9583)
@@ -58,8 +58,10 @@
#include <stdio.h>
#ifndef _WIN32
#include <sys/wait.h>
+#include <strings.h>
#else
#define snprintf _snprintf
+#define strncasecmp strnicmp
#endif
#include <curl/curl.h>
@@ -415,6 +417,7 @@
if (url_info->timelimit_header)
url_info->timelimit_header_len = strlen (url_info->timelimit_header);
+ curl_easy_setopt (url_info->handle, CURLOPT_USERAGENT, ICECAST_VERSION_STRING);
curl_easy_setopt (url_info->handle, CURLOPT_HEADERFUNCTION, handle_returned_header);
curl_easy_setopt (url_info->handle, CURLOPT_WRITEFUNCTION, handle_returned_data);
curl_easy_setopt (url_info->handle, CURLOPT_WRITEDATA, url_info->handle);
More information about the commits
mailing list