diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2008-09-06 23:59:32 +0100 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2008-09-06 23:59:32 +0100 |
commit | 3183c21afa7700ebc4dac02367653d1398a5b14a (patch) | |
tree | 70f46f382d76a99e1a4c9cd790604ab8cbc7da94 | |
parent | 0a4f6f4d3eff2944ff36a0bd6ec0986824f23ade (diff) |
Completely reviewed all uses of irc->password, irc_setpass() and
USTATUS_IDENTIFIED after another account overwriting vulnerability was
found by Tero Marttila.
-rw-r--r-- | irc.c | 4 | ||||
-rw-r--r-- | root_commands.c | 12 | ||||
-rw-r--r-- | storage.c | 40 | ||||
-rw-r--r-- | storage.h | 8 | ||||
-rw-r--r-- | storage_text.c | 13 | ||||
-rw-r--r-- | storage_xml.c | 19 |
6 files changed, 52 insertions, 44 deletions
@@ -37,7 +37,7 @@ static char *set_eval_password( set_t *set, char *value ) { irc_t *irc = set->data; - if( irc->status & USTATUS_IDENTIFIED ) + if( irc->status & USTATUS_IDENTIFIED && value ) { irc_setpass( irc, value ); return NULL; @@ -238,7 +238,7 @@ void irc_free( irc_t * irc ) log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) ) - if( storage_save( irc, TRUE ) != STORAGE_OK ) + if( storage_save( irc, NULL, TRUE ) != STORAGE_OK ) irc_usermsg( irc, "Error while saving settings!" ); irc_connection_list = g_slist_remove( irc_connection_list, irc ); diff --git a/root_commands.c b/root_commands.c index 88127acb..57d5c91a 100644 --- a/root_commands.c +++ b/root_commands.c @@ -130,7 +130,7 @@ static void cmd_account( irc_t *irc, char **cmd ); static void cmd_identify( irc_t *irc, char **cmd ) { - storage_status_t status = storage_load( irc->nick, cmd[1], irc ); + storage_status_t status = storage_load( irc, cmd[1] ); char *account_on[] = { "account", "on", NULL }; switch (status) { @@ -142,6 +142,8 @@ static void cmd_identify( irc_t *irc, char **cmd ) break; case STORAGE_OK: irc_usermsg( irc, "Password accepted, settings and accounts loaded" ); + irc_setpass( irc, cmd[1] ); + irc->status |= USTATUS_IDENTIFIED; irc_umode_set( irc, "+R", 1 ); if( set_getbool( &irc->set, "auto_connect" ) ) cmd_account( irc, account_on ); @@ -161,14 +163,14 @@ static void cmd_register( irc_t *irc, char **cmd ) return; } - irc_setpass( irc, cmd[1] ); - switch( storage_save( irc, FALSE )) { + switch( storage_save( irc, cmd[1], FALSE ) ) { case STORAGE_ALREADY_EXISTS: irc_usermsg( irc, "Nick is already registered" ); break; case STORAGE_OK: irc_usermsg( irc, "Account successfully created" ); + irc_setpass( irc, cmd[1] ); irc->status |= USTATUS_IDENTIFIED; irc_umode_set( irc, "+R", 1 ); break; @@ -886,7 +888,9 @@ static void cmd_set( irc_t *irc, char **cmd ) static void cmd_save( irc_t *irc, char **cmd ) { - if( storage_save( irc, TRUE ) == STORAGE_OK ) + if( ( irc->status & USTATUS_IDENTIFIED ) == 0 ) + irc_usermsg( irc, "Please create an account first" ); + else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK ) irc_usermsg( irc, "Configuration saved" ); else irc_usermsg( irc, "Configuration could not be saved!" ); @@ -102,20 +102,21 @@ storage_status_t storage_check_pass (const char *nick, const char *password) return STORAGE_NO_SUCH_USER; } -storage_status_t storage_load (const char *nick, const char *password, irc_t * irc) +storage_status_t storage_load (irc_t * irc, const char *password) { GList *gl; + if (irc && irc->status & USTATUS_IDENTIFIED) + return STORAGE_OTHER_ERROR; + /* 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); + status = st->load(irc, password); + if (status == STORAGE_OK) return status; - } if (status != STORAGE_NO_SUCH_USER) return status; @@ -124,9 +125,27 @@ storage_status_t storage_load (const char *nick, const char *password, irc_t * i return STORAGE_NO_SUCH_USER; } -storage_status_t storage_save (irc_t *irc, int overwrite) +storage_status_t storage_save (irc_t *irc, char *password, int overwrite) { - return ((storage_t *)global.storage->data)->save(irc, overwrite); + storage_status_t st; + + if (password != NULL) { + /* Should only use this in the "register" command. */ + if (irc->password || overwrite) + return STORAGE_OTHER_ERROR; + + irc_setpass(irc, password); + } else if ((irc->status & USTATUS_IDENTIFIED) == 0) { + return STORAGE_NO_SUCH_USER; + } + + st = ((storage_t *)global.storage->data)->save(irc, overwrite); + + if (password != NULL) { + irc_setpass(irc, NULL); + } + + return st; } storage_status_t storage_remove (const char *nick, const char *password) @@ -142,14 +161,16 @@ storage_status_t storage_remove (const char *nick, const char *password) storage_status_t status; status = st->remove(nick, password); - if (status != STORAGE_NO_SUCH_USER && - status != STORAGE_OK) + if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK) ret = status; } return ret; } +#if 0 +Not using this yet. Test thoroughly before adding UI hooks to this function. + storage_status_t storage_rename (const char *onick, const char *nnick, const char *password) { storage_status_t status; @@ -188,3 +209,4 @@ storage_status_t storage_rename (const char *onick, const char *nnick, const cha return STORAGE_OK; } +#endif @@ -44,7 +44,7 @@ typedef struct { storage_status_t (*check_pass) (const char *nick, const char *password); - storage_status_t (*load) (const char *nick, const char *password, irc_t * irc); + storage_status_t (*load) (irc_t *irc, const char *password); storage_status_t (*save) (irc_t *irc, int overwrite); storage_status_t (*remove) (const char *nick, const char *password); @@ -54,11 +54,11 @@ typedef struct { 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_load (irc_t * irc, const char *password); +storage_status_t storage_save (irc_t *irc, char *password, 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); +/* storage_status_t storage_rename (const char *onick, const char *nnick, const char *password); */ void register_storage_backend(storage_t *); G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate); diff --git a/storage_text.c b/storage_text.c index 78f7e3bd..8ce4edcf 100644 --- a/storage_text.c +++ b/storage_text.c @@ -43,7 +43,7 @@ static void text_init (void) it's read only! */ } -static storage_status_t text_load ( const char *my_nick, const char* password, irc_t *irc ) +static storage_status_t text_load( irc_t *irc, const char* password ) { char s[512]; char *line; @@ -53,10 +53,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i user_t *ru = user_find( irc, ROOT_NICK ); account_t *acc, *acc_lookup[9]; - if( irc->status & USTATUS_IDENTIFIED ) - return( 1 ); - - g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" ); + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); fp = fopen( s, "r" ); if( !fp ) return STORAGE_NO_SUCH_USER; @@ -68,10 +65,6 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i return STORAGE_INVALID_PASSWORD; } - /* Do this now. If the user runs with AuthMode = Registered, the - account command will not work otherwise. */ - irc->status |= USTATUS_IDENTIFIED; - while( fscanf( fp, "%511[^\n]s", s ) > 0 ) { fgetc( fp ); @@ -100,7 +93,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i acc_lookup[8] = acc; } - g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" ); + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" ); fp = fopen( s, "r" ); if( !fp ) return STORAGE_NO_SUCH_USER; while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 ) diff --git a/storage_xml.c b/storage_xml.c index 8b205c5a..bd0c1953 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -258,7 +258,7 @@ static void xml_init( void ) log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to `%s'.", global.conf->configdir ); } -static storage_status_t xml_load_real( const char *my_nick, const char *password, irc_t *irc, xml_pass_st action ) +static storage_status_t xml_load_real( irc_t *irc, const char *my_nick, const char *password, xml_pass_st action ) { GMarkupParseContext *ctx; struct xml_parsedata *xd; @@ -266,9 +266,6 @@ static storage_status_t xml_load_real( const char *my_nick, const char *password GError *gerr = NULL; int fd, st; - if( irc && irc->status & USTATUS_IDENTIFIED ) - return( 1 ); - xd = g_new0( struct xml_parsedata, 1 ); xd->irc = irc; xd->given_nick = g_strdup( my_nick ); @@ -320,21 +317,19 @@ static storage_status_t xml_load_real( const char *my_nick, const char *password if( action == XML_PASS_CHECK_ONLY ) return STORAGE_OK; - irc->status |= USTATUS_IDENTIFIED; - return STORAGE_OK; } -static storage_status_t xml_load( const char *my_nick, const char *password, irc_t *irc ) +static storage_status_t xml_load( irc_t *irc, const char *password ) { - return xml_load_real( my_nick, password, irc, XML_PASS_UNKNOWN ); + return xml_load_real( irc, irc->nick, password, XML_PASS_UNKNOWN ); } static storage_status_t xml_check_pass( const char *my_nick, const char *password ) { /* This is a little bit risky because we have to pass NULL for the irc_t argument. This *should* be fine, if I didn't miss anything... */ - return xml_load_real( my_nick, password, NULL, XML_PASS_CHECK_ONLY ); + return xml_load_real( NULL, my_nick, password, XML_PASS_CHECK_ONLY ); } static int xml_printf( int fd, int indent, char *fmt, ... ) @@ -370,12 +365,6 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) md5_byte_t pass_md5[21]; md5_state_t md5_state; - if( irc->password == NULL ) - { - irc_usermsg( irc, "Please register yourself if you want to save your settings." ); - return STORAGE_OTHER_ERROR; - } - path2 = g_strdup( irc->nick ); nick_lc( path2 ); g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" ); |