*** ../ircu2.10.04/doc/Configure.help Tue Jun 16 16:55:00 1998 --- ../ircu2.10.04+/doc/Configure.help Tue Jun 16 16:57:56 1998 *************** *** 802,807 **** --- 802,814 ---- without being OP in that channel. He only need to include the "extended mode" (flag "x") in his mode command. + ESNET Distributed DataBase Support - ESNET + DB_ESNET + If you choose "yes", your server will can manage + ESNET Distributed DataBases. A "database" file will be + created in IRCd home directory to support nick + and channel registration, etc. + Allow local opers to use the REHASH command LOCOP_REHASH Allows a local operator (defined by a lowercase o:line in ircd.conf) *** ../ircu2.10.04/config/config-sh.in Tue Jun 16 17:00:02 1998 --- ../ircu2.10.04+/config/config-sh.in Tue Jun 16 17:00:26 1998 *************** *** 336,341 **** --- 336,342 ---- mainmenu_option next_comment comment 'Mandatory defines (you should leave these untouched)' bool 'XMODE Networking - ESNET' XMODE_ESNET y + bool 'ESNET Distributed DataBase Support - ESNET' DB_ESNET y bool 'Check for clones (y!)' CHECK_CLONE y if [ "$CHECK_CLONE" = "y" ]; then int 'Check clone limit (2!)' CHECK_CLONE_LIMIT 2 *** ../ircu2.10.04/include/msg.h Fri May 29 17:32:54 1998 --- ../ircu2.10.04+/include/msg.h Tue Jun 16 17:01:54 1998 *************** *** 40,45 **** --- 40,51 ---- /* *INDENT-OFF* */ + #ifdef DB_ESNET + #define MSG_DB "DB" /* Base de Datos ESNET */ + #define TOK_DB "DB" + #define CLASS_DB LEVEL_PROPAGATE + #endif + #define MSG_PRIVATE "PRIVMSG" /* PRIV */ #define TOK_PRIVATE "P" #define CLASS_PRIVATE LEVEL_PROPAGATE *** ../ircu2.10.04/include/s_serv.h Fri May 29 17:53:50 1998 --- ../ircu2.10.04+/include/s_serv.h Tue Jun 16 17:55:52 1998 *************** *** 60,63 **** --- 60,71 ---- extern int max_connection_count, max_client_count; + #ifdef DB_ESNET + extern void tea(unsigned long v[],unsigned long k[],unsigned long x[]); + extern void reload_db(void); + extern void initdb(void); + struct DB_nick *find_db_nick(char *nick); + extern int m_db(aClient *cptr, aClient *sptr, int parc, char *parv[]); + #endif + #endif /* S_SERV_H */ *** ../ircu2.10.04/include/numeric.h Mon Jun 15 18:56:28 1998 --- ../ircu2.10.04+/include/numeric.h Tue Jun 16 17:02:24 1998 *************** *** 69,74 **** --- 69,77 ---- #define ERR_NONICKNAMEGIVEN 431 #define ERR_ERRONEUSNICKNAME 432 #define ERR_NICKNAMEINUSE 433 + #ifdef DB_ESNET + #define ERR_NICKREGISTERED ERR_NICKNAMEINUSE + #endif #define ERR_NICKCOLLISION 436 #define ERR_BANNICKCHANGE 437 /* Undernet extension */ #define ERR_NICKTOOFAST 438 /* Undernet extension */ *** ../ircu2.10.04/include/s_user.h Tue Jun 16 10:53:03 1998 --- ../ircu2.10.04+/include/s_user.h Tue Jun 16 17:04:53 1998 *************** *** 67,72 **** --- 67,75 ---- extern void set_snomask(aClient *, snomask_t, int); extern int is_snomask(char *); extern int check_target_limit(aClient *sptr, void *target, const char *name); + #ifdef DB_ESNET + extern unsigned int base64toint(const char *str); + #endif extern const char *inttobase64(unsigned int i); #ifdef CHECK_CLONE extern int check_clones(aClient *cptr, const char *host); *** ../ircu2.10.04/ircd/ircd.c Tue Jun 16 17:06:53 1998 --- ../ircu2.10.04+/ircd/ircd.c Tue Jun 16 17:06:53 1998 *************** *** 790,795 **** --- 790,798 ---- initwhowas(); initmsgtree(); initstats(); + #ifdef DB_ESNET + initdb(); + #endif open_debugfile(); if (portnum < 0) portnum = PORTNUM; *** ../ircu2.10.04/ircd/parse.c Tue Jun 16 17:06:55 1998 --- ../ircu2.10.04+/ircd/parse.c Tue Jun 16 17:06:55 1998 *************** *** 120,125 **** --- 120,128 ---- #if defined(OPER_DIE) || defined(LOCOP_DIE) {CLASS_DIE, MSG_DIE, TOK_DIE, m_die, 0, MAXPARA, MFLG_SLOW, 0L}, #endif + #ifdef DB_ESNET + {CLASS_DB, MSG_DB, TOK_DB, m_db, 0, MAXPARA, MFLG_SLOW, 0L}, + #endif {0, (char *)0, (char *)0, (int (*)())0, 0, 0, 0, 0L} } ; /* *INDENT-ON* */ *** ../ircu2.10.04/ircd/s_debug.c Tue Jun 16 17:06:58 1998 --- ../ircu2.10.04+/ircd/s_debug.c Tue Jun 16 17:06:58 1998 *************** *** 196,201 **** --- 196,207 ---- '-', #endif #endif + 'D','B', + #ifdef DB_ESNET + '+', + #else + '-', + #endif '\0' }; *** ../ircu2.10.04/ircd/s_err.c Tue Jun 16 17:06:58 1998 --- ../ircu2.10.04+/ircd/s_err.c Tue Jun 16 17:06:58 1998 *************** *** 131,137 **** --- 131,142 ---- /* 432 */ {ERR_ERRONEUSNICKNAME, "%s :Erroneus Nickname"}, /* 433 */ + #ifdef DB_ESNET + {ERR_NICKNAMEINUSE, "%s :Nickname is already in use or registered " + "(missing or wrong password)"}, + #else {ERR_NICKNAMEINUSE, "%s :Nickname is already in use."}, + #endif /* 434 */ {0, (char *)NULL}, /* 435 */ *** ../ircu2.10.04/ircd/s_conf.c Tue Jun 16 17:47:02 1998 --- ../ircu2.10.04+/ircd/s_conf.c Tue Jun 16 17:56:13 1998 *************** *** 537,542 **** --- 537,546 ---- if (sig == 1) sendto_ops("Got signal SIGHUP, reloading ircd conf. file"); + #ifdef DB_ESNET + reload_db(); + #endif + for (i = 0; i <= highest_fd; i++) if ((acptr = loc_clients[i]) && !IsMe(acptr)) { *** ../ircu2.10.04/ircd/s_serv.c Tue Jun 16 17:07:00 1998 --- ../ircu2.10.04+/ircd/s_serv.c Tue Jun 16 18:26:49 1998 *************** *** 26,31 **** --- 26,37 ---- #endif #include "sys.h" #include + #ifdef DB_ESNET + #include + #include + #include + #include "common.h" + #endif #include "h.h" #include "struct.h" #include "ircd.h" *************** *** 709,714 **** --- 715,723 ---- cptr->serv->timestamp = timestamp; cptr->serv->prot = prot; cptr->serv->ghost = ghost; + #ifdef DB_ESNET + cptr->serv->esnet_db=0; /* De momento exigimos un BURST de la base de datos */ + #endif SetServerYXX(cptr, cptr, parv[6]); if (start_timestamp > 780000000) { *************** *** 1095,1097 **** --- 1104,1492 ---- } return 0; } + + #ifdef DB_ESNET + + /* + * TEA (cifrado) + * + * Cifra 64 bits de datos, usando clave de 64 bits (los 64 bits superiores son cero) + * Se cifra v[0]^x[0], v[1]^x[1], para poder hacer CBC facilmente. + * + */ + void tea(unsigned long v[],unsigned long k[],unsigned long x[]) + { + unsigned long y=v[0]^x[0],z=v[1]^x[1],sum=0,delta=0x9E3779B9; + unsigned long a=k[0],b=k[1],n=32; + unsigned long c=0,d=0; + + while(n-->0) + { + sum += delta; + y += (z << 4)+a ^ z+sum ^ (z >> 5)+b; + z += (y << 4)+c ^ y+sum ^ (y >> 5)+d; + } + + x[0]=y; x[1]=z; + } + + /* + * leer_db + * + * Lee un registro de la base de datos. Si hay error, cierra el handle. + * + */ + int leer_db(int handle,char *buf) + { + int cont=0; + int estado; + + do { + alarm(3); + estado=read(handle,buf,1); + alarm(0); + if(estado!=1) { + close(handle); + *buf='\0'; + return estado; + } + cont++; + } while((*buf++!='\n') && (cont<500)); + *(--buf)='\0'; + return cont; + } + + /* + * abrir_db + * + * Se mueve hasta un registro de la base de datos + * + */ + int abrir_db(unsigned long registro,char *buf) + { + int handle; + int cont; + + *buf='\0'; + alarm(3); + handle=open("database", O_RDONLY, S_IRUSR | S_IWUSR); + alarm(0); + if(handle==-1) return 0; + do { + cont=leer_db(handle,buf); + if(cont==-1) { + *buf='\0'; + return 0; + } + } while(atol(buf)<=registro); + return handle; + } + + /* + ** El 0 es nuestra base de datos local + ** El 1 son los registros que no son nuestros, para poder compactar luego la DB. + */ + static struct DB_nick *nick_db[2]={NULL,NULL}; + static unsigned long db_num_serie_local=0; + + /* + * db_manage_nick + * + * Escribe un registro nuevo, modifica uno existente o lo borra + * + */ + struct DB_nick *db_manage_nick(char *nick_,int offset,int borrar) + { + struct DB_nick *n,*n2=NULL; + char nick[512],*p=nick; + + while(*p++=tolower(*nick_++)); + + n=nick_db[offset]; + /* Busca el registro */ + while(n!=NULL) { + if(!strcmp(n->nick,nick)) break; + if(*(n->nick)=='\0') n2=n; + n=n->siguiente; + } + if(n!=NULL) { + memset(n->nick,0,sizeof(n->nick)); + if(borrar) return n; + strcpy(n->nick,nick); + return n; + } + if(borrar) return NULL; + + /* + ** No existe el registro. Busco un hueco o pido uno nuevo + */ + if(n2!=NULL) { + memset(n->nick,0,sizeof(n->nick)); + strcpy(n->nick,nick); + return n2; + } + n=(struct DB_nick *)RunMalloc(sizeof(struct DB_nick)); + if(n==NULL) { + sendto_ops("No hay memoria para un nuevo registro"); + return NULL; + } + memset(n,0,sizeof(struct DB_nick)); + strcpy(n->nick,nick); + n->siguiente=nick_db[offset]; + nick_db[offset]=n; + return n; + } + + /* + * db_alta + * + * Da de alta una entrada en la base de datos en memoria + * Formato "serie destino id clave contenido" + * + */ + void db_alta(char *registro) + { + char *p,*p2,*p3; + aClient *acptr; + int offset=0; + struct DB_nick *nick; + + p=strchr(registro,' '); + if(p==NULL) return; + p2=strchr(++p,' '); + if(p2==NULL) return; + db_num_serie_local=atol(registro); + + /* + * Guardamos en memoria AUNQUE no sea para nosotros, para poder hacer + * luego la compactacion de la base de datos. + * Si no es para nosotros, los ponemos en una cola aparte. + * + */ + *p2='\0'; + if(*p=='*') p=me.name; + acptr=find_match_server(p); + if((acptr==NULL) || !IsMe(acptr)) offset=1; + *p2++=' '; + p=strchr(p2,' '); + if(p==NULL) return; + p3=strchr(++p,' '); + if(p3!=NULL) *p3++='\0'; + + switch (*p2) { + case 'N': + if(p3==NULL) { /* Borrado */ + db_manage_nick(p,offset,!0); + return; + } + if(strlen(p3)<12) return; + nick=db_manage_nick(p,offset,0); + if(nick==NULL) return; + nick->clave[0]=base64toint(p3); + nick->clave[1]=base64toint(p3+6); + break; + } + + if(p3!=NULL) *(--p3)=' '; + return; + } + + /* + * initdb + * + * Lee la base de datos de disco + * + */ + void initdb(void) + { + char buf[1024]; + int handle; + + nick_db[0]=nick_db[1]=NULL; + if(!(handle=abrir_db(0,buf))) return; + do { + db_alta(buf); + } while(leer_db(handle,buf)!=-1); + return; + } + + /* + * reload_db + * + * Recarga la base de datos de disco, liberando la memoria + * + */ + void reload_db(void) + { + struct DB_nick *n,*n2; + + n=nick_db[0]; + while(n!=NULL) { + n2=n->siguiente; + RunFree(n); + n=n2; + } + + n=nick_db[1]; + while(n!=NULL) { + n2=n->siguiente; + RunFree(n); + n=n2; + } + + initdb(); + sendto_ops("Releyendo la base de datos. Ultimo registro: %lu",db_num_serie_local); + } + + /* + * find_db_nick + * + * Busca un nick en la base de datos + * + */ + struct DB_nick *find_db_nick(char *nick) + { + struct DB_nick *db_nick; + char n[512],*p=n; + + while(*p++=tolower(*nick++)); + + db_nick=nick_db[0]; + while(db_nick!=NULL) { + sendto_ops("Nick %s",db_nick->nick); + if(!strcmp(db_nick->nick,n)) break; + db_nick=db_nick->siguiente; + } + return db_nick; + } + + /* + * m_db + * + * Gestion de la base de datos - ESNET + * 29/May/98 jcea@argo.es + * + */ + int m_db(aClient *cptr, aClient *sptr, int parc, char *parv[]) + { + unsigned long db; + aClient *acptr; + Dlink *lp; + char db_buf[1024]; + int db_file; + + if(!IsServer(sptr) || parc<5) return 0; + db=atol(parv[2]); + if(!db) { + db=atol(parv[4]); + switch(*parv[3]) { + case 'B': + sendto_one(sptr,"%c DB %s 0 J %lu",me.yxx[0],parv[0],db_num_serie_local); + return 0; + break; + + case 'J': + { + char *p,*p2; + int cont=100; + + if(db>=db_num_serie_local) { /* Se le pueden mandar registros individuales */ + sptr->serv->esnet_db=!0; + return 0; + break; + } + db_file=abrir_db(db,db_buf); + if(db_file==0) return 0; /* Problemas con la DB */ + do { + p=strchr(db_buf,' '); + if(p==NULL) return 0; + *p++='\0'; + p2=strchr(p,' '); + if(p2==NULL) return 0; + *p2++='\0'; + sendto_one(sptr,"%c DB %s %s %s",me.yxx[0],p,db_buf,p2); + if(!(--cont)) break; + } while(leer_db(db_file,db_buf)!=-1); + close(db_file); + sendto_one(sptr,"%c DB %s 0 B %lu",me.yxx[0],parv[0],db_num_serie_local); + if(cont) sptr->serv->esnet_db=!0; + return 0; + break; + } + + case 'q': + if((acptr=find_match_server(parv[1]))&&(!IsMe(acptr))) + sendto_one(acptr,"%c DB %s 0 q %lu %s",NumServ(sptr), + acptr->name,db,parv[5]); + return 0; + break; + + case 'Q': + if(!(acptr = find_match_server(parv[1]))) { + sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], parv[1]); + return 0; + } + + if(!IsMe(acptr)) { + sendto_one(acptr,"%c DB %s 0 Q %lu\n",NumServ(sptr),acptr->name,db); + return 0; + } + if(dbdown; lp; lp = lp->next) + { + if(!(lp->value.cptr->serv->esnet_db) || (lp->value.cptr==cptr)) continue; + sendto_one(lp->value.cptr,db_buf); + } + + db_num_serie_local=db; + + alarm(3); + db_file=open("database",O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); + alarm(0); + + if(parc==5) + sprintf_irc(db_buf,"%lu %s %s %s\n",db,parv[1],parv[3],parv[4]); + else + sprintf_irc(db_buf,"%lu %s %s %s %s\n",db,parv[1],parv[3],parv[4],parv[5]); + + alarm(3); + write(db_file,db_buf,strlen(db_buf)); + alarm(0); + + close(db_file); + + return 0; + } + + #endif /* Base de Datos ESNET */ *** ../ircu2.10.04/include/struct.h Tue Jun 16 17:07:01 1998 --- ../ircu2.10.04+/include/struct.h Mon Jun 15 19:27:55 1998 *************** *** 134,139 **** --- 134,140 ---- u_short nn_mask; /* [Remote] FD_SETSIZE - 1 */ u_char last_x1; u_char last_x2; + u_char esnet_db; /* !0 = La DB se puede transferir directamente, sin burst */ #ifdef LIST_DEBUG struct Client *bcptr; #endif *************** *** 154,159 **** --- 155,166 ---- #ifdef LIST_DEBUG struct Client *bcptr; #endif + }; + + struct DB_nick { + char nick[8*((NICKLEN+8)/8)]; /* El +8 es para que siempre sea multiplo entero de 8 */ + unsigned long clave[2]; + struct DB_nick *siguiente; }; #endif /* STRUCT_H */ *** ../ircu2.10.04/ircd/s_user.c Tue Jun 16 17:07:00 1998 --- ../ircu2.10.04+/ircd/s_user.c Tue Jun 16 17:07:00 1998 *************** *** 848,854 **** /* *INDENT-ON* */ ! static unsigned int base64toint(const char *str) { register unsigned int i; i = convert2n[(unsigned char)str[5]]; --- 848,854 ---- /* *INDENT-ON* */ ! unsigned int base64toint(const char *str) { register unsigned int i; i = convert2n[(unsigned char)str[5]]; *************** *** 878,883 **** --- 878,884 ---- * * parv[0] = sender prefix * parv[1] = nickname + * parv[2] = clave (opcional) * * If from server: * parv[2] = hopcount *************** *** 893,898 **** --- 894,902 ---- */ int m_nick(aClient *cptr, aClient *sptr, int parc, char *parv[]) { + #ifdef DB_ESNET + struct DB_nick *nick_db=NULL; + #endif aClient *acptr, *server = NULL; char nick[NICKLEN + 2], *s; Link *lp; *************** *** 1003,1008 **** --- 1007,1016 ---- return exit_client(cptr, sptr, &me, "Nick/Server collision"); } + #ifdef DB_ESNET + if(!IsServer(cptr)) nick_db=find_db_nick(nick); + #endif + if (!(acptr = find_client(nick, NULL))) goto nickkilldone; /* No collisions, all clear... */ /* *************** *** 1169,1174 **** --- 1177,1219 ---- return 0; nickkilldone: + + #ifdef DB_ESNET + /* + * Comprueba si el nick esta registrado, y si lo esta que se ponga la clave correcta + * + */ + if(nick_db) { /* El nick indicado esta registrado */ + unsigned long v[2],k[2],x[2]; + int cont=(NICKLEN+8)/8; + unsigned long *p=(unsigned long *)nick_db->nick; + + k[0]=k[1]=x[0]=x[1]=0; + if((parc>=3) && (strlen(parv[2])>=12)) { + k[0]=base64toint(parv[2]); + k[1]=base64toint(parv[2]+6); + } else { + k[0]=base64toint(cptr->passwd); + k[1]=base64toint(cptr->passwd+6); + } + while(cont--) { + v[0]=ntohl(*p++); + v[1]=ntohl(*p++); + tea(v,k,x); + } + + parc=3; /* Chanchullo !!OJO!! */ + + if(x[0]!=nick_db->clave[0] || x[1]!=nick_db->clave[1]) parc=0; + + if(parc<3) { + sendto_one(cptr,err_str(ERR_NICKREGISTERED), + me.name,parv[0],nick); + return 0; + } + } + #endif + if (IsServer(sptr)) { int flag, *s;