source: storage_text.c @ 90bbb0e

Last change on this file since 90bbb0e was 90bbb0e, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-06-26T16:50:47Z

Moved the call to "account on" to the right place.

  • Property mode set to 100644
File size: 9.0 KB
RevLine 
[1ee6c18]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Storage backend that uses the same file format as <=1.0 */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28#include "crypting.h"
29
[703f0f7]30/* DO NOT USE THIS FUNCTION IN NEW CODE. This
31 * function is here merely because the save/load code still uses
[bf02a67]32 * ids rather than names */
[703f0f7]33static struct prpl *find_protocol_by_id(int id)
34{
35        switch (id) {
[c4168f4]36        case 0: case 1: case 3: return find_protocol("oscar");
[703f0f7]37        case 4: return find_protocol("msn");
38        case 2: return find_protocol("yahoo");
39        case 8: return find_protocol("jabber");
40        default: break;
41        }
42        return NULL;
43}
44
45static int find_protocol_id(const char *name)
46{
47        if (!strcmp(name, "oscar")) return 1;
48        if (!strcmp(name, "msn")) return 4;
49        if (!strcmp(name, "yahoo")) return 2;
50        if (!strcmp(name, "jabber")) return 8;
51
52        return -1;
53}
54
55
[1ee6c18]56static void text_init (void)
57{
58        if( access( global.conf->configdir, F_OK ) != 0 )
59                log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", CONFIG );
60        else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 )
61                log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir );
62}
63
[a1f17d4]64static storage_status_t text_load ( const char *my_nick, const char* password, irc_t *irc )
[1ee6c18]65{
66        char s[512];
67        char *line;
68        int proto;
69        char nick[MAX_NICK_LENGTH+1];
70        FILE *fp;
71        user_t *ru = user_find( irc, ROOT_NICK );
72       
[79e826a]73        if( irc->status & USTATUS_IDENTIFIED )
[1ee6c18]74                return( 1 );
75       
76        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" );
77        fp = fopen( s, "r" );
[a1f17d4]78        if( !fp ) return STORAGE_NO_SUCH_USER;
[1ee6c18]79       
80        fscanf( fp, "%32[^\n]s", s );
[7cad7b4]81
82        if (checkpass (password, s) != 0) 
[1ee6c18]83        {
84                fclose( fp );
[a1f17d4]85                return STORAGE_INVALID_PASSWORD;
[1ee6c18]86        }
87       
88        /* Do this now. If the user runs with AuthMode = Registered, the
89           account command will not work otherwise. */
[79e826a]90        irc->status |= USTATUS_IDENTIFIED;
[1ee6c18]91       
92        while( fscanf( fp, "%511[^\n]s", s ) > 0 )
93        {
94                fgetc( fp );
[b73ac9c]95                line = deobfucrypt( s, password );
96                if (line == NULL) return STORAGE_OTHER_ERROR;
[1ee6c18]97                root_command_string( irc, ru, line, 0 );
98                g_free( line );
99        }
100        fclose( fp );
101       
102        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" );
103        fp = fopen( s, "r" );
[a1f17d4]104        if( !fp ) return STORAGE_NO_SUCH_USER;
[1ee6c18]105        while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 )
106        {
[703f0f7]107                struct prpl *prpl;
108
109                prpl = find_protocol_by_id(proto);
110
111                if (!prpl)
112                        continue;
113
[1ee6c18]114                http_decode( s );
[703f0f7]115                nick_set( irc, s, prpl, nick );
[1ee6c18]116        }
117        fclose( fp );
118       
[a1f17d4]119        return STORAGE_OK;
[1ee6c18]120}
121
[a1f17d4]122static storage_status_t text_save( irc_t *irc, int overwrite )
[1ee6c18]123{
124        char s[512];
125        char path[512], new_path[512];
126        char *line;
127        nick_t *n;
128        set_t *set;
129        mode_t ou = umask( 0077 );
130        account_t *a;
131        FILE *fp;
132        char *hash;
[a1f17d4]133
134        if (!overwrite) {
135                g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
136                if (access( path, F_OK ) != -1)
137                        return STORAGE_ALREADY_EXISTS;
138       
139                g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
140                if (access( path, F_OK ) != -1)
141                        return STORAGE_ALREADY_EXISTS;
142        }
[1ee6c18]143       
144        /*\
145         *  [SH] Nothing should be saved if no password is set, because the
146         *  password is not set if it was wrong, or if one is not identified
147         *  yet. This means that a malicious user could easily overwrite
148         *  files owned by someone else:
149         *  a Bad Thing, methinks
150        \*/
151
152        /* [WVG] No? Really? */
153
154        /*\
155         *  [SH] Okay, okay, it wasn't really Wilmer who said that, it was
156         *  me. I just thought it was funny.
157        \*/
158       
[b73ac9c]159        hash = hashpass( irc->password );
[1ee6c18]160        if( hash == NULL )
161        {
162                irc_usermsg( irc, "Please register yourself if you want to save your settings." );
[b73ac9c]163                return STORAGE_OTHER_ERROR;
[1ee6c18]164        }
165       
166        g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" );
167        fp = fopen( path, "w" );
[a1f17d4]168        if( !fp ) return STORAGE_OTHER_ERROR;
[1ee6c18]169        for( n = irc->nicks; n; n = n->next )
170        {
171                strcpy( s, n->handle );
172                s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */
173                http_encode( s );
[703f0f7]174                g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", find_protocol_id(n->proto->name), n->nick );
[1ee6c18]175                if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 )
176                {
177                        irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
178                        fclose( fp );
[a1f17d4]179                        return STORAGE_OTHER_ERROR;
[1ee6c18]180                }
181        }
182        if( fclose( fp ) != 0 )
183        {
184                irc_usermsg( irc, "fclose() reported an error. Disk full?" );
[a1f17d4]185                return STORAGE_OTHER_ERROR;
[1ee6c18]186        }
187 
188        g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
189        if( unlink( new_path ) != 0 )
190        {
191                if( errno != ENOENT )
192                {
193                        irc_usermsg( irc, "Error while removing old .nicks file" );
[a1f17d4]194                        return STORAGE_OTHER_ERROR;
[1ee6c18]195                }
196        }
197        if( rename( path, new_path ) != 0 )
198        {
199                irc_usermsg( irc, "Error while renaming new .nicks file" );
[a1f17d4]200                return STORAGE_OTHER_ERROR;
[1ee6c18]201        }
202       
203        g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" );
204        fp = fopen( path, "w" );
[a1f17d4]205        if( !fp ) return STORAGE_OTHER_ERROR;
[1ee6c18]206        if( fprintf( fp, "%s", hash ) != strlen( hash ) )
207        {
208                irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
209                fclose( fp );
[a1f17d4]210                return STORAGE_OTHER_ERROR;
[1ee6c18]211        }
212        g_free( hash );
213
214        for( a = irc->accounts; a; a = a->next )
215        {
[703f0f7]216                if( !strcmp(a->prpl->name, "oscar") )
[1ee6c18]217                        g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server );
218                else
219                        g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"",
[703f0f7]220                                    a->prpl->name, a->user, a->pass, a->server ? a->server : "" );
[1ee6c18]221               
[b73ac9c]222                line = obfucrypt( s, irc->password );
[1ee6c18]223                if( *line )
224                {
225                        if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
226                        {
227                                irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
228                                fclose( fp );
[a1f17d4]229                                return STORAGE_OTHER_ERROR;
[1ee6c18]230                        }
231                }
232                g_free( line );
233        }
234       
235        for( set = irc->set; set; set = set->next )
236        {
237                if( set->value && set->def )
238                {
239                        g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value );
[b73ac9c]240                        line = obfucrypt( s, irc->password );
[1ee6c18]241                        if( *line )
242                        {
243                                if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
244                                {
245                                        irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
246                                        fclose( fp );
[a1f17d4]247                                        return STORAGE_OTHER_ERROR;
[1ee6c18]248                                }
249                        }
250                        g_free( line );
251                }
252        }
253       
254        if( strcmp( irc->mynick, ROOT_NICK ) != 0 )
255        {
256                g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick );
[b73ac9c]257                line = obfucrypt( s, irc->password );
[1ee6c18]258                if( *line )
259                {
260                        if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
261                        {
262                                irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
263                                fclose( fp );
[a1f17d4]264                                return STORAGE_OTHER_ERROR;
[1ee6c18]265                        }
266                }
267                g_free( line );
268        }
269        if( fclose( fp ) != 0 )
270        {
271                irc_usermsg( irc, "fclose() reported an error. Disk full?" );
[a1f17d4]272                return STORAGE_OTHER_ERROR;
[1ee6c18]273        }
274       
275        g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
276        if( unlink( new_path ) != 0 )
277        {
278                if( errno != ENOENT )
279                {
280                        irc_usermsg( irc, "Error while removing old .accounts file" );
[a1f17d4]281                        return STORAGE_OTHER_ERROR;
[1ee6c18]282                }
283        }
284        if( rename( path, new_path ) != 0 )
285        {
286                irc_usermsg( irc, "Error while renaming new .accounts file" );
[a1f17d4]287                return STORAGE_OTHER_ERROR;
[1ee6c18]288        }
289       
290        umask( ou );
291       
[a1f17d4]292        return STORAGE_OK;
[1ee6c18]293}
294
[7989fcf3]295static storage_status_t text_check_pass( const char *nick, const char *password )
[1ee6c18]296{
297        char s[512];
298        FILE *fp;
299       
[b73ac9c]300        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" );
[1ee6c18]301        fp = fopen( s, "r" );
[a1f17d4]302        if (!fp)
303                return STORAGE_NO_SUCH_USER;
[1ee6c18]304
305        fscanf( fp, "%32[^\n]s", s );
306        fclose( fp );
307
[7cad7b4]308        if (checkpass( password, s) == -1)
309                return STORAGE_INVALID_PASSWORD;
[a1f17d4]310
[7989fcf3]311        return STORAGE_OK;
312}
313
314static storage_status_t text_remove( const char *nick, const char *password )
315{
316        char s[512];
317        storage_status_t status;
318
319        status = text_check_pass( nick, password );
320        if (status != STORAGE_OK)
321                return status;
322
[a1f17d4]323        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" );
324        if (unlink( s ) == -1)
325                return STORAGE_OTHER_ERROR;
326       
327        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
328        if (unlink( s ) == -1)
329                return STORAGE_OTHER_ERROR;
330
331        return STORAGE_OK;
[1ee6c18]332}
333
334storage_t storage_text = {
335        .name = "text",
336        .init = text_init,
[7989fcf3]337        .check_pass = text_check_pass,
[1ee6c18]338        .remove = text_remove,
339        .load = text_load,
340        .save = text_save
341};
Note: See TracBrowser for help on using the repository browser.