diff --git a/Makefile b/Makefile index 8c77001..27dc03e 100644 --- a/Makefile +++ b/Makefile @@ -39,13 +39,13 @@ DEFINES= OBJECTS = bans.o buffer.o channels.o chat.o conf.o connect.o dbio.o debug.o \ defchan.o events.o floodpro.o help.o http.o ignore.o kicks.o \ - match.o modes.o nick.o opcom.o ops.o patch.o privmsg.o \ + match.o modes.o nick.o nickserv.o opcom.o ops.o patch.o privmsg.o \ replies.o servers.o shitlist.o socketio.o special.o userlist.o \ users.o version.o SOURCES = bans.c buffer.c channels.c chat.c conf.c connect.c dbio.c debug.c \ defchan.c events.c floodpro.c help.c http.c ignore.c kicks.c \ - match.c modes.c nick.c opcom.c ops.c patch.c privmsg.c \ + match.c modes.c nick.c nickserv.c opcom.c ops.c patch.c privmsg.c \ replies.c servers.c shitlist.c socketio.c special.c userlist.c \ users.c version.c diff --git a/Sources/nickserv.c b/Sources/nickserv.c new file mode 100644 index 0000000..8a5c6cc --- /dev/null +++ b/Sources/nickserv.c @@ -0,0 +1,864 @@ +/* @(#)$Id: nickserv.c,v 1.7 1997/07/18 21:52:38 cvs Exp $ */ + +/* Undernet Channel Service (X) + * Copyright (C) 1995-2002 Robin Thellend + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * The author can be contact by email at + * + * Please note that this software is unsupported and mostly + * obsolete. It was replaced by GNUworld/CMaster. See + * http://gnuworld.sourceforge.net/ for more information. + */ + +#include "h.h" + +#ifdef NICKSERV + +#define NSERV_HASH 100 +#define NSERV_FILE "nickserv.dat" + +static struct aregnick *NServ_DB [NSERV_HASH]; + +static void nserv_notice(char *nick, char *msg) +{ + char buffer[1024]; + + sprintf(buffer,":%s NOTICE %s :%s\r\n",NSERV_NICK,nick,msg); + sendtoserv(buffer); +} + +static int nserv_hash(char *nick) +{ + register int i,j=0; + + for(i=0; nick[i] != '\0'; i++) + { + j += (unsigned char) toupper(nick[i]); + } + + return j % NSERV_HASH; +} + + +static struct aregnick *nserv_find(char *nick) +{ + register struct aregnick *scan; + + scan = NServ_DB [ nserv_hash(nick) ]; + + while(scan != NULL && strcmp(scan->nick,nick)) + scan = scan->next; + + return scan; +} + +static struct aregnick **nserv_find_ptr(char *nick) +{ + register struct aregnick **scan; + + scan = & NServ_DB [ nserv_hash(nick) ]; + + while(*scan != NULL && strcmp((*scan)->nick,nick)) + scan = &(*scan)->next; + + return scan; +} + + +void nserv_nickserv(char *source, char *args) +{ + register aluser *luser; + char buffer[512]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_nickserv() can't locate user!"); + return; + } + + if(!(luser->mode&LFL_ISOPER)) + { + notice(source,"Cette commande est réservée aux IRC Opérateurs"); + return; + } + + if(!strcmp(args,"on")) + { + if(NServ_status == 1) + { + sprintf(buffer,"%s est déjà actif!",NSERV_NICK); + notice(source,buffer); + } + else + { + IntroduceNickserv(); + sprintf(buffer,"%s est maintenant actif!",NSERV_NICK); + notice(source,buffer); + } + } + else if(!strcmp(args,"off")) + { + sprintf(buffer,"Désactivé par %s",source); + KillNickserv(buffer); + sprintf(buffer,"%s est maintenant désactivé!",NSERV_NICK); + notice(source,buffer); + } + else + { + notice(source,"SYNTAXE: nickserv "); + } +} + + +void nserv_addnick(char *source, char *args) +{ + register aluser *luser; + register struct aregnick *reg; + char buffer[512], nick[80], password[80], mask[80], email[80]; + int idx; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_addnick() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + if(!(luser->mode&LFL_ISOPER)) + { + nserv_notice(source,"Cette commande est réservée aux IRC Opérateurs"); + return; + } + + GetWord(0,args,nick); + GetWord(1,args,mask); + GetWord(2,args,password); + GetWord(3,args,email); + + if(!*nick || !*mask || !*password) + { + nserv_notice(source,"SYNTAXE: addnick [e-mail]"); + return; + } + + nick[9] = '\0'; + password[19] = '\0'; + + if((reg=nserv_find(nick)) != NULL) + { + sprintf(buffer,"Le nick \"%s\" est déjà enregistré",nick); + nserv_notice(source,buffer); + return; + } + + reg = (struct aregnick *) malloc(sizeof(struct aregnick)); + memset(reg,0,sizeof(struct aregnick)); + + strcpy(reg->nick, nick); + strcpy(reg->password, password); + strcpy(reg->email, email); + reg->created = now; + reg->modified = now; + + reg->mask = (struct aregmask *) malloc(sizeof(struct aregmask)); + strcpy(reg->mask->mask, mask); + reg->mask->lastused = (time_t) 0; + reg->mask->next = NULL; + + idx = nserv_hash(nick); + reg->next = NServ_DB[idx]; + NServ_DB[idx] = reg; + + reg->ref = 1; + + sprintf(buffer,"Nick %s (%s) ajouté",nick,mask); + nserv_notice(source,buffer); +} + + + +void nserv_addmask(char *source, char *args) +{ + register aluser *luser; + register struct aregnick *reg; + register struct aregmask *rmask; + char buffer[512], nick[80], mask[80]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_addnick() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + if(!(luser->mode&LFL_ISOPER)) + { + nserv_notice(source,"Cette commande est réservée aux IRC Opérateurs"); + return; + } + + + GetWord(0,args,nick); + GetWord(1,args,mask); + + if(!*nick || !*mask) + { + nserv_notice(source,"SYNTAXE: addmask "); + return; + } + + nick[9] = '\0'; + + if((reg=nserv_find(nick)) == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas enregistré",nick); + nserv_notice(source,buffer); + return; + } + + reg->modified = now; + + rmask = (struct aregmask *) malloc(sizeof(struct aregmask)); + memset(rmask,0,sizeof(struct aregmask)); + + strcpy(rmask->mask, mask); + rmask->lastused = (time_t) 0; + rmask->next = reg->mask; + reg->mask = rmask; + + sprintf(buffer,"Mask %s ajouté a %s",mask,nick); + nserv_notice(source,buffer); +} + + + +void nserv_remnick(char *source, char *args) +{ + register aluser *luser; + register struct aregnick **reg, *tmpreg; + register struct aregmask *rmask; + char buffer[512], nick[80]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_addnick() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + if(!(luser->mode&LFL_ISOPER)) + { + nserv_notice(source,"Cette commande est réservée aux IRC Opérateurs"); + return; + } + + + GetWord(0,args,nick); + + if(!*nick) + { + nserv_notice(source,"SYNTAXE: remnick "); + return; + } + + nick[9] = '\0'; + + if( *(reg=nserv_find_ptr(nick)) == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas enregistré",nick); + nserv_notice(source,buffer); + return; + } + + tmpreg = *reg; + *reg = tmpreg->next; + + tmpreg->next = NULL; + tmpreg->ref--; + + if(tmpreg->ref == 0) + { + while((rmask=tmpreg->mask) != NULL) + { + tmpreg->mask = rmask->next; + free(rmask); + } + free(tmpreg); + } + + sprintf(buffer,"Nick %s effacé",nick); + nserv_notice(source,buffer); +} + + +void nserv_remmask(char *source, char *args) +{ + register aluser *luser; + register struct aregnick *reg; + register struct aregmask **rmask, *tmprmask; + char buffer[512], nick[80], mask[80]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_addnick() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + if(!(luser->mode&LFL_ISOPER)) + { + nserv_notice(source,"Cette commande est réservée aux IRC Opérateurs"); + return; + } + + + GetWord(0,args,nick); + GetWord(1,args,mask); + + if(!*nick || !*mask) + { + nserv_notice(source,"SYNTAXE: remmask "); + return; + } + + nick[9] = '\0'; + + if((reg=nserv_find(nick)) == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas enregistré",nick); + nserv_notice(source,buffer); + return; + } + + reg->modified = now; + + rmask = & reg->mask; + + while(*rmask != NULL && strcmp((*rmask)->mask, mask)) + rmask = &(*rmask)->next; + + if(*rmask == NULL) + { + sprintf(buffer,"%s n'as pas de mask %s",nick,mask); + nserv_notice(source,buffer); + return; + } + + tmprmask = *rmask; + *rmask = tmprmask->next; + + free(tmprmask); + + sprintf(buffer,"Mask %s enlevé de %s",mask,nick); + nserv_notice(source,buffer); +} + + + +void nserv_nickinfo(char *source, char *args) +{ + register aluser *luser; + register struct aregnick *reg; + register struct aregmask *rmask; + char buffer[512], nick[80]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_addnick() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + GetWord(0,args,nick); + + if(!*nick) + { + nserv_notice(source,"SYNTAXE: nickinfo "); + return; + } + + nick[9] = '\0'; + + if((reg=nserv_find(nick)) == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas enregistré",nick); + nserv_notice(source,buffer); + return; + } + + sprintf(buffer,"Nick: %s",reg->nick); + nserv_notice(source,buffer); + sprintf(buffer,"Création: %.24s",ctime(®->created)); + nserv_notice(source,buffer); + sprintf(buffer,"Modification: %.24s",ctime(®->modified)); + nserv_notice(source,buffer); + + if((!strcmp(source,reg->nick) && luser->regnick && luser->reglimit == 0) + || (luser->mode&LFL_ISOPER)) + { + sprintf(buffer,"Mot de passe: %s",reg->password); + nserv_notice(source,buffer); + + sprintf(buffer,"E-mail: %s",reg->email); + nserv_notice(source,buffer); + } + + for(rmask = reg->mask; rmask != NULL; rmask = rmask->next) + { + if(rmask->lastused == (time_t) 0) + sprintf(buffer,"Mask: %s (jamais utilisé)",rmask->mask); + else + sprintf(buffer,"Mask: %s %.24s",rmask->mask, ctime(&rmask->lastused)); + nserv_notice(source,buffer); + } +} + + +void nserv_identify(char *source, char *args) +{ + register aluser *luser; + register struct aregmask *rmask; + char buffer[512], password[80]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_identify() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + GetWord(0,args,password); + + if(!*password) + { + nserv_notice(source,"SYNTAXE: identify "); + return; + } + + if(luser->regnick == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas enregistré",source); + nserv_notice(source,buffer); + return; + } + + if(luser->reglimit == 0) + { + nserv_notice(source,"Vous vous êtes déjà identifié"); + return; + } + + sprintf(buffer,"%s!%s@%s",luser->nick,luser->username,luser->site); + + rmask = luser->regnick->mask; + while(rmask != NULL && !match(buffer,rmask->mask)) + rmask = rmask->next; + + if(rmask && !strcmp(password,luser->regnick->password)) + { + luser->reglimit = 0; + rmask->lastused = now; + nserv_notice(source,"Mot de passe accepté. Bienvenue!"); + } + else + { + nserv_notice(source,"Le mot de passe est \002incorrect!\002"); + } +} + + +void nserv_ghost(char *source, char *args) +{ + register aluser *luser, *luser2; + register struct aregnick *reg; + register struct aregmask *rmask; + char buffer[512], nick[80], password[80]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_ghost() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + GetWord(0,args,nick); + GetWord(1,args,password); + + if(!*nick || !*password) + { + nserv_notice(source,"SYNTAXE: ghost "); + return; + } + + if(!strcmp(nick,source)) + { + nserv_notice(source,"Ah oui? Vous n'avez pas l'air d'un ghost!"); + return; + } + + luser2 = ToLuser(nick); + + if(luser2 == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas utilisé présentement",nick); + nserv_notice(source,buffer); + return; + } + + reg = nserv_find(nick); + + if(reg == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas enregistré",nick); + nserv_notice(source,buffer); + return; + } + + sprintf(buffer,"%s!%s@%s",luser->nick,luser->username,luser->site); + + rmask = reg->mask; + while(rmask != NULL && !match(buffer,rmask->mask)) + rmask = rmask->next; + + if(rmask && !strcmp(password,luser->regnick->password)) + { + sprintf(buffer, ":%s KILL %s :%s (Ghost kill demandé par %s)\r\n", + NSERV_NICK, nick, NSERV_NICK, source); + sendtoserv(buffer); + onquit(nick); + + sprintf(buffer,"Le ghost \"%s\" a été killé",nick); + nserv_notice(source,buffer); + } + else + { + nserv_notice(source,"Le mot de passe est \002incorrect!\002"); + } +} + + +void nserv_nicknewpass(char *source, char *args) +{ + register aluser *luser; + register struct aregnick *reg; + char buffer[512], nick[80], password[80]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_nicknewpass() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + GetWord(0,args,nick); + GetWord(1,args,password); + + if(!*nick && !*password) + { + nserv_notice(source,"SYNTAXE: nicknewpass [nick] "); + return; + } + + if(!*password) + { + strcpy(password,nick); + strcpy(nick,source); + } + + if(strcmp(nick,source) && !(luser->mode&LFL_ISOPER)) + { + nserv_notice(source,"Vous n'avez pas le droit de changer le mot de passe de quelqu'un d'autre"); + return; + } + + if(!(luser->mode&LFL_ISOPER) && (luser->regnick == NULL || + luser->reglimit != 0)) + { + nserv_notice(source,"Vous devez d'abord vous identifier"); + return; + } + + if((luser->mode&LFL_ISOPER)) + { + reg = nserv_find(nick); + } + else + { + reg = luser->regnick; + } + + if(reg == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas enregistré",nick); + nserv_notice(source,buffer); + return; + } + + password[19] = '\0'; + + strcpy(reg->password,password); + + sprintf(buffer,"Le nouveau mot de passe pour %s est %s", + reg->nick,reg->password); + nserv_notice(source,buffer); +} + + +void nserv_nicknewemail(char *source, char *args) +{ + register aluser *luser; + register struct aregnick *reg; + char buffer[512], nick[80], email[80]; + + if((luser=ToLuser(source))==NULL) + { + log("ERROR: nserv_nicknewemail() can't locate user!"); + return; + } + + if(NServ_status != 1) + { + notice(source,"NickServ n'est pas actif!"); + return; + } + + GetWord(0,args,nick); + GetWord(1,args,email); + + if(!*nick || !*email) + { + nserv_notice(source,"SYNTAXE: nicknewemail "); + return; + } + + if(!(luser->mode&LFL_ISOPER)) + { + nserv_notice(source,"Cette commande est réservée aux IRC Opérateurs"); + return; + } + + reg = nserv_find(nick); + if(reg == NULL) + { + sprintf(buffer,"Le nick \"%s\" n'est pas enregistré",nick); + nserv_notice(source,buffer); + return; + } + + strcpy(reg->email,email); + + sprintf(buffer,"Le nouveau e-mail pour %s est %s",reg->nick,reg->email); + nserv_notice(source,buffer); +} + + +void nserv_save(void) +{ + register struct aregnick *reg; + register struct aregmask *mask; + register int i; + FILE *fp; + + fp = fopen(NSERV_FILE".new","w"); + if(fp == NULL) + return; + + for(i=0; inext) + { + fwrite(reg, sizeof(struct aregnick), 1, fp); + + for(mask=reg->mask; mask != NULL; mask=mask->next) + fwrite(mask, sizeof(struct aregmask), 1, fp); + } + } + + fclose(fp); + + rename(NSERV_FILE".new", NSERV_FILE); +} + + +void nserv_load(void) +{ + struct aregnick reg; + struct aregmask mask; + register struct aregnick *treg; + register struct aregmask *tmask; + FILE *fp; + + fp = fopen(NSERV_FILE,"r"); + if(fp == NULL) + return; + + while(fread(®, sizeof(struct aregnick), 1, fp) != 0) + { + treg = (struct aregnick *) malloc (sizeof(struct aregnick)); + memcpy(treg, ®, sizeof(struct aregnick)); + treg->next = NULL; + if(treg->mask != NULL) + { + treg->mask = NULL; + while(fread(&mask, sizeof(struct aregmask), 1, fp) != 0) + { + int end = 0; + tmask = (struct aregmask *) malloc (sizeof(struct aregmask)); + memcpy(tmask, &mask, sizeof(struct aregmask)); + if(tmask->next == NULL) + end = 1; + tmask->next = treg->mask; + treg->mask = tmask; + if(end) + break; + } + } + treg->next = NServ_DB[nserv_hash(treg->nick)]; + NServ_DB[nserv_hash(treg->nick)] = treg; + } + + fclose(fp); +} + +void nserv_checkregnick(char *nick) +{ + register aluser *luser; + char buffer[512]; + + if(NServ_status != 1) + return; + + luser = ToLuser(nick); + if(luser == NULL || luser->regnick == NULL || luser->reglimit == 0 || + luser->reglimit > now) + return; + + /* timeout for receiving valid password has expired */ + nserv_notice(nick,"Vous ne vous êtes pas identifié. Vous devez partir!"); + /*sprintf(buffer,":%s KILL %s :NickServ (Non vérifié)\r\n",mynick,nick); + sendtoserv(buffer);*/ + sprintf(buffer, + ":%s GLINE + +%s@%s %d :Échec de l'identification pour le nick %s. " + "Accès non autorisé au serveur pendant %d secondes.\r\n", + mynick,luser->username,luser->site,NSERV_GLINETIME,nick, + NSERV_GLINETIME); + sendtoserv(buffer); + onquit(nick); +} + +void nserv_quit(aluser *user) +{ + if(user->regnick) + { + user->regnick->ref--; + + if(user->regnick->ref == 0) + { + register struct aregmask *rmask; + while((rmask=user->regnick->mask) != NULL) + { + user->regnick->mask = rmask->next; + free(rmask); + } + free(user->regnick); + } + + user->regnick = NULL; + } +} + +void nserv_nick(char *newnick, aluser *user) +{ + char buffer[200]; + + nserv_quit(user); + + if(NServ_status != 1) + { + return; + } + + user->regnick = nserv_find(newnick); + + if(user->regnick) + { + user->regnick->ref++; + user->reglimit = now + NSERV_DELAY; + sprintf(buffer,"Ce nick est enregistré. Vous avez 60 secondes pour vous identifier avec la commande \"/msg %s identify mot_de_passe\"",NSERV_NICK); + nserv_notice(newnick,buffer); + AddEvent(EVENT_CHECKREGNICK,user->reglimit,newnick); + } +} + + +void nserv_onop(char *channel, auser *user) +{ + if(user == NULL) /* NULL if X is opped */ + return; + + if(NServ_status != 1) + return; + + if(user->N->regnick == NULL) + { + nserv_notice(user->N->nick,"Vous ne pouvez pas être op sans être enregistré"); + changemode(channel,"-o",user->N->nick,1); + user->chanop = 0; + } +} + +#endif /* NICKSERV */ diff --git a/Sources/nickserv.h b/Sources/nickserv.h new file mode 100644 index 0000000..6501b2a --- /dev/null +++ b/Sources/nickserv.h @@ -0,0 +1,47 @@ +/* @(#)$Id: nickserv.h,v 1.2 1997/07/18 07:55:05 cvs Exp $ */ + +/* Undernet Channel Service (X) + * Copyright (C) 1995-2002 Robin Thellend + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * The author can be contact by email at + * + * Please note that this software is unsupported and mostly + * obsolete. It was replaced by GNUworld/CMaster. See + * http://gnuworld.sourceforge.net/ for more information. + */ + +#define NSERV_DELAY 60 +#define NSERV_SAVE_FREQ 3600 +#define NSERV_GLINETIME 60 + +struct aregmask { + char mask[80]; + time_t lastused; + struct aregmask *next; +}; + +struct aregnick { + char nick[10]; + char password[20]; + char email[80]; + int ref; + time_t created; + time_t modified; + struct aregmask *mask; + struct aregnick *next; +}; + diff --git a/config.h.dist b/config.h.dist index 079e45a..1cb9220 100644 --- a/config.h.dist +++ b/config.h.dist @@ -302,3 +302,18 @@ extern char CALMDOWNTOPIC[512]; #endif +#undef NICKSERV + +#ifdef NICKSERV +#ifdef MAIN +char NSERV_NICK[10] = "NickServ"; +char NSERV_USER[10] = "nickserv"; +char NSERV_HOST[80] = "undernet.org"; +char NSERV_INFO[200] = "Nickname registration service"; +#else +extern char NSERV_NICK[10]; +extern char NSERV_USER[10]; +extern char NSERV_HOST[80]; +extern char NSERV_INFO[200]; +#endif +#endif diff --git a/cs.conf.dist b/cs.conf.dist index d9bf1d7..0d6b326 100644 --- a/cs.conf.dist +++ b/cs.conf.dist @@ -59,4 +59,11 @@ UWORLD2_SERVER Uworld2.undernet.org # CALMDOWNTOPIC CALMDOWN was used on this channel # +# +NSERV_STAT ON +NSERV_NICK NickServ +NSERV_USER nickserv +NSERV_HOST undernet.org +NSERV_INFO Nickname registration service +# # End of configuration file