5749368 [rkeene@sledge /home/rkeene/projects/ircbot/bot]$ cat -n users.c
  1 /* users.c version 0.333 */
  2 /* all versions previous to 0.333 are completely public domain */
  3 /* all contributed code falls under the same BSD style license as */
  4 /* noted below unless the contributing author places a copyright */
  5 /* notice in their file/s. */
  6 
  7 
  8 /*
  9  *  * Copyright (c) 2001 David T. Stiles
 10  *  * All rights reserved.
 11  *  *
 12  *  * Redistribution and use in source and binary forms, with or without
 13  *  * modification, are permitted provided that the following conditions
 14  *  * are met:
 15  *  * 1. Redistributions of source code must retain the above copyright
 16  *  *    notice, this list of conditions and the following disclaimer.
 17  *  * 2. Redistributions in binary form must reproduce the above copyright
 18  *  *    notice, this list of conditions and the following disclaimer in the
 19  *  *    documentation and/or other materials provided with the distribution.
 20  *  * 3. All advertising materials mentioning features or use of this software
 21  *  *    must display the following acknowledgement:
 22  *  *      This product includes software developed by David T. Stiles
 23  *  * 4. The name David T. Stiles may not be used to endorse or promote
 24  *  *    products derived from this software without specific prior written
 25  *  *    permission.
 26  *  *
 27  *  * THIS SOFTWARE IS PROVIDED BY DAVID T. STILES `AS IS'' AND ANY
 28  *  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 29  *  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 30  *  * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID T. STILES BE LIABLE
 31  *  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 32  *  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 33  *  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 34  *  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 35  *  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 36  *  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 37  *  * SUCH DAMAGE.
 38  *  */
 39 
 40 /* this code would not be possible without the patience and intelligence */
 41 /* provided by many of the people from #c/efnet. I thank all of you sincerely. */
 42 
 43 /* user stuff. ugh!
 44  * i load in the data file on users into a linked list that is defined in
 45  * users.h. *usr is the anchor, *trv is is the pointer i use to travel
 46  * through the list. *lag makes it so i do not need a doubly linked list by
 47  * providing a pointer to the node previous to the one *trv is pointing at.
 48  * i use crypt to generate password hashes. you may need to provide the
 49  * flag -lcrypto in the makefile. i have to in slackware but not in openbsd.
 50  */
 51 
 52 #include "users.h"
 53 #include "bot.h"
 54 
 55 extern char MSGTO[MAXDATASIZE];
 56 
 57 static struct user *usr;
 58 static struct user *trv;
 59 static struct user *lag;
 60 static FILE *fp;
 61 static long int total_users = 0;
 62 
 63 
 64 /* call only once during the entire course of the program! or else... */
 65 int loadusers( char *filename )
 66 {
 67    fp = fopen( filename, "r" );
 68    if( !fp ) return 1;
 69 
 70    usr = (struct user *)malloc( sizeof( struct user ) );
 71    if( !usr ) return( 1 );
 72    lag = trv = usr;
 73 
 74    while( !feof( fp ) ) {
 75       fgets( trv->data, USERINFO, fp );
 76       clean_message( trv->data );
 77       if( !trv->data[0] ) break;
 78       ++total_users;
 79       lag = trv;
 80       trv->next = (struct user *)malloc( sizeof( struct user ) );
 81       trv = trv->next;
 82       if(!trv) return( 1 );
 83      }
 84 
 85    free( trv );
 86    lag->next = NULL;
 87 
 88    fclose( fp );
 89 
 90    return 0;
 91 }
 92 
 93 
 94 
 95 
 96 void saveusers( char *filename )
 97 {
 98    fp = fopen( filename, "w" );
 99    if( !fp ) return;
100 
101    trv = usr;
102 
103    while( trv->next ) { fprintf( fp, "%s\n", trv->data ); trv = trv->next; }
104    fprintf( fp, "%s\n", trv->data );
105    fclose( fp );
106 
107    return;
108 }
109 
110 
111 
112 void rmuser( char *passwd, char *name, char *rmname )
113 {
114    int x = 0;
115    char sndmsg[MAXDATASIZE];
116 
117    /* validate user before we do what they want */
118 
119    if( valid_login( name, passwd ) ) snprintf( sndmsg, MAXDATASIZE, "privmsg %s :credentials verified.", name );
120    else {
121       snprintf( sndmsg, MAXDATASIZE, "privmsg %s :access denied.", name );
122       send_irc_message( sndmsg );
123       return;
124      }
125 
126    if( rmname[0] == '\0' ) return;
127 
128    x = valid_user( rmname );
129    if( !x ) {
130       snprintf( sndmsg, MAXDATASIZE, "privmsg %s :user: %s not found.", name, rmname );
131       send_irc_message( sndmsg );
132       return;
133      }
134 
135    lag->next = trv->next;
136    free( trv );
137    --total_users;
138    
139 
140    snprintf( sndmsg, MAXDATASIZE, "privmsg %s :user: %s removed.", name, rmname );
141    send_irc_message( sndmsg );
142    saveusers( "user.list" );
143    return;
144 }
145 
146 
147 
148 void adduser( char *pass, char *name, char *newupass, char *newuname )
149 {
150    char sndmsg[MAXDATASIZE];
151    char salt[MAXDATASIZE];
152    char *hash;
153 
154    /* validate user before we do what they want */
155    if( valid_login( name, pass ) ) {
156       snprintf( sndmsg, MAXDATASIZE, "privmsg %s :credentials verified.", name );
157       send_irc_message( sndmsg );
158      }
159    else {
160       snprintf( sndmsg, MAXDATASIZE, "privmsg %s :access denied.", name );
161       send_irc_message( sndmsg );
162       return;
163      }
164 
165    if( newupass[0] == '\0' ) {
166       snprintf( sndmsg, MAXDATASIZE, "PRIVMSG %s : new password is invalid", name );
167       send_irc_message( sndmsg );
168       return;
169      }
170    if( newuname[0] == '\0' ) {
171       snprintf( sndmsg, MAXDATASIZE, "PRIVMSG %s : new username is invalid", name );
172       send_irc_message( sndmsg );
173       return;
174      }
175 
176    if( valid_user( newuname ) ) {
177       snprintf( sndmsg, MAXDATASIZE, "privmsg %s :user exists.", name );
178       send_irc_message( sndmsg );
179       return;
180      }
181 
182    lag->next = (struct user *)malloc( sizeof( struct user ) );
183    trv = lag->next;
184    trv->next = NULL;
185 
186    get_salt( salt );
187 
188    hash = crypt( newupass, salt );
189 
190    snprintf( trv->data, MAXDATASIZE, "%s %s 0", newuname, hash );
191 
192    ++total_users;
193    snprintf( sndmsg, MAXDATASIZE, "privmsg %s :user: %s added.", name, newuname );
194    send_irc_message( sndmsg );
195 
196    saveusers( "user.list" );
197    return;
198 }
199 
200 
201 
202 void chpass( char *passwd, char *name, char *newpass )
203 {
204    int x;
205    char sndmsg[MAXDATASIZE];
206    char tmpray[MAXDATASIZE];
207    char salt[MAXDATASIZE];
208    char *hash;
209 
210    /* validate user before we do what they want */
211    if( !valid_login( name, passwd ) ) {
212        snprintf( sndmsg, MAXDATASIZE, "privmsg %s :access denied.", MSGTO );
213       send_irc_message( sndmsg );
214       return;
215      }
216 
217    if( newpass[0] == '\0' ) {
218        snprintf( sndmsg, MAXDATASIZE, "privmsg %s :null passwords are not allowed.", MSGTO );
219       send_irc_message( sndmsg );
220       return;
221      }
222 
223    x = chop( trv->data, tmpray, 0, ' ' );
224    x = chop( trv->data, tmpray, x, ' ' ); /* these two calls to chop() are to init x. the data is discarded */
225    strncpy( tmpray, &trv->data[x], MAXDATASIZE );
226 
227    get_salt( salt );
228 
229    hash = crypt( newpass, salt );
230    snprintf( trv->data, MAXDATASIZE, "%s %s %s", name, hash, tmpray );
231 
232    snprintf( sndmsg, MAXDATASIZE, "privmsg %s :password changed.", MSGTO );
233    send_irc_message( sndmsg );
234 
235    saveusers( "user.list" );
236    return;
237 }
238 
239 
240 
241 void whois( char *name )
242 {
243    int position = 0;
244    char tmpray[MAXDATASIZE];
245 
246    position = valid_user( name );
247    if( !position ) {
248       snprintf( tmpray, MAXDATASIZE, "privmsg %s :%s is not known to me.", MSGTO, name );
249       send_irc_message( tmpray );
250       return;
251      }
252 
253    snprintf( tmpray, MAXDATASIZE, "privmsg %s :I know who %s is.", MSGTO, name );
254    send_irc_message( tmpray );
255 
256    return;
257 }
258 
259 
260 
261 /* returns a positive value if the user is found. */
262 
263 int valid_user( char *nickname )
264 {
265    char checklistname[USERINFO];
266 
267    lag = usr;
268    trv = usr->next;
269 
270    while( trv ){
271       chop( trv->data, checklistname, 0, ' ' );
272       if( strcmp( nickname, checklistname ) ) {
273          lag = trv;
274          trv = trv->next;
275          continue;
276         }
277       return 1;
278      }
279 
280    return 0;
281 }
282 
283 
284 /* returns true/false */
285 
286 int valid_password( char *passwd )
287 {
288    int x;
289    char checklistpword[MAXDATASIZE];
290    char salt[MAXDATASIZE];
291    char *hash;
292 
293    x = chop( trv->data, checklistpword, 0, ' ' );
294    x = chop( trv->data, checklistpword, x, ' ' ); /* this now holds the password in hashed form. */
295 
296    salt[0] = checklistpword[0]; /* the salt is held in the first two characters */
297    salt[1] = checklistpword[1];
298    salt[2] = '\0'; /* since this is address space on the stack, i will null terminate it explicitly */
299 
300    hash = crypt( passwd, salt );
301 
302    if( strcmp( hash, checklistpword ) ) return 0; /* passwd hashes don't match */
303    return 1;
304 }
305 
306 
307 /*this is basically a wrapper for the two functions that verify users. */
308 int valid_login( char *name, char *passwd )
309 {
310    int position = 0;
311 
312    if( !valid_user( name ) ) return 0;
313    position = valid_password( passwd );
314    return position;
315 }
316 
317 
318 
319 /* no comment right now. sorry. */
320 
321 void oppeople( char *chan, char *passwd, char *name, char *nick )
322 {
323    char sndmsg[MAXDATASIZE];
324 
325 
326    if( valid_login( name, passwd ) ){
327       snprintf( sndmsg, MAXDATASIZE, "mode %s +o %s", chan, nick );
328       send_irc_message( sndmsg );
329       return;
330      }
331 
332    snprintf( sndmsg, MAXDATASIZE, "privmsg %s :either your username or password is incorrect. channels require a #.",
	MSGTO );
333    send_irc_message( sndmsg );
334 
335    return;
336 }
337 
338 
339 
340 void get_salt( char *ray )
341 {
342 
343    long x;
344 
345    x = 1 + (rand() % 26);
346    x += 64;
347    *ray = (char)x;
348 
349    x = 1 + (rand() % 26);
350    x+= 64;
351    *(ray + 1) = (char)x;
352    *(ray + 2) = '\0';
353 
354    return;
355 }
5749369 [rkeene@sledge /home/rkeene/projects/ircbot/bot]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2003-12-11 08:06:35