/********************************************************/ /* aprelay.c v1.2 */ /* P.Toilon (zorthrax@id-net.fr) */ /* 29/10/1998 IDNET - Nancy - FRANCE */ /* This relay is released into the Public Domain */ /* The original file 'aprelay.c' has 8141 bytes */ /********************************************************/ /* ** This relay is made for Apirc v1.1 ** IT WILL NOT WORK ON PREVIOUS VERSIONS */ #include #include #include #include #include /* Change it to #undef UNIX if under Windows */ #define UNIX /* Max simultaneous users on the relay */ #define MAXUSERS 128 /* Local listener socket timeout in seconds */ #define LCTIMEOUT 120 /* Max length of negociation frame before connecting to remote */ #define MAXFRAME 128 /* Max length of each frame's field */ #define MAXSE (MAXFRAME/2) /* ** Change CLASSIDENT to #define if : ** 1 - You want to have each user with a different username to ** avoid K-line on some servers. ** 2 - #define UNIX is set (and you are running a Unix/Linux OS) ** 3 - You can have root access and can set the aprelay file uid bit to root ** (under root, after each compilation, do a 'chmod u+s aprelay') ** On Windows OSes, you can run apidentd for this. */ #ifdef UNIX #define CLASSIDENT #endif /* ** If CLASSIDENT is defined (see above), we set a range of UIDs ** that begin at FIRSTUID. For example if FIRSTUID = 3000 and ** MAXUSERS = 16, users will have 3000@yourmachine.com, 3001@ ** yourmachine.com and so on until 3015. ** ** As numbers could not be appreciated by some ircops, it's ** probably better to add corresponding login entries in ** /etc/passwd to get real names. ** ** E.g.: Still with MAXUSERS = 16 and FIRSTUID = 3000, you ** should have to add 16 users on your system, from ** apircuser1 to apircuser16 with UIDs from 3000 to 3015 ** (Full Name: "Untrusted chat user"). ** ** On RedHat 5.0 you should make : adduser -u 3000 apircuser1 ** On Slackware, run adduser and follow the instructions. ** Do not edit directly /etc/passwd if shadow passwords are used. ** ** Users will have apircuser1@yourmachine.com for example. ** If user addresses still remain with UID numbers, verify that ** the auth port 113 (identd) is reachable from outside. */ #ifdef CLASSIDENT #define FIRSTUID 3000 #define LASTUID (MAXUSERS+FIRSTUID-1) #endif struct usr { int fd; int fdo; } usr[MAXUSERS]; fd_set rfds,fds; long uip[MAXUSERS]; struct sockaddr_in uin; short eoframe[MAXUSERS]; int FIRST,mfd,maxfd,osz; char hname[MAXUSERS][MAXFRAME]; char cnick[MAXSE],cserv[MAXSE],cport[MAXSE]; char oc[BUFSIZ],*arg,*strchr(),*inet_ntoa(),tmp[BUFSIZ]; int open_remote_server_socket(server,port) char *server; int port; { int fd; struct hostent *rmt; struct sockaddr_in out; if((fd=socket(AF_INET,SOCK_STREAM,0))<0) return(-1); if(!(rmt=gethostbyname(server))) { close(fd); return(-1); } memcpy(&out.sin_addr,rmt->h_addr,rmt->h_length); out.sin_family=AF_INET; out.sin_port=htons(port); if(connect(fd,(struct sockaddr *)&out,sizeof out)<0) { close(fd); return(-1); } return(fd); } int open_listener_socket(port,maxusers,timeout) int port,maxusers,timeout; { time_t tvey; struct sockaddr_in in; int fd,rt,sz=sizeof(struct sockaddr_in); if((fd=socket(AF_INET,SOCK_STREAM,0))<0) return(-1); memset(&in,0,sz); in.sin_family=AF_INET; in.sin_addr.s_addr=INADDR_ANY; in.sin_port=htons(port); time(&tvey); while((rt=bind(fd,(struct sockaddr *)&in,sz))<0 && (time(0l)-tvey)j) j=usr[i].fd; if(usr[i].fdo>j) j=usr[i].fdo; } if(fd>j) j=fd; return(j); } /* ** accept sent a broken pipe (signal 13) ** We go back into accept_user() */ void b_accept() { FIRST=0; accept_user(); } accept_user() { char *pt1,*pt2; struct hostent *ht; int i,j,si[4],newfd; /* ** To avoid the accept() brokenpipe */ signal(13,b_accept); if(FIRST) { for(i=0;i=0) { /* ** IP Filtering. E.g: 'arg="192.168";' will ** forbid all 192.168.x.x IP addresses. */ //arg="192.168.0.43"; if(arg && !strncmp(arg,inet_ntoa(uin.sin_addr.s_addr),strlen(arg))) { sd(newfd,"Sorry, your host is not allowed !\n\r"); close(newfd); } else if((i=getnewusernum())==-1) { sd(newfd,"Sorry, all relay sockets are busy !\n\r"); close(newfd); } else { usr[i].fd=newfd; usr[i].fdo=-1; eoframe[i]=0; sd(usr[i].fd,"Apirc relay v1.2\r\n\n"); if(!(ht=gethostbyaddr((char *)&uin.sin_addr,sizeof(unsigned long),AF_INET))) strcpy(hname[i],inet_ntoa(uin.sin_addr.s_addr)); else strcpy(hname[i],ht->h_name); FD_SET(usr[i].fd,&fds); maxfd=getmaxfdvalue(mfd); } } } else for(i=0;i=MAXFRAME) { FD_CLR(usr[i].fd,&fds); close(usr[i].fd); usr[i].fd=-1; maxfd=getmaxfdvalue(mfd); } else if(j>4 && strchr(oc,'§')) /* "MyNick:irc.id-net.fr:6667:§" */ { pt1=oc; *(pt2=strchr(pt1,':'))='\0'; strcpy(cnick,pt1); pt1=pt2+1; *(pt2=strchr(pt1,':'))='\0'; strcpy(cserv,pt1); pt1=pt2+1; *(pt2=strchr(pt1,':'))='\0'; strcpy(cport,pt1); eoframe[i]=1; } } else /* We just received the complete frame, let's connect */ { #ifdef CLASSIDENT setreuid(FIRSTUID+i,NULL); #endif if((usr[i].fdo=open_remote_server_socket(cserv,atoi(cport)))<0) { sd(usr[i].fd,"Server unavailable\r\n"); FD_CLR(usr[i].fd,&fds); /* On libere */ close(usr[i].fd); usr[i].fd=-1; maxfd=getmaxfdvalue(mfd); } else { FD_SET(usr[i].fdo,&fds); maxfd=getmaxfdvalue(mfd); srand(time(0l)); sprintf(tmp,"NICK %s\nUSER user%d host server :%s [Real user host]\n",cnick,rand()%9000+1000,hname[i]); sd(usr[i].fdo,tmp); send(usr[i].fdo,oc,j,0); /* 1st datas sent to th server */ } } } if(usr[i].fdo!=-1 && FD_ISSET(usr[i].fdo,&rfds)) { if(!(j=recv(usr[i].fdo,oc,BUFSIZ,0))) /* If disconnected */ { FD_CLR(usr[i].fd,&fds); FD_CLR(usr[i].fdo,&fds); close(usr[i].fd); close(usr[i].fdo); usr[i].fd=-1; usr[i].fdo=-1; maxfd=getmaxfdvalue(mfd); } else send(usr[i].fd,oc,j,0); } } } } main(argc,argv) int argc; char **argv; { arg=(argc==2)?argv[1]:NULL; #ifdef CLASSIDENT if(getuid() && setuid(NULL)==-1) { printf("\nYou must set the binary file uid bit to root. Daemon not ready\n"); exit(); } #endif printf("Trying to open the listener socket ... "); fflush(stdout); if((mfd=open_listener_socket(8888,MAXUSERS,LCTIMEOUT))<0) { printf("\nSocket not openable. Daemon not ready\n"); exit(); } printf("\nListener socket ready\n"); fflush(stdout); #ifdef UNIX if(fork()) exit(); #endif osz=sizeof(struct sockaddr_in); FIRST=1; accept_user(); }