aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitlbee.h2
-rw-r--r--commands.c10
-rw-r--r--conf.c13
-rw-r--r--conf.h3
-rw-r--r--crypting.c59
-rw-r--r--crypting.h6
-rw-r--r--irc.c2
-rw-r--r--storage.c129
-rw-r--r--storage.h10
-rw-r--r--storage_text.c15
-rw-r--r--unix.c5
11 files changed, 187 insertions, 67 deletions
diff --git a/bitlbee.h b/bitlbee.h
index 46a62bf0..41247270 100644
--- a/bitlbee.h
+++ b/bitlbee.h
@@ -115,7 +115,7 @@ typedef struct global_t {
int listen_socket;
help_t *help;
conf_t *conf;
- storage_t *storage;
+ GList *storage; /* The first backend in the list will be used for saving */
char *helpfile;
GMainLoop *loop;
} global_t;
diff --git a/commands.c b/commands.c
index 2877aa4b..27a84ee1 100644
--- a/commands.c
+++ b/commands.c
@@ -85,7 +85,7 @@ int cmd_help( irc_t *irc, char **cmd )
int cmd_identify( irc_t *irc, char **cmd )
{
- storage_status_t status = global.storage->load( irc->nick, cmd[1], irc );
+ storage_status_t status = storage_load( irc->nick, cmd[1], irc );
switch (status) {
case STORAGE_INVALID_PASSWORD:
@@ -101,7 +101,7 @@ int cmd_identify( irc_t *irc, char **cmd )
irc_usermsg( irc, "Something very weird happened" );
break;
}
-
+
return( 0 );
}
@@ -114,7 +114,7 @@ int cmd_register( irc_t *irc, char **cmd )
}
irc_setpass( irc, cmd[1] );
- switch( global.storage->save( irc, FALSE )) {
+ switch( storage_save( irc, FALSE )) {
case STORAGE_ALREADY_EXISTS:
irc_usermsg( irc, "Nick is already registered" );
break;
@@ -135,7 +135,7 @@ int cmd_drop( irc_t *irc, char **cmd )
{
storage_status_t status;
- status = global.storage->remove (irc->nick, cmd[1]);
+ status = storage_remove (irc->nick, cmd[1]);
switch (status) {
case STORAGE_NO_SUCH_USER:
irc_usermsg( irc, "That account does not exist" );
@@ -615,7 +615,7 @@ int cmd_set( irc_t *irc, char **cmd )
int cmd_save( irc_t *irc, char **cmd )
{
- if( global.storage->save( irc, TRUE ) == STORAGE_OK )
+ if( storage_save( irc, TRUE ) == STORAGE_OK )
irc_usermsg( irc, "Configuration saved" );
else
irc_usermsg( irc, "Configuration could not be saved!" );
diff --git a/conf.c b/conf.c
index 304a15a8..10c6911f 100644
--- a/conf.c
+++ b/conf.c
@@ -49,7 +49,7 @@ conf_t *conf_load( int argc, char *argv[] )
conf->port = 6667;
conf->nofork = 0;
conf->verbose = 0;
- conf->storage = "text";
+ conf->primary_storage = "text";
conf->runmode = RUNMODE_INETD;
conf->authmode = AUTHMODE_OPEN;
conf->password = NULL;
@@ -198,10 +198,15 @@ static int conf_loadini( conf_t *conf, char *file )
g_free( conf->motdfile );
conf->motdfile = g_strdup( ini->value );
}
- else if( g_strcasecmp( ini->key, "storage" ) == 0 )
+ else if( g_strcasecmp( ini->key, "account_storage" ) == 0 )
{
- g_free( conf->storage );
- conf->storage = g_strdup( ini->value );
+ g_free( conf->primary_storage );
+ conf->primary_storage = g_strdup( ini->value );
+ }
+ else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 )
+ {
+ g_strfreev( conf->migrate_storage );
+ conf->migrate_storage = g_strsplit( ini->value, " \t,;", -1 );
}
else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 )
{
diff --git a/conf.h b/conf.h
index a4f3ed79..ea9de150 100644
--- a/conf.h
+++ b/conf.h
@@ -41,7 +41,8 @@ typedef struct conf
char *hostname;
char *configdir;
char *motdfile;
- char *storage;
+ char *primary_storage;
+ char **migrate_storage;
int ping_interval;
int ping_timeout;
} conf_t;
diff --git a/crypting.c b/crypting.c
index eaba7285..5ba47e5b 100644
--- a/crypting.c
+++ b/crypting.c
@@ -28,31 +28,12 @@
included if CRYPTING_MAIN is defined. Or just do "make decode" and
the programs will be built. */
-#ifndef CRYPTING_MAIN
-#define BITLBEE_CORE
-#include "bitlbee.h"
-#include "irc.h"
#include "md5.h"
#include "crypting.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
-#else
-
-typedef struct irc
-{
- char *password;
-} irc_t;
-
-#include "md5.h"
-#include "crypting.h"
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#endif
-
/*\
* [SH] Do _not_ call this if it's not entirely sure that it will not cause
* harm to another users file, since this does not check the password for
@@ -82,20 +63,20 @@ int checkpass (const char *pass, const char *md5sum)
}
-char *hashpass (irc_t *irc) {
+char *hashpass (const char *password)
+{
md5_state_t md5state;
md5_byte_t digest[16];
int i;
char digits[3];
char *rv;
- if (irc->password == NULL) return (NULL);
+ if (password == NULL) return (NULL);
- rv = (char *)g_malloc (33);
- memset (rv, 0, 33);
+ rv = g_new0 (char, 33);
md5_init (&md5state);
- md5_append (&md5state, (unsigned char *)irc->password, strlen (irc->password));
+ md5_append (&md5state, (const unsigned char *)password, strlen (password));
md5_finish (&md5state, digest);
for (i = 0; i < 16; i++) {
@@ -107,47 +88,46 @@ char *hashpass (irc_t *irc) {
return (rv);
}
-char *obfucrypt (irc_t *irc, char *line)
+char *obfucrypt (char *line, const char *password)
{
int i, j;
char *rv;
- if (irc->password == NULL) return (NULL);
+ if (password == NULL) return (NULL);
- rv = g_new0(char, strlen (line) + 1);
+ rv = g_new0 (char, strlen (line) + 1);
i = j = 0;
while (*line) {
/* Encrypt/obfuscate the line, using the password */
if (*(signed char*)line < 0) *line = - (*line);
- if (((signed char*)irc->password)[i] < 0) irc->password[i] = - irc->password[i];
- rv[j] = *line + irc->password[i]; /* Overflow intended */
+ rv[j] = *line + password[i]; /* Overflow intended */
line++;
- if (!irc->password[++i]) i = 0;
+ if (!password[++i]) i = 0;
j++;
}
return (rv);
}
-char *deobfucrypt (irc_t *irc, char *line)
+char *deobfucrypt (char *line, const char *password)
{
int i, j;
char *rv;
- if (irc->password == NULL) return (NULL);
+ if (password == NULL) return (NULL);
- rv = g_new0(char, strlen (line) + 1);
+ rv = g_new0 (char, strlen (line) + 1);
i = j = 0;
while (*line) {
/* Decrypt/deobfuscate the line, using the pass */
- rv[j] = *line - irc->password[i]; /* Overflow intended */
+ rv[j] = *line - password[i]; /* Overflow intended */
line++;
- if (!irc->password[++i]) i = 0;
+ if (!password[++i]) i = 0;
j++;
}
@@ -161,9 +141,8 @@ char *deobfucrypt (irc_t *irc, char *line)
int main( int argc, char *argv[] )
{
- irc_t *irc = g_new0( irc_t, 1 );
char *hash, *action, line[256];
- char* (*func)( irc_t *, char * );
+ char* (*func)( char *, const char * );
if( argc < 2 )
{
@@ -173,9 +152,7 @@ int main( int argc, char *argv[] )
return( 1 );
}
- irc->password = g_strdup( argv[1] );
-
- hash = hashpass( irc );
+ hash = hashpass( argv[1] );
action = argv[0] + strlen( argv[0] ) - strlen( "encode" );
if( strcmp( action, "encode" ) == 0 )
@@ -207,7 +184,7 @@ int main( int argc, char *argv[] )
/* Flush the newline */
fgetc( stdin );
- out = func( irc, line );
+ out = func( line, argv[1] );
printf( "%s\n", out );
g_free( out );
}
diff --git a/crypting.h b/crypting.h
index c2572770..fbaa7dcc 100644
--- a/crypting.h
+++ b/crypting.h
@@ -24,6 +24,6 @@
*/
int checkpass (const char *password, const char *md5sum);
-char *hashpass (irc_t *irc);
-char *obfucrypt (irc_t *irc, char *line);
-char *deobfucrypt (irc_t *irc, char *line);
+char *hashpass (const char *password);
+char *obfucrypt (char *line, const char *password);
+char *deobfucrypt (char *line, const char *password);
diff --git a/irc.c b/irc.c
index 5601e314..d976410e 100644
--- a/irc.c
+++ b/irc.c
@@ -160,7 +160,7 @@ void irc_free(irc_t * irc)
log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd );
if( irc->status >= USTATUS_IDENTIFIED && set_getint( irc, "save_on_quit" ) )
- if( !global.storage->save( irc, TRUE ) )
+ if( storage_save( irc, TRUE ) != STORAGE_OK )
irc_usermsg( irc, "Error while saving settings!" );
if( irc->ping_source_id > 0 )
diff --git a/storage.c b/storage.c
index 8738a58f..b766c9e3 100644
--- a/storage.c
+++ b/storage.c
@@ -37,7 +37,7 @@ void register_storage_backend(storage_t *backend)
storage_backends = g_list_append(storage_backends, backend);
}
-storage_t *storage_init(const char *name)
+static storage_t *storage_init_single(const char *name)
{
GList *gl;
storage_t *st;
@@ -56,3 +56,130 @@ storage_t *storage_init(const char *name)
return st;
}
+
+GList *storage_init(const char *primary, char **migrate)
+{
+ GList *ret = NULL;
+ int i;
+ storage_t *storage;
+
+ storage = storage_init_single(primary);
+ if (storage == NULL)
+ return NULL;
+
+ ret = g_list_append(ret, storage);
+
+ for (i = 0; migrate && migrate[i]; i++) {
+ storage = storage_init_single(migrate[i]);
+
+ if (storage)
+ ret = g_list_append(ret, storage);
+ }
+
+ return ret;
+}
+
+storage_status_t storage_check_pass (const char *nick, const char *password)
+{
+ GList *gl;
+
+ /* Loop until we don't get NO_SUCH_USER */
+
+ for (gl = global.storage; gl; gl = gl->next) {
+ storage_t *st = gl->data;
+ storage_status_t status;
+
+ status = st->check_pass(nick, password);
+ if (status != STORAGE_NO_SUCH_USER)
+ return status;
+ }
+
+ return STORAGE_NO_SUCH_USER;
+}
+
+storage_status_t storage_load (const char *nick, const char *password, irc_t * irc)
+{
+ GList *gl;
+
+ /* Loop until we don't get NO_SUCH_USER */
+ for (gl = global.storage; gl; gl = gl->next) {
+ storage_t *st = gl->data;
+ storage_status_t status;
+
+ status = st->load(nick, password, irc);
+ if (status == STORAGE_OK) {
+ irc_setpass(irc, password);
+ return status;
+ }
+
+ if (status != STORAGE_NO_SUCH_USER)
+ return status;
+ }
+
+ return STORAGE_NO_SUCH_USER;
+}
+
+storage_status_t storage_save (irc_t *irc, int overwrite)
+{
+ return ((storage_t *)global.storage->data)->save(irc, overwrite);
+}
+
+storage_status_t storage_remove (const char *nick, const char *password)
+{
+ GList *gl;
+ storage_status_t ret = STORAGE_OK;
+
+ /* Remove this account from all storage backends. If this isn't
+ * done, the account will still be usable, it'd just be
+ * loaded from a different backend. */
+ for (gl = global.storage; gl; gl = gl->next) {
+ storage_t *st = gl->data;
+ storage_status_t status;
+
+ status = st->remove(nick, password);
+ if (status != STORAGE_NO_SUCH_USER &&
+ status != STORAGE_OK)
+ ret = status;
+ }
+
+ return ret;
+}
+
+storage_status_t storage_rename (const char *onick, const char *nnick, const char *password)
+{
+ storage_status_t status;
+ GList *gl = global.storage;
+ storage_t *primary_storage = gl->data;
+ irc_t *irc;
+
+ /* First, try to rename in the current write backend, assuming onick
+ * is stored there */
+ status = primary_storage->rename(onick, nnick, password);
+ if (status != STORAGE_NO_SUCH_USER)
+ return status;
+
+ /* Try to load from a migration backend and save to the current backend.
+ * Explicitly remove the account from the migration backend as otherwise
+ * it'd still be usable under the old name */
+
+ irc = g_new0(irc_t, 1);
+ status = storage_load(onick, password, irc);
+ if (status != STORAGE_OK) {
+ irc_free(irc);
+ return status;
+ }
+
+ g_free(irc->nick);
+ irc->nick = g_strdup(nnick);
+
+ status = storage_save(irc, FALSE);
+ if (status != STORAGE_OK) {
+ irc_free(irc);
+ return status;
+ }
+ irc_free(irc);
+
+ storage_remove(onick, password);
+
+ return STORAGE_OK;
+}
diff --git a/storage.h b/storage.h
index 3139d63b..301b424c 100644
--- a/storage.h
+++ b/storage.h
@@ -52,7 +52,15 @@ typedef struct {
storage_status_t (*rename) (const char *onick, const char *nnick, const char *password);
} storage_t;
+storage_status_t storage_check_pass (const char *nick, const char *password);
+
+storage_status_t storage_load (const char *nick, const char *password, irc_t * irc);
+storage_status_t storage_save (irc_t *irc, int overwrite);
+storage_status_t storage_remove (const char *nick, const char *password);
+
+storage_status_t storage_rename (const char *onick, const char *nnick, const char *password);
+
void register_storage_backend(storage_t *);
-storage_t *storage_init(const char *name);
+GList *storage_init(const char *primary, char **migrate);
#endif /* __STORAGE_H__ */
diff --git a/storage_text.c b/storage_text.c
index f3ca8a38..5909ff63 100644
--- a/storage_text.c
+++ b/storage_text.c
@@ -66,7 +66,8 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i
while( fscanf( fp, "%511[^\n]s", s ) > 0 )
{
fgetc( fp );
- line = deobfucrypt( irc, s );
+ line = deobfucrypt( s, password );
+ if (line == NULL) return STORAGE_OTHER_ERROR;
root_command_string( irc, ru, line, 0 );
g_free( line );
}
@@ -128,11 +129,11 @@ static storage_status_t text_save( irc_t *irc, int overwrite )
* me. I just thought it was funny.
\*/
- hash = hashpass( irc );
+ hash = hashpass( irc->password );
if( hash == NULL )
{
irc_usermsg( irc, "Please register yourself if you want to save your settings." );
- return( 0 );
+ return STORAGE_OTHER_ERROR;
}
g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" );
@@ -191,7 +192,7 @@ static storage_status_t text_save( irc_t *irc, int overwrite )
g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"",
proto_name[a->protocol], a->user, a->pass, a->server ? a->server : "" );
- line = obfucrypt( irc, s );
+ line = obfucrypt( s, irc->password );
if( *line )
{
if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
@@ -209,7 +210,7 @@ static storage_status_t text_save( irc_t *irc, int overwrite )
if( set->value && set->def )
{
g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value );
- line = obfucrypt( irc, s );
+ line = obfucrypt( s, irc->password );
if( *line )
{
if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
@@ -226,7 +227,7 @@ static storage_status_t text_save( irc_t *irc, int overwrite )
if( strcmp( irc->mynick, ROOT_NICK ) != 0 )
{
g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick );
- line = obfucrypt( irc, s );
+ line = obfucrypt( s, irc->password );
if( *line )
{
if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
@@ -269,7 +270,7 @@ static storage_status_t text_check_pass( const char *nick, const char *password
char s[512];
FILE *fp;
- g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
+ g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" );
fp = fopen( s, "r" );
if (!fp)
return STORAGE_NO_SUCH_USER;
diff --git a/unix.c b/unix.c
index 6813be31..75f0b11d 100644
--- a/unix.c
+++ b/unix.c
@@ -71,9 +71,10 @@ int main( int argc, char *argv[] )
if( i != 0 )
return( i );
- global.storage = storage_init( global.conf->storage );
+ global.storage = storage_init( global.conf->primary_storage,
+ global.conf->migrate_storage );
if ( global.storage == NULL) {
- log_message( LOGLVL_ERROR, "No such storage backend '%s'", global.conf->storage );
+ log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage );
return( 1 );
}