00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00041 #include "services.h"
00042 #include "nickserv.h"
00043 #include "operserv.h"
00044 #include "memoserv.h"
00045 #include "chanserv.h"
00046 #include "infoserv.h"
00047 #include "gameserv.h"
00048 #include "mass.h"
00049 #include "log.h"
00050
00051 void parseLine(char *);
00052
00059 int
00060 ConnectToServer(char *hostname, int portnum)
00061 {
00062 fd_set wfd, xfd;
00063 struct sockaddr_in sa;
00064 struct hostent *hp;
00065 int s;
00066
00067 if ((hp = gethostbyname(hostname)) == NULL) {
00068 errno = ECONNREFUSED;
00069 return (-1);
00070 }
00071
00072 bzero(&sa, sizeof(sa));
00073 bcopy(hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
00074 sa.sin_family = hp->h_addrtype;
00075 sa.sin_port = htons((u_short) portnum);
00076
00077 if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
00078 return (-1);
00079 if (connect(s, (struct sockaddr *)&sa, sizeof sa) < 0) {
00080 printf("Error: %s\n", strerror(errno));
00081 close(s);
00082 return (-1);
00083 }
00084
00085
00086
00087
00088
00089 FD_ZERO(&wfd);
00090 FD_ZERO(&xfd);
00091 FD_SET(s, &wfd);
00092 FD_SET(s, &xfd);
00093 if (select(s + 2, NULL, &wfd, &xfd, NULL) < 0 || !FD_ISSET(s, &wfd)
00094 || FD_ISSET(s, &xfd)) {
00095 logDump(corelog,
00096 "Error occured while attempting to establish connection [%d]",
00097 errno);
00098 flushLogs(NULL);
00099 sshutdown(2);
00100 }
00101
00102 return (s);
00103 }
00104
00111 void
00112 sSend(char *format, ...)
00113 {
00114 char sBuffer[IRCBUF];
00115 va_list stuff;
00116
00117
00118
00119
00120
00121
00122 va_start(stuff, format);
00123 vsnprintf(sBuffer, sizeof(sBuffer) - 3, format, stuff);
00124 va_end(stuff);
00125
00126
00127
00128
00129 strcat(sBuffer, "\r\n");
00130 #if 0
00131 printf("Writing: %s\n", sBuffer);
00132 #endif
00133 if (net_write(server, sBuffer, strlen(sBuffer)) == -1) {
00134 if (errno == EPIPE || errno == EBADF || errno == EINVAL ||
00135 errno == EFAULT) {
00136 logDump(corelog, "Terminating on write error, errno=%d", errno);
00137 sshutdown(0);
00138 }
00139 }
00140
00141 #ifdef DEBUG
00142 printf("-> %s\n", sBuffer);
00143 #endif
00144 }
00145
00152 void
00153 addUser(char *nick, char *user, char *host, char *name, char *mode)
00154 {
00155 if (!nick || !*nick) {
00156 return;
00157 }
00158 sSend("NICK %s 1 0 %s %s %s :%s", nick, user, host, myname, name);
00159 sSend(":%s MODE %s :%s", nick, nick, mode);
00160 }
00161
00162
00163
00164
00166 #define MAX_IRC_LINE_LEN 512
00167
00173 char oldData[MAX_IRC_LINE_LEN];
00174
00181 void
00182 breakLine(char *tmpbuffer)
00183 {
00184 int usedbuf, terminated;
00185 char sendBuffer[MAX_IRC_LINE_LEN + 1];
00186
00187 memset(sendBuffer, 0, MAX_IRC_LINE_LEN + 1);
00188
00189 usedbuf = 0;
00190
00191
00192
00193
00194
00195 if (strlen(oldData) >= MAX_IRC_LINE_LEN) {
00196 sSend(":%s GLOBOPS :Infinate loop encounted in breakLine(). "
00197 "Mail this line to coders@sorcery.net", OperServ);
00198 sSend(":%s GLOBOPS :Services terminating", OperServ);
00199 sshutdown(1);
00200 }
00201
00202
00203 if (oldData[0] != '\0') {
00204 strncpyzt(sendBuffer, oldData, MAX_IRC_LINE_LEN);
00205 bzero(oldData, MAX_IRC_LINE_LEN);
00206 usedbuf = strlen(sendBuffer);
00207 }
00208
00209 while (*tmpbuffer) {
00210 terminated = FALSE;
00211
00212
00213
00214
00215
00216
00217 while (*tmpbuffer != '\n' && *tmpbuffer != '\r'
00218 && *tmpbuffer != '\0' && usedbuf < MAX_IRC_LINE_LEN) {
00219 sendBuffer[usedbuf] = *tmpbuffer;
00220 usedbuf++;
00221 tmpbuffer++;
00222 }
00223
00224 sendBuffer[usedbuf] = 0;
00225 usedbuf = 0;
00226
00227
00228 while (*tmpbuffer == '\r' || *tmpbuffer == '\n') {
00229 tmpbuffer++;
00230 terminated = TRUE;
00231 }
00232
00233 if (terminated == FALSE) {
00234
00235
00236
00237
00238
00239
00240 strncpyzt(oldData, sendBuffer, MAX_IRC_LINE_LEN);
00241 } else {
00242
00243 parseLine(sendBuffer);
00244 }
00245 }
00246 }
00247
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 void
00273 parseLine(char *line)
00274 {
00275 int i = 0, a = 0, x = 0, prefixed = 0;
00276 char *args2[MAX_IRC_LINE_LEN + 5];
00277 char *args[MAX_IRC_LINE_LEN + 5];
00278 char realargs[151][151];
00279 u_int16_t numargs = 0;
00280
00281
00282
00283
00284
00285
00286
00287 strncpyzt(coreBuffer, line, MAX_IRC_LINE_LEN);
00288 #ifdef DEBUG
00289 printf("Read: %s\n", coreBuffer);
00290 #endif
00291
00292 CTime = time(NULL);
00293
00294 while (*line && x < 150) {
00295 while (*line != ' ' && *line && a < 150) {
00296 realargs[x][a] = *line;
00297 a++;
00298 line++;
00299 }
00300 realargs[x][a] = 0;
00301 args[x] = realargs[x];
00302 x++;
00303 numargs++;
00304 while (*line == ' ')
00305 line++;
00306 a = 0;
00307 }
00308
00309
00310 realargs[x][0] = 0;
00311 args[x] = realargs[x];
00312
00313 if (args[0][0] == ':') {
00314 prefixed = 1;
00318 args[0]++;
00319 } else
00320 prefixed = 0;
00321
00322 if (!strcmp(args[0], "PING") && !prefixed) {
00323 sSend("PONG :%s", myname);
00324 return;
00325 }
00326
00327 else if (!strcmp(args[0], "ERROR") && !strcmp(args[1], ":Closing"))
00328 sshutdown(0);
00329
00330 else if (!strcmp(args[0], "NICK") && !prefixed) {
00331 if (strchr(args[4], '*') || strchr(args[4], '?')
00332 || strchr(args[4], '!') || strchr(args[4], '@')) {
00333 char nick[NICKLEN];
00334
00335 strncpyzt(nick, args[1], NICKLEN);
00336 sSend
00337 (":%s KILL %s :%s!%s (Your ident reply contains either a *, !, @, or ?. Please remove this before returning.)",
00338 services[1].name, nick, services[1].host,
00339 services[1].name);
00340 addGhost(nick);
00341 timer(15, delTimedGhost, strdup(nick));
00342 return;
00343 }
00344
00345 addNewUser(args, numargs);
00346 return;
00347 }
00348
00349
00350 if (!strcmp(args[1], "PRIVMSG")) {
00351 UserList *tmp = getNickData(args[0]);
00352
00353
00354 if (strchr(args[2], '#') || strchr(args[2], '$'))
00355 return;
00356
00357 if (!strcasecmp(args[0], NickServ)
00358 || !strcasecmp(args[0], GameServ)
00359 || !strcasecmp(args[0], OperServ)
00360 || !strcasecmp(args[0], ChanServ)
00361 || !strcasecmp(args[0], MemoServ)
00362 || !strcasecmp(args[0], InfoServ)) return;
00363
00364 if (tmp && tmp->reg && tmp->reg->flags & NBANISH) {
00365 sSend(":%s NOTICE %s :This nickname is banished."
00366 " You cannot use services until you change"
00367 " nicknames.",
00368 NickServ, args[0]);
00369 return;
00370 }
00371
00372 if (!tmp) {
00373 nDesynch(args[0], "PRIVMSG");
00374 return;
00375 }
00376
00377 if (addFlood(tmp, 1))
00378 return;
00379
00380 if (isIgnored(tmp->nick, tmp->user, tmp->host)) {
00381 if (tmp->floodlevel.GetLev() < 2)
00382 sSend
00383 (":%s NOTICE %s :You are on services ignore, you may not use any Service",
00384 NickServ, tmp->nick);
00385 if (!isOper(tmp) || tmp->caccess < 2 || !tmp->reg
00386 || !(tmp->reg->opflags & OROOT))
00387 return;
00388 }
00389
00390 args[3]++;
00391 while (*args[3] == ' ')
00392 args[3]++;
00393
00394 for (i = 3; i < numargs; i++)
00395 args2[i - 3] = args[i];
00396 numargs -= 3;
00397
00398
00399 if (!strcasecmp(args2[0], "\001PING")) {
00400 if (addFlood(tmp, 3))
00401 return;
00402 if (numargs < 3)
00403 sSend(":%s NOTICE %s :\001PING %s", args[2], args[0],
00404 args2[1]);
00405 else
00406 sSend(":%s NOTICE %s :\001PING %s %s", args[2], args[0],
00407 args2[1], args2[2]);
00408 return;
00409 }
00410
00411
00412 if (!strncasecmp(args[2], OperServ, strlen(OperServ)))
00413 sendToOperServ(tmp, args2, numargs);
00414 else if (!strncasecmp(args[2], NickServ, strlen(NickServ)))
00415 sendToNickServ(tmp, args2, numargs);
00416 else if (!strncasecmp(args[2], ChanServ, strlen(ChanServ)))
00417 sendToChanServ(tmp, args2, numargs);
00418 else if (!strncasecmp(args[2], MemoServ, strlen(MemoServ)))
00419 sendToMemoServ(tmp, args2, numargs);
00420 else if (!strncasecmp(args[2], InfoServ, strlen(InfoServ)))
00421 sendToInfoServ(tmp, args2, numargs);
00422 else if (!strncasecmp(args[2], GameServ, strlen(GameServ)))
00423 sendToGameServ(tmp, args2, numargs);
00424 else if (isGhost(args[2])) {
00425 sSend
00426 (":%s NOTICE %s :This is a NickServ registered nick enforcer, and not a real user.",
00427 args[2], args[0]);
00428 }
00429
00430 else if ((numargs >= 1) && adCheck(tmp, args[2], args2, numargs))
00431 return;
00432 return;
00433 }
00434
00435 else if (!strcmp(args[1], "QUIT")) {
00436 remUser(args[0], 0);
00437 return;
00438 } else if (!strcmp(args[1], "NICK")) {
00439 UserList *tmp = getNickData(args[0]);
00440 if (addFlood(tmp, 5))
00441 return;
00442 changeNick(args[0], args[2], args[3]);
00443 return;
00444 } else if (!strcmp(args[1], "MODE") && !strcmp(args[0], args[2])) {
00445 setMode(args[0], args[3]);
00446 return;
00447 } else if (!strcmp(args[1], "MODE")) {
00448 setChanMode(args, numargs);
00449 return;
00450 } else if (!strcmp(args[1], "TOPIC")) {
00451 setChanTopic(args, numargs);
00452 return;
00453 } else if (!strcmp(args[1], "AWAY")) {
00454 if (numargs < 3) {
00455 setFlags(args[0], NISAWAY, '-');
00456 checkMemos(getNickData(args[0]));
00457 } else
00458 setFlags(args[0], NISAWAY, '+');
00459 return;
00460 }
00461
00462 else if (!strcmp(args[1], "JOIN")) {
00463 addUserToChan(getNickData(args[0]), args[2]);
00464 return;
00465 } else if (!strcmp(args[1], "PART")) {
00466 remUserFromChan(getNickData(args[0]), args[2]);
00467 return;
00468 } else if (!strcmp(args[1], "KICK")) {
00469 remUserFromChan(getNickData(args[3]), args[2]);
00470 return;
00471 }
00472
00473 else if (!strcmp(args[1], "KILL")) {
00474 int i;
00475 for (i = 0; i < NUMSERVS; i++) {
00476 if (!strcasecmp(args[2], services[i].name)) {
00477 addUser(services[i].name, services[i].uname,
00478 services[i].host, services[i].rname,
00479 services[i].mode);
00480 sSend(":%s KILL %s :%s!%s (services kill protection)",
00481 services[i].name, args[0], services[i].host,
00482 services[i].name);
00483 sSend(":%s GLOBOPS :%s just killed me!", services[i].name,
00484 args[0]);
00485 remUser(args[0], 0);
00486 return;
00487 }
00488 }
00489
00490 if (isGhost(args[2])) {
00491 delGhost(args[2]);
00492 return;
00493 }
00494
00495 else
00496 remUser(args[2], 1);
00497 return;
00498 } else if (!strcmp(args[1], "MOTD")) {
00499 UserList *tmp = getNickData(args[0]);
00500 if (addFlood(tmp, 1))
00501 return;
00502 motd(args[0]);
00503 return;
00504 }
00505
00506 else if (!strcmp(args[1], "INFO")) {
00507 UserList *tmp = getNickData(args[0]);
00508 if (!tmp || addFlood(tmp, 3))
00509 return;
00510 sendInfoReply(tmp);
00511 return;
00512 }
00513
00514 else if (!strcmp(args[1], "VERSION")) {
00515 UserList *tmp = getNickData(args[0]);
00516 if (addFlood(tmp, 1))
00517 return;
00518 sSend(":%s 351 %s %s %s :%s", myname, args[0], VERSION_STRING,
00519 myname, VERSION_QUOTE);
00520 return;
00521 } else if ((!strcmp(args[1], "GNOTICE") || !strcmp(args[1], "GLOBOPS"))
00522 && !strcmp(args[2], ":Link") && !strcmp(args[3], "with")
00523 && !strncmp(args[4], myname, strlen(myname))) {
00524 sSend(":%s GNOTICE :Link with %s[services@%s] established.",
00525 myname, args[0], hostname);
00526 strncpyzt(hostname, args[0], sizeof(hostname));
00527
00528 expireNicks(NULL);
00529 expireChans(NULL);
00530 sync_cfg("1");
00531 checkTusers(NULL);
00532 flushLogs(NULL);
00533 nextNsync = (SYNCTIME + CTime);
00534 nextCsync = ((SYNCTIME * 2) + CTime);
00535 nextMsync = ((SYNCTIME * 3) + CTime);
00536 loadakills();
00537 return;
00538 }
00539 #ifdef IRCD_HURTSET
00540 else if (!strcmp(args[1], "HURTSET") && (numargs >= 4)) {
00541 UserList *hurtwho;
00542 if ((hurtwho = getNickData(args[2]))) {
00543 if (args[3] && *args[3] == '-')
00544 hurtwho->oflags &= ~(NISAHURT);
00545 else if (args[3] && atoi(args[3]) == 4) {
00546 hurtwho->oflags |= (NISAHURT);
00547 }
00548 else if (args[3] && isdigit(*args[3])
00549 && isAHurt(hurtwho->nick, hurtwho->user,
00550 hurtwho->host)) hurtwho->oflags |=
00551 (NISAHURT);
00552 }
00553 }
00554 #endif
00555 else if (!strcmp(args[1], "SQUIT")) {
00556 time_t jupe;
00557 jupe = time(NULL);
00558 if (strchr(args[2], '.'))
00559 return;
00560 sSend(":%s WALLOPS :%s Un-jupitered by %s at %s", myname, args[2],
00561 args[0], ctime(&(jupe)));
00562 return;
00563 }
00564
00565 else if (!strcmp(args[1], "STATS") && numargs > 3) {
00566 const char* from = args[0];
00567
00568 if (args[2] && !strcasecmp(args[2], "OPTS"))
00569 {
00570 sSend(":%s NOTICE %s :Network name: %s", InfoServ, from, NETWORK);
00571
00572
00573 #ifdef AKILLMAILTO
00574 sSend(":%s NOTICE %s :Akill log address: %s", InfoServ, from,
00575 AKILLMAILTO);
00576 #endif
00577
00578 #ifdef ENABLE_GRPOPS
00579 sSend(":%s NOTICE %s :GRPops enabled.", InfoServ, from);
00580 #endif
00581
00582 #ifdef MD5_AUTH
00583 sSend(":%s NOTICE %s :MD5 authentication available.", InfoServ, from);
00584 #endif
00585
00586 }
00587 else if (args[2] && !strcasecmp(args[2], "V$"))
00588 {
00589 sSend(":%s NOTICE %s :Based on sn services1.4.", InfoServ, from);
00590 }
00591 }
00592
00593
00594 else if (!strcmp(args[0], "ERROR") && !strcmp(args[1], ":No")) {
00595 fprintf(stderr, "Error connecting to server: No N-line\n");
00596 sshutdown(2);
00597 }
00598 }
00599
00604 void
00605 sendInfoReply(UserList * nick)
00606 {
00607 char *from = nick->nick;
00608 extern char *services_info[];
00609 int i = 0;
00610
00611 sSend(":%s 373 %s :Server INFO", myname, from);
00612 for (i = 0; services_info[i]; i++)
00613 sSend(":%s 371 %s :%s", myname, from, services_info[i]);
00614 sSend(":%s 374 %s :End of /INFO list.", myname, from);
00615 return;
00616 }