diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2005-12-14 00:21:21 +0100 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2005-12-14 00:21:21 +0100 | 
| commit | 6aaa2213588f7c4c00a68c5622f6974679eaf196 (patch) | |
| tree | 7aad536700d387bacd3003927e9ac3c531616259 | |
| parent | ab4afbab829a4a5bf520d4e1425a743cdb8c4865 (diff) | |
| parent | d3307e281afdbed22a561eb2cd73f97a03e3073d (diff) | |
More work on the storage abstraction layer from Jelmer.
| -rw-r--r-- | bitlbee.h | 2 | ||||
| -rw-r--r-- | commands.c | 10 | ||||
| -rw-r--r-- | conf.c | 13 | ||||
| -rw-r--r-- | conf.h | 3 | ||||
| -rw-r--r-- | crypting.c | 59 | ||||
| -rw-r--r-- | crypting.h | 6 | ||||
| -rw-r--r-- | irc.c | 2 | ||||
| -rw-r--r-- | storage.c | 129 | ||||
| -rw-r--r-- | storage.h | 10 | ||||
| -rw-r--r-- | storage_text.c | 15 | ||||
| -rw-r--r-- | unix.c | 5 | 
11 files changed, 187 insertions, 67 deletions
| @@ -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; @@ -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!" ); @@ -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 )  			{ @@ -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; @@ -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 );  	} @@ -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); @@ -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 ) @@ -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; +} @@ -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; @@ -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 );  	} | 
