Created
June 19, 2010 21:21
-
-
Save Estella/445289 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* [ ORIGNICK: irc bot -- version X+final+++. ] ****************************** | |
* irc bot for obtaining names stored in a file, looping until one is found. * | |
* supports general irc functions, channel invite/(re)joining, random * | |
* nicknames, backgrounding, server list, quit priority, passwd auth, debug * | |
* and other misc. functions. * | |
* * | |
* AUTHOR: * | |
* v9/vade79@realhalo.org, realhalo.org. (* model) * | |
* Estella/Estella@Mystagic, mystagic.com (ipv6 port) * | |
* * | |
* COMPILE: * | |
* # cc orignick.c -o orignick -lcrypt * | |
* method 1(usually), depends on distribution/os. * | |
* * | |
* # cc orignick.c -o orignick * | |
* method 2(secondary), depends distribution/os. * | |
* * | |
* note: apply the "-DNOCOLOR" argument to your compiler to disable color. * | |
* * | |
* DISTRIBUTION: * | |
* +autostop(snatch->solid model) : stops scanning once met any objective. * | |
* +check(snatch->solid model) : extended buffer checking for security. * | |
* +fix(snatch->solid model) : appended fixes from the snatch model. * | |
* +cchannel(snatch->solid model) : channel correction support. * | |
* +noroot(snatch->solid model) : disallowed root to run by default. * | |
* +version(snatch->solid model) : display the version and id information. * | |
* +nickfix(snatch->solid model) : major non-functional error fixed. (1.9) * | |
* +extended(snatch->solid model) : for servers that allow 30 char names. * | |
* +buffix(snatch->solid model) : fixes off-by-one buffer sizes. (2.3) * | |
* +buffix2(snatch->solid model) : fixes differences in allocations. (2.4) * | |
* -permnick(snatch->solid model) : conflicted with new options. * | |
* +combine(solid->complete model): combined both features of both models. * | |
* +invite(solid->complete model) : re-included for the combined model. * | |
* +doquit(complete->iodine model): priority to get nicknames that quit. * | |
* +passwd(complete->iodine model): kill passwd option used via privmsg. * | |
* +nodisp(complete->iodine model): disable bot showing status. * | |
* +envfix(complete->iodine model): fixes possible null sets in env vars. * | |
* +global(iodine->global model) : support for more linux distributions. * | |
* +buffree(iodine->global model) : released finished buffers, save memory. * | |
* +kdelay(iodine->global model) : delay remote kills, prevent regain. * | |
* +vhost(iodine->global model) : virtual host support. (3.5) * | |
* +delay(iodine->global model) : delay support, to prevent flood. (3.8) * | |
* +vhostfix(iodine->global model): fixes reconnection memory wipe. (3.9) * | |
* +vreply(iodine->global model) : version response option. * | |
* +delayfix(iodine->global model): change in delay method, less waste. * | |
* +cvreply(iodine->global model) : won't reply to version until newnick. * | |
* -buffix2(iodine->global model) : reverted to old buffer method, for new. * | |
* +bsd(global->glob++ model) : support for bsd distributions/os. * | |
* +kencrypt(global->glob++ model): kill passwd encryption. * | |
* +finished(glob++->final model) : orignick project completed. (NUL) * | |
* +finished(final->final+ model) : minor fix from previous version. (NUL) * | |
* +done(final+->final++ model) : final changes. (X) * | |
* +done(final++->final+++ model) : so i thought, fixed fd volume. (X) * | |
* * | |
* TUTORIAL: * | |
* the names file(-f argument) should contain a list similar to this: * | |
* ------------------------------------------------------------------------- * | |
* a * | |
* b * | |
* c * | |
* ... * | |
* ------------------------------------------------------------------------- * | |
* if you are trying to get one letter nicknames, for example. other uses * | |
* could be to hold botnet names - to prevent posing. or possibly to hold * | |
* an array of nicknames you use. many reasons can apply. * | |
* * | |
* the server file(-s argument) should contain a list similar to this: * | |
* ------------------------------------------------------------------------- * | |
* irc.server1.net * | |
* irc.server2.net * | |
* irc.server3.net * | |
* ... * | |
* ------------------------------------------------------------------------- * | |
* the port is changed via the -p argument, if none is given it reverts to * | |
* the default port. * | |
* * | |
* EXAMPLES: * | |
* note: all examples include the same load file("alphabet") and server * | |
* file("servers") in the current directory. (-f and -s options, required) * | |
* * | |
* # ./orignick -f alphabet -s servers -c '#private' -k keyed -n on[a-z] * | |
* this example would join #private with the key 'keyed' and use the * | |
* nickname "on[a-z]" if not in use. * | |
* * | |
* # ./orignick -f alphabet -s servers -P 6666 -d * | |
* this example would change the irc connection port to 6666 and show the * | |
* output of server data. * | |
* * | |
* # ./orignick -f alphabet -s servers -b -P ~/pid.orignick * | |
* this example would background orignick and write the pid to * | |
* pid.orignick in the home directory. * | |
* * | |
* # ./orignick -f alphabet -s servers -K killme * | |
* this example would set the kill password to "killme" and could be * | |
* killed via "/msg <botnick/channel> killme" remotely. by being killed * | |
* it will simply quit the server and reconnect to the next server on the * | |
* server list. so, since it can be killed via the channel, don't make it * | |
* an easy password. also, if you are not comfortable with having your * | |
* password in the command line you can set the environmental variable * | |
* "PASSWD"(default) to the password you desire. (use -E or the * | |
* environmental variable "EPASSWD" for encrypted passwords, if you don't * | |
* know how to encrypt your password use the -M option of orignick) * | |
* * | |
* # ./orignick -f alphabet -s servers -Z -S 1000000 -L 3000000 -H host.com * | |
* this example would disable version replies, set a server delayed * | |
* response time for a full second, set a special situation delayed * | |
* response time for a full three seconds(both delay times are used to * | |
* prevent excess flooding) and use host.com as a virtual host. * | |
* * | |
* # ./orignick -f alphabet -s servers -V "mIRC32 v5.82 K.Mardam-Bey" * | |
* this example would set the version reply to "mIRC32 v5.82 K.Mardam-Bey" * | |
* instead of the default orignick reply. (note: will only reply after * | |
* the desired nickname(s) has been obtained.) * | |
* * | |
* final note: if the -e argument is used make sure the server supports 30 * | |
* character names. otherwise, display and internal errors will occur. if * | |
* you notice excess flooding quits by the bot, apply the -S and/or -L * | |
* arguments with a specified time that stops the excess flood quits. * | |
* (-S 1000000 and/or -L 3000000 perhaps?) * | |
* * | |
* COMMENTS: * | |
* i'm aware that i didn't write this in the most clean manner, but it is * | |
* effective and compact to me. i'm the only person who really needs to * | |
* read it anyways. also, there are benefits from having a channel for the * | |
* bot to join, it will keep the nicknames you already have via the quit * | |
* method. finally, when orignick is placed in the background it will not * | |
* exit due to errors that it would during normal foreground processing. * | |
* * | |
* orignick.c: program source code for orignick. (969l!2992w!36061b) * | |
*****************************************************************************/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <pwd.h> | |
#include <signal.h> | |
#include <netdb.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
/* GENERAL INFORMATION, POSSIBLE CHANGES. */ | |
#define VERSION "X+final-ipv6+++" /* version information. */ | |
#define ENV_IRCHOST "IRC_HOST" /* optional virtual host variable. */ | |
#define ENV_PASSWORD "PASSWD" /* optional passwd variable. */ | |
#define ENV_EPASSWORD "EPASSWD" /* optional crypted passwd variable. */ | |
#define ENV_USERNAME "USERNAME" /* optional username variable. */ | |
#define ENV_REALNAME "REALNAME" /* optional realname variable. */ | |
#define DEFAULT_INFO "Unknown" /* generic name info if no other. */ | |
#define DEFAULT_PORT 6667 /* generic irc port to connect to. */ | |
#define MAX_NAME_LENGTH 9 /* name argument limit. (regular) */ | |
#define MAX_NAME_LENGTH_EXT 30 /* name argument limit. (extended) */ | |
#define MAX_ARGS 512 /* name and server array limit. */ | |
#define MAX_ERRORS 5 /* invalid nicknames before exit. */ | |
#define KILL_DELAY 5 /* delay after remote kill to rcon. */ | |
#define BASE_BUFFER 1024 /* shouldn't change this. */ | |
#define VERSION_FPROT 5 /* delay for version reply. (secs) */ | |
#define ALLOW_ROOT 0 /* 1=allow root to run, 0=don't. */ | |
/* #define NOCOLOR */ /* un-comment to disable color. */ | |
#define _XOPEN_SOURCE /* for the encrypted passwd option. */ | |
/* PROMPTS OR PRECURSORS TO DISPLAY TEXT. */ | |
#ifdef NOCOLOR | |
#define PMT "[orignick6]: " /* regular. (no color) */ | |
#define EPMT "[ERROR]: " /* error. (no color) */ | |
#define DPMT "[debug]: " /* debug. (no color) */ | |
#endif | |
#ifndef NOCOLOR | |
#define PMT "\033[1;30m[\033[1;37morignick6\033[1;30m]:\033[0m " /* regular. */ | |
#define EPMT "\033[1;30m[\033[1;31mERROR\033[1;30m]:\033[0m " /* error. */ | |
#define DPMT "\033[1;30m[\033[0;36mdebug\033[1;30m]:\033[0m " /* debug. */ | |
#endif | |
/* PROGRAM BEGIN. */ | |
int port=DEFAULT_PORT; | |
int name_length=MAX_NAME_LENGTH; | |
int killd=KILL_DELAY; | |
int ischannel=0; | |
int ispasswd=0; | |
int isnick=0; | |
int isvhost=0; | |
int isversion=1; | |
int isbg=0; | |
int allowversion=0; | |
int nodisplay=0; | |
int noquit=0; | |
int debug=0; | |
int delay=0; | |
int delay2=0; | |
int tot_n=0; | |
int tot_s=0; | |
int bg=0; | |
char id[]="$Id: orignick.c,v "VERSION" 2001/03/30 23:35:21 EST vade79 Exp $"; | |
char *names[MAX_ARGS]; | |
char *servers[MAX_ARGS]; | |
char *vreply="orignick/v"VERSION": v9@realhalo.org, realhalo.org."; | |
char *channel_key="none"; | |
char *parm; | |
char *nickname; | |
char *basenickname; | |
char *username; | |
char *realname; | |
char *password; | |
char *channel; | |
char *vhost; | |
void abort_show(){ | |
fprintf(stderr,"(ctrl-c aborted)\n"); | |
exit(0); | |
} | |
void bug_show(){ | |
printe("orignick failed in memory management, please report this event and ho" | |
"w it occured",1); | |
} | |
void version_fprot(){ | |
allowversion=0; | |
} | |
int main(int argc,char **argv){ | |
int i=0; | |
int j=0; | |
int isname=0; | |
int isserver=0; | |
int isun=0; | |
int isrn=0; | |
int ispid=0; | |
char *pid_file; | |
char *name_file; | |
char *server_file; | |
extern char *optarg; | |
FILE *pid_f; | |
setreuid(getuid(),getuid()); | |
setregid(getgid(),getgid()); | |
signal(SIGHUP,SIG_IGN); | |
signal(SIGPIPE,SIG_IGN); | |
signal(SIGTSTP,SIG_IGN); | |
signal(SIGSEGV,bug_show); | |
signal(SIGINT,abort_show); | |
fprintf(stderr,"(%u) [*] orignick/v%s, written by: vade79/v9[@realhalo.org]." | |
"\n\n",getpid(),VERSION); | |
if((!getuid()||!getgid())&&!ALLOW_ROOT) | |
printe("running orignick as root is disabled",1); | |
make_userinfo(); | |
while((i=getopt(argc,argv,"f:s:p:u:r:c:k:n:S:L:P:dbK:E:M:D:H:V:ZzNev"))!=EOF){ | |
switch(i){ | |
case 'f': | |
if(!isname){ | |
isname=1; | |
if(!(name_file=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(name_file,optarg); | |
} | |
break; | |
case 's': | |
if(!isserver){ | |
isserver=1; | |
if(!(server_file=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(server_file,optarg); | |
} | |
break; | |
case 'p': | |
if(atoi(optarg)>0) | |
port=atoi(optarg); | |
break; | |
case 'u': | |
if(!isun){ | |
if(!(username=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(username,optarg); | |
isun=1; | |
} | |
break; | |
case 'r': | |
if(!isrn){ | |
if(!(realname=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(realname,optarg); | |
isrn=1; | |
} | |
break; | |
case 'c': | |
ischannel=1; | |
if(!(channel=(char *)malloc(strlen(optarg)+2))) | |
printe("main(): allocating memory",1); | |
strcpy(channel,optarg); | |
if(channel[0]!=0x23&&channel[0]!=0x26) | |
sprintf(channel,"#%s",optarg); | |
strtok(channel,","); | |
break; | |
case 'k': | |
if(!(channel_key=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(channel_key,optarg); | |
break; | |
case 'n': | |
isnick=1; | |
if(!(nickname=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(nickname,optarg); | |
if(!(basenickname=(char *)malloc(strlen(nickname)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(basenickname,nickname); | |
break; | |
case 'S': | |
delay=atoi(optarg); | |
break; | |
case 'L': | |
delay2=atoi(optarg); | |
break; | |
case 'P': | |
ispid=1; | |
if(!(pid_file=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(pid_file,optarg); | |
break; | |
case 'd': | |
debug=1; | |
break; | |
case 'b': | |
bg=1; | |
break; | |
case 'K': | |
ispasswd=1; | |
if(!(password=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(password,optarg); | |
break; | |
case 'E': | |
ispasswd=2; | |
if(!(password=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(password,optarg); | |
break; | |
case 'M': | |
orignick_encrypt(optarg); | |
fprintf(stderr,"%sEncrypted password: %s\n",PMT,password); | |
exit(0); | |
break; | |
case 'D': | |
if(atoi(optarg)>-1) | |
killd=atoi(optarg); | |
break; | |
case 'H': | |
isvhost=1; | |
if(!(vhost=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(vhost,optarg); | |
break; | |
case 'V': | |
isversion=1; | |
if(!(vreply=(char *)malloc(strlen(optarg)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(vreply,optarg); | |
break; | |
case 'Z': | |
isversion=0; | |
break; | |
case 'z': | |
noquit=1; | |
break; | |
case 'N': | |
nodisplay=1; | |
break; | |
case 'e': | |
name_length=MAX_NAME_LENGTH_EXT; | |
break; | |
case 'v': | |
fprintf(stderr,"Version information: orignick/v%s.\n" | |
"Id inormation: %s\n",VERSION,id); | |
exit(0); | |
break; | |
default: | |
usage(argv[0]); | |
break; | |
} | |
} | |
if(!isvhost) | |
if(getenv(ENV_IRCHOST)&&strlen((char *)getenv(ENV_IRCHOST))>0){ | |
isvhost=1; | |
if(!(vhost=(char *)malloc(strlen((char *)getenv(ENV_IRCHOST))+1))) | |
printe("main(): allocating memory",1); | |
strcpy(vhost,(char *)getenv(ENV_IRCHOST)); | |
} | |
if(!ispasswd){ | |
if(getenv(ENV_PASSWORD)&&strlen((char *)getenv(ENV_PASSWORD))>0){ | |
ispasswd=1; | |
if(!(password=(char *)malloc(strlen((char *)getenv(ENV_PASSWORD))+1))) | |
printe("main(): allocating memory",1); | |
strcpy(password,(char *)getenv(ENV_PASSWORD)); | |
} | |
if(getenv(ENV_EPASSWORD)&&strlen((char *)getenv(ENV_EPASSWORD))>0){ | |
ispasswd=2; | |
if(!(password=(char *)malloc(strlen((char *)getenv(ENV_EPASSWORD))+1))) | |
printe("main(): allocating memory",1); | |
strcpy(password,(char *)getenv(ENV_EPASSWORD)); | |
} | |
} | |
if(!isun) | |
if(getenv(ENV_USERNAME)&&strlen((char *)getenv(ENV_USERNAME))>0){ | |
isun=1; | |
if(!(username=(char *)malloc(strlen((char *)getenv(ENV_USERNAME))+1))) | |
printe("main(): allocating memory",1); | |
strcpy(username,(char *)getenv(ENV_USERNAME)); | |
} | |
if(!isrn) | |
if(getenv(ENV_REALNAME)&&strlen((char *)getenv(ENV_REALNAME))>0){ | |
isrn=1; | |
if(!(realname=(char *)malloc(strlen((char *)getenv(ENV_REALNAME))+1))) | |
printe("main(): allocating memory",1); | |
strcpy(realname,(char *)getenv(ENV_REALNAME)); | |
} | |
if(!isserver||!isname) | |
usage(argv[0]); | |
else{ | |
fprintf(stderr,"%sHostname is set: %s.\n",PMT,isvhost?vhost:"default"); | |
fprintf(stderr,"%sServer response delays are set: 1(%dms), 2(%dms).\n",PMT, | |
delay,delay2); | |
fprintf(stderr,"%sMaximum nickname length is set: %d. (%s)\n",PMT, | |
name_length,name_length==MAX_NAME_LENGTH?"default":"extended"); | |
fprintf(stderr,"%sChannel join is set: %s.\n",PMT,ischannel?channel:"none"); | |
fprintf(stderr,"%sVersion reply is set: %s.\n",PMT,isversion?"on":"off"); | |
fprintf(stderr,"%sOn quit grab is set: %s.\n",PMT,noquit?"off":"on"); | |
fprintf(stderr,"%sKill password is set: %s.\n",PMT,ispasswd?"on":"off"); | |
if(ispasswd) | |
fprintf(stderr,"%sKill delay time is set: %ds. (%s)\n",PMT,killd, | |
killd==KILL_DELAY?"default":"extended"); | |
fprintf(stderr,"%sUsing server file: %s.\n",PMT,server_file); | |
make_server_list(server_file); | |
if(!tot_s){ | |
fprintf(stderr,"%sNot enough servers gathered to create an array.\n",PMT); | |
exit(1); | |
} | |
fprintf(stderr,"%sArray server list created: %d server(s).\n",PMT,tot_s--); | |
fprintf(stderr,"%sUsing name file: %s.\n",PMT,name_file); | |
make_names_list(name_file); | |
if(!tot_n){ | |
fprintf(stderr,"%sNot enough names gathered to create an array.\n",PMT); | |
exit(1); | |
} | |
fprintf(stderr,"%sArray name list created: %d name(s).\n",PMT,tot_n--); | |
if(!isnick) | |
rand_nickname(name_length); | |
if(bg){ | |
fprintf(stderr,"%sForking into the background.\n",PMT); | |
switch(isbg=fork()){ | |
case -1: | |
printe("forking into the background",1); | |
break; | |
case 0: | |
if(ispid){ | |
pid_f=fopen(pid_file,"w"); | |
fprintf(pid_f,"%u\n",getpid()); | |
fclose(pid_f); | |
} | |
setsid(); | |
while(1){ | |
irc_parse(servers[j++],port); | |
usleep(250000); | |
if(tot_s<j) | |
j=0; | |
} | |
break; | |
default: | |
fprintf(stderr,"%sBackgrounded to pid: %u.\n",PMT,isbg); | |
exit(0); | |
break; | |
} | |
} | |
else | |
while(1){ | |
irc_parse(servers[j++],port); | |
usleep(250000); | |
if(tot_s<j) | |
j=0; | |
} | |
} | |
exit(0); | |
} | |
int valid_name(char *word){ | |
int i=0; | |
for(i=0;i<strlen(word);i++) | |
if(word[i]<0x30||word[i]>0x7D) | |
return(1); | |
return(0); | |
} | |
int make_names_list(char *path){ | |
int i=0; | |
int j=0; | |
char read[(BASE_BUFFER+name_length)]; | |
FILE *fd; | |
if(!(fd=fopen(path,"r"))) | |
printe("name file doesn't appear to exist or isn't readable",1); | |
tot_n=0; | |
while(fgets(read,sizeof(read),fd)){ | |
if(j>=MAX_ARGS) | |
printe("too many names to store in memory",1); | |
if(read[0]!=0x23){ | |
for(i=0;i<strlen(read);i++) | |
if(read[i]==0x0A) | |
read[i]=0x0; | |
if(read[0]!=0x0A&&read[0]!=0x0){ | |
if(j-tot_n>MAX_ERRORS) | |
printe("maximum invalid name(s) exceeded",1); | |
if(strlen(read)>name_length) | |
printe("ignored name in name file due to length restrictions",0); | |
else if(valid_name(read)) | |
printe("ignored name in name file due to invalid character(s)",0); | |
else{ | |
if(!(names[tot_n]=(char *)malloc(name_length)+1)) | |
printe("make_names_list(): allocating memory",1); | |
strcpy(names[tot_n++],read); | |
} | |
} | |
bzero(read,sizeof(read)); | |
} | |
j++; | |
} | |
fclose(fd); | |
return(0); | |
} | |
int make_server_list(char *path){ | |
int i=0; | |
int j=0; | |
char read[(256+2)]; | |
FILE *fd; | |
if(!(fd=fopen(path,"r"))) | |
printe("server file doesn't appear to exist or isn't readable",1); | |
while(fgets(read,sizeof(read),fd)){ | |
if(j>=MAX_ARGS) | |
printe("too many servers to store in memory",1); | |
if(read[0]!=0x23){ | |
for(i=0;i<strlen(read);i++) | |
if(read[i]==0x0A) | |
read[i]=0x0; | |
if(read[0]!=0x0A&&read[0]!=0x0) | |
if(strlen(read)>256) | |
printe("ignored server due to length restrictions",0); | |
else{ | |
if(!(servers[tot_s]=(char *)malloc(256+1))) | |
printe("make_server_list(): allocating memory",1); | |
strcpy(servers[tot_s++],read); | |
} | |
bzero(read,sizeof(read)); | |
} | |
j++; | |
} | |
fclose(fd); | |
return(0); | |
} | |
int make_userinfo(){ | |
struct passwd *userinfo; | |
if(!(userinfo=getpwuid(getuid()))) | |
printe("passwd entry doesn't appear to exist",1); | |
else{ | |
if(strlen(userinfo->pw_name)){ | |
if(!(username=(char *)malloc(strlen((char *)userinfo->pw_name)+1))) | |
printe("make_userinfo(): allocating memory",1); | |
strcpy(username,(char *)userinfo->pw_name); | |
} | |
else{ | |
if(!(username=(char *)malloc(strlen(DEFAULT_INFO)+1))) | |
printe("make_userinfo(): allocating memory",1); | |
strcpy(username,DEFAULT_INFO); | |
} | |
if(strlen(userinfo->pw_gecos)){ | |
if(!(realname=(char *)malloc(strlen((char *)userinfo->pw_gecos)+1))) | |
printe("make_userinfo(): allocating memory",1); | |
strcpy(realname,(char *)userinfo->pw_gecos); | |
} | |
else{ | |
if(!(realname=(char *)malloc(strlen(DEFAULT_INFO)+1))) | |
printe("make_userinfo(): allocating memory",1); | |
strcpy(realname,DEFAULT_INFO); | |
} | |
} | |
return(0); | |
} | |
int parameter(char *array,int i){ | |
int j=0; | |
int k=0; | |
char buf[(strlen(array)+1)]; | |
bzero(buf,sizeof(buf)); | |
if(i<0) | |
strcpy(buf,"*"); | |
else | |
for(j=0;j<strlen(array);j++){ | |
if(array[j]==0x20) | |
i--; | |
else if(!i) | |
buf[k++]=array[j]; | |
if(array[j]==0x0A||array[j]==0x0) | |
j=(strlen(array)+1); | |
} | |
if(i>0) | |
strcpy(buf,"*"); | |
free(parm); | |
if(!(parm=(char *)malloc(strlen(buf)+1))) | |
printe("parameter(): allocating memory",1); | |
strcpy(parm,buf); | |
return(0); | |
} | |
int orignick_encrypt(char *pwd){ | |
char chr[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; | |
char salt[3]; | |
struct timeval tv; | |
srandom(time(0)); | |
sprintf(salt,"%c%c%c",chr[random()%64],chr[random()%64],0x0); | |
if(!(password=(char *)malloc(strlen((char *)crypt(pwd,salt))+1))) | |
printe("orignick_encrypt(): allocating memory",1); | |
strcpy(password,(char *)crypt(pwd,salt)); | |
return(0); | |
} | |
int rand_nickname(int size){ | |
int i=0; | |
int r=0; | |
char string[(MAX_NAME_LENGTH_EXT+1)]; | |
struct timeval tv; | |
while(i<=sizeof(string)){ | |
gettimeofday(&tv,(struct timezone*)0); | |
srand(tv.tv_usec); | |
if((2.0*rand()/(RAND_MAX+1.0))>1) | |
r=(0x41+(int)(26.0*rand()/(RAND_MAX+1.0))); | |
else | |
r=(0x61+(int)(26.0*rand()/(RAND_MAX+1.0))); | |
string[i++]=r; | |
} | |
if(!(nickname=(char *)malloc(strlen(string)+1))) | |
printe("rand_nickname(): allocating memory",1); | |
strncpy(nickname,string,size); | |
return(0); | |
} | |
int irc_parse(char *host,int port){ | |
int err; | |
int i=0; | |
int j=0; | |
int k=0; | |
int l=0; | |
int m=0; | |
int sock=0; | |
int serr=0; | |
int first_ison=0; | |
int start=0; | |
int stop=0; | |
char *tmpchannel; | |
char *tmppassword; | |
char active_nickname[BASE_BUFFER]; | |
char swrite[BASE_BUFFER]; | |
char sread[BASE_BUFFER]; | |
char sread_line[BASE_BUFFER]; | |
struct hostent *he; | |
struct sockaddr_in6 irc; | |
alarm(0); | |
allowversion=0; | |
if(!bg) | |
fprintf(stderr,"%sAttempting to connect to: %s:%d.\n",PMT,host,port); | |
sock=socket(PF_INET6,SOCK_STREAM,0); | |
if(sock<0){ | |
if(!bg) | |
printe("socket error",0); | |
serr=1; | |
} | |
bzero(&irc,sizeof(struct sockaddr_in6)); | |
irc.sin6_family=AF_INET6; | |
if(isvhost){ | |
if (inet_pton(AF_INET6, vhost, &(irc.sin6_addr)) <= 0) { | |
if ((he = getipnodebyname(vhost, AF_INET6, AI_DEFAULT, &err)) == NULL) { | |
if(!bg&&!serr) | |
printe("couldn't resolve the provided host, trying any.",0); | |
irc.sin6_addr=in6addr_any; | |
} | |
else | |
memcpy((char *)&irc.sin6_addr,(char *)he->h_addr,he->h_length); | |
} | |
if(bind(sock,(struct sockaddr*)&irc,sizeof(struct sockaddr_in6))){ | |
if(!bg&&!serr) | |
printe("binding name to socket, trying any.",0); | |
bzero(&irc,sizeof(struct sockaddr_in6)); | |
irc.sin6_len=sizeof(irc); | |
irc.sin6_family=AF_INET6; | |
irc.sin6_addr=in6addr_any; | |
if(bind(sock,(struct sockaddr*)&irc,sizeof(struct sockaddr_in6))){ | |
if(!bg&&!serr) | |
printe("binding any name to socket.",0); | |
serr=1; | |
} | |
} | |
} | |
bzero(&irc,sizeof(struct sockaddr_in6)); | |
irc.sin6_len=sizeof(irc); | |
irc.sin6_family=AF_INET6; | |
irc.sin6_port=htons(port); | |
if (inet_pton(AF_INET6, host, &(irc.sin6_addr)) <= 0) { | |
if ((he = getipnodebyname(host, AF_INET6, AI_DEFAULT, &err)) == NULL) { | |
if(!bg&&!serr) | |
printe("couldn't resolve the provided host",0); | |
serr=1; | |
} | |
else | |
memcpy((char *)&irc.sin6_addr,(char *)he->h_addr,he->h_length); | |
} | |
if(connect(sock,(struct sockaddr *)&irc,sizeof(irc))){ | |
if(!bg&&!serr) | |
printe("couldn't connect to the provided host",0); | |
serr=1; | |
} | |
if(!serr){ | |
if(isnick){ | |
if(!(nickname=(char *)malloc(strlen(basenickname)+1))) | |
printe("main(): allocating memory",1); | |
strcpy(nickname,basenickname); | |
} | |
else | |
rand_nickname(name_length); | |
strtok(username," "); | |
sprintf(swrite,"\nUSER %.128s %.128s %.128s :%.128s\nNICK %.128s\n",username, | |
username,username,realname,nickname); | |
write(sock,swrite,sizeof(swrite)); | |
while(1){ | |
bzero(sread,sizeof(sread)); | |
bzero(swrite,sizeof(swrite)); | |
if(!read(sock,sread,sizeof(sread))){ | |
if(!bg){ | |
if(first_ison&&!nodisplay) | |
fprintf(stderr,"\n"); | |
fprintf(stderr,"%sSession closed from: %s:%d.\n",PMT,host,port); | |
} | |
break; | |
} | |
for(i=0;i<strlen(sread);i++){ | |
if(sread[i]==0x0A){ | |
sread_line[j]=0x0; | |
parameter(sread_line,0); | |
if(!strcmp(parm,"PING")){ | |
parameter(sread_line,1); | |
snprintf(swrite,sizeof(swrite),"\nPONG %s\n",parm); | |
write(sock,swrite,sizeof(swrite)); | |
} | |
bzero(active_nickname,sizeof(active_nickname)); | |
strncpy(active_nickname,sread_line,sizeof(active_nickname)); | |
strtok(active_nickname,"!"); | |
for(l=1;l<strlen(active_nickname);l++) | |
active_nickname[(l-1)]=active_nickname[l]; | |
active_nickname[l-1]=0x0; | |
parameter(sread_line,1); | |
if(!stop){ | |
if(!strcmp(parm,"303")){ | |
if(!first_ison){ | |
first_ison=1; | |
if(!bg&&!debug) | |
if(nodisplay) | |
fprintf(stderr,"%sAttempting to obtain supplied names...\n",PMT); | |
else | |
fprintf(stderr,"(. = in use, ! = free, % = failed, * = success%s): ", | |
ispasswd?", @ = killed":""); | |
} | |
parameter(sread_line,3); | |
if(strlen(parm)==1){ | |
ondelay(1); | |
snprintf(swrite,sizeof(swrite),"\nNICK %s\n",names[(k-1)]); | |
write(sock,swrite,sizeof(swrite)); | |
if(!bg&&!debug&&first_ison&&!nodisplay) | |
fprintf(stderr,"!(%s is free)",names[(k-1)]); | |
} | |
else{ | |
if(k>tot_n) | |
k=0; | |
snprintf(swrite,sizeof(swrite),"\nISON %s\n",names[k++]); | |
write(sock,swrite,sizeof(swrite)); | |
if(!bg&&!debug&&first_ison&&!nodisplay) | |
fprintf(stderr,"."); | |
ondelay(0); | |
} | |
} | |
if(!strcmp(parm,"431")||!strcmp(parm,"432")||!strcmp(parm,"433")){ | |
if(!first_ison){ | |
rand_nickname(name_length); | |
if(!bg) | |
fprintf(stderr,"%sFailed setting nickname, trying random. (%s)\n", | |
PMT,nickname); | |
snprintf(swrite,sizeof(swrite),"\nNICK %s\n",nickname); | |
write(sock,swrite,sizeof(swrite)); | |
} | |
if(start){ | |
if(!bg&&!debug&&first_ison&&!nodisplay) | |
fprintf(stderr,"%(set failed)"); | |
if(k>tot_n) | |
k=0; | |
snprintf(swrite,sizeof(swrite),"\nISON %s\n",names[k++]); | |
write(sock,swrite,sizeof(swrite)); | |
ondelay(0); | |
} | |
} | |
if(!strcmp(parm,"NICK")){ | |
if(!strcmp(active_nickname,nickname)){ | |
parameter(sread_line,2); | |
if(!(nickname=(char *)malloc(strlen(parm)+1))) | |
printe("irc_parse(): allocating memory",1); | |
strcpy(nickname,parm); | |
for(m=1;m<strlen(nickname);m++) | |
nickname[(m-1)]=nickname[m]; | |
nickname[(m-1)]=0x0; | |
if(!bg&&!debug&&first_ison) | |
if(!nodisplay) | |
fprintf(stderr,"*(%s set, now idle)",nickname); | |
else | |
fprintf(stderr,"%sObtained nickname: %s.\n",PMT,nickname); | |
stop=1; | |
} | |
} | |
if(!strcmp(parm,"QUIT")&&ischannel&&!noquit){ | |
for(m=0;m<=tot_n;m++) | |
if(!(strcmp(active_nickname,names[m]))){ | |
ondelay(1); | |
snprintf(swrite,sizeof(swrite),"\nNICK %s\n",names[m]); | |
write(sock,swrite,sizeof(swrite)); | |
if(!bg&&!debug&&first_ison&&!nodisplay) | |
fprintf(stderr,"!(%s is free, quit in %s)",names[m],channel); | |
} | |
} | |
} | |
if(!strcmp(parm,"001")){ | |
if(!bg) | |
fprintf(stderr,"%sConnected successfully to: %s:%d.\n",PMT,host,port); | |
parameter(sread_line,2); | |
if(!(nickname=(char *)malloc(strlen(parm)+1))) | |
printe("irc_parse(): allocating memory",1); | |
strcpy(nickname,parm); | |
if(!bg) | |
fprintf(stderr,"%sConnected with nickname: %s.\n",PMT,nickname); | |
if(ischannel){ | |
snprintf(swrite,sizeof(swrite),"\nJOIN %s :%s\n",channel,channel_key); | |
write(sock,swrite,sizeof(swrite)); | |
} | |
if(k>tot_n) | |
k=0; | |
snprintf(swrite,sizeof(swrite),"\nISON %s\n",names[k++]); | |
write(sock,swrite,sizeof(swrite)); | |
start=1; | |
ondelay(0); | |
} | |
if(!strcmp(parm,"366")){ | |
parameter(sread_line,3); | |
if(!bg&&!first_ison) | |
fprintf(stderr,"%sJoined channel: %s.\n",PMT,parm); | |
} | |
if((!strcmp(parm,"403")||!strcmp(parm,"471")||!strcmp(parm,"472") | |
||!strcmp(parm,"473")||!strcmp(parm,"474")||!strcmp(parm,"475"))&&!bg | |
&&!first_ison){ | |
parameter(sread_line,3); | |
fprintf(stderr,"%sFailed joining channel: %s.\n",PMT,parm); | |
} | |
if(!strcmp(parm,"461")){ | |
make_userinfo(); | |
sprintf(swrite,"\nUSER %.128s %.128s %.128s :%.128s\nNICK %.128s\n", | |
username,username,username,realname,nickname); | |
write(sock,swrite,sizeof(swrite)); | |
} | |
if(!strcmp(parm,"PRIVMSG")){ | |
parameter(sread_line,3); | |
if(isversion&&!allowversion&&stop&&!strcasecmp(":\x01VERSION\x01",parm)){ | |
snprintf(swrite,sizeof(swrite),"\nNOTICE %s :%cVERSION %s%c\n", | |
active_nickname,0x01,vreply,0x01); | |
write(sock,swrite,sizeof(swrite)); | |
allowversion=1; | |
signal(SIGALRM,version_fprot); | |
alarm(VERSION_FPROT); | |
} | |
else if(ispasswd){ | |
if(!(tmppassword=(char *)malloc(strlen(parm)+1))) | |
printe("irc_parse(): allocating memory",1); | |
strcpy(tmppassword,parm); | |
for(m=1;m<strlen(tmppassword);m++) | |
tmppassword[(m-1)]=tmppassword[m]; | |
tmppassword[(m-1)]=0x0; | |
if((ispasswd==2&&!strcmp((char *)crypt(tmppassword,password),password)) | |
||(ispasswd==1&&!strcmp(tmppassword,password))){ | |
if(!bg&&!debug&&first_ison&&!nodisplay) | |
fprintf(stderr,"@(%s sent kill passwd, killing with %ds delay)", | |
active_nickname,killd); | |
shutdown(sock,2); | |
stop=1; | |
sleep(killd); | |
} | |
free(tmppassword); | |
} | |
} | |
if(!strcmp(parm,"KICK")&&ischannel){ | |
parameter(sread_line,2); | |
if(!strcmp(parm,channel)){ | |
parameter(sread_line,3); | |
if(!strcmp(parm,nickname)){ | |
snprintf(swrite,sizeof(swrite),"\nJOIN %s :%s\n",channel,channel_key); | |
write(sock,swrite,sizeof(swrite)); | |
} | |
} | |
} | |
if(!strcmp(parm,"INVITE")&&ischannel){ | |
parameter(sread_line,3); | |
if(!(tmpchannel=(char *)malloc(strlen(parm)+1))) | |
printe("irc_parse(): allocating memory",1); | |
strcpy(tmpchannel,parm); | |
for(m=1;m<strlen(tmpchannel);m++) | |
tmpchannel[(m-1)]=tmpchannel[m]; | |
tmpchannel[(m-1)]=0x0; | |
if(!strcmp(tmpchannel,channel)){ | |
snprintf(swrite,sizeof(swrite),"\nJOIN %s :%s\n",channel,channel_key); | |
write(sock,swrite,sizeof(swrite)); | |
} | |
free(tmpchannel); | |
} | |
bzero(swrite,sizeof(swrite)); | |
parameter(sread_line,1); | |
if(!bg&&debug&&strcmp(parm,"421")) | |
fprintf(stderr,"%s%s\n",DPMT,sread_line); | |
bzero(sread_line,sizeof(sread_line)); | |
j=0; | |
} | |
else if(sread[i]!=0x0D) | |
sread_line[j++]=sread[i]; | |
} | |
} | |
} | |
else if(!bg){ | |
if(first_ison&&!nodisplay) | |
fprintf(stderr,"\n"); | |
fprintf(stderr,"\n%sSession closed from: %s:%d.\n",PMT,host,port); | |
} | |
if(sock) | |
close(sock); | |
return(0); | |
} | |
int printe(char *err,int quit){ | |
if(isbg<1) | |
fprintf(stderr,"%s%s.\n",EPMT,err); | |
if(quit) | |
exit(1); | |
} | |
int ondelay(int ext){ | |
if(ext) | |
if(delay2) | |
usleep(delay2); | |
else | |
if(delay) | |
usleep(delay); | |
return(0); | |
} | |
int usage(char *prog){ | |
fprintf(stderr,"Usage: %s <-s file> <-f file> [options...]\n\n" | |
" -s <file>%cserver file list. [standard per line format] (required)\n" | |
" -f <file>%cname file list. [standard per line format] (required)\n" | |
" -p <numeric>%cwill use an alternate ircd port to connect to.\n" | |
" -u <argument>%cwill use an alternate user name. [non-passwd entry]\n" | |
" -r <argument>%cwill use an alternate real name. [non-passwd entry]\n" | |
" -c <argument>%cwill join the provided channel.\n" | |
" -k <argument>%cwill apply a key to join the channel. [for the -c option]\n" | |
" -n <argument>%cwill use a non-random nickname to start with.\n" | |
" -d%c%cwill use debug mode. [show server data]\n" | |
" -b%c%cwill place orignick into the background. [with errors ignored]\n" | |
" -S <numeric>%cwill delay responding with provided time. [1000000=1s]\n" | |
" -L <numeric>%cis like -S, but used for special situations. [3000000=3s]\n" | |
" -P <file>%cfile to place the pid of the bg process. [for the -b option]\n" | |
" -K <argument>%cwill use a kill passwd to reset the bot via irc.\n" | |
" -E <argument>%cis like -K, but uses an encrypted password instead.\n" | |
" -M <argument>%cwill encrypt the argument as a password and exit.\n" | |
" -D <numeric>%cwill use an alternate remote kill delay time.\n" | |
" -H <argument>%cwill use the provided argument as a virtual host.\n" | |
" -V <argument>%cwill use the provided argument as a version reply.\n" | |
" -Z%c%cwill ignore remote version requests.\n" | |
" -z%c%cwill disable on quit nickname grabs. [if in channel]\n" | |
" -N%c%cwill disable local status showing on the bot.\n" | |
" -e%c%cwill use extended nickname length. [servers with >9 nick limit]\n" | |
" -v%c%cwill display version information and exit.\n" | |
"\nAuthor: vade79@realhalo.org, realhalo.org. [ihadnihn]\n",prog,0x9,0x9,0x9, | |
0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9, | |
0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9); | |
exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment