00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: ircparty.c,v 1.21 2007-11-06 00:05:40 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026 #include "ircparty.h"
00027
00028 irc_config_t irc_config = {0};
00029
00030 static config_var_t irc_config_vars[] = {
00031 {"vhost", &irc_config.vhost, CONFIG_STRING},
00032 {"port", &irc_config.port, CONFIG_INT},
00033 {"stealth", &irc_config.stealth, CONFIG_INT},
00034 {0}
00035 };
00036
00037 EXPORT_SCOPE int ircparty_LTX_start(egg_module_t *modinfo);
00038 static int ircparty_close(int why);
00039
00040
00041 extern partyline_event_t irc_party_handler;
00042
00043 static int irc_idx = -1;
00044 static int irc_port = 0;
00045 static bind_table_t *BT_ircparty = NULL;
00046
00047
00048 static int got_join(partymember_t *p, int idx, char *cmd, int nargs, char *args[]);
00049 static int got_part(partymember_t *p, int idx, char *cmd, int nargs, char *args[]);
00050 static int got_quit(partymember_t *p, int idx, char *cmd, int nargs, char *args[]);
00051 static int got_privmsg(partymember_t *p, int idx, char *cmd, int nargs, char *args[]);
00052 static int got_who(partymember_t *p, int idx, char *cmd, int nargs, char *args[]);
00053 static int got_mode(partymember_t *p, int idx, char *cmd, int nargs, char *args[]);
00054
00055
00056 static int irc_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port);
00057 static int irc_on_read(void *client_data, int idx, char *data, int len);
00058 static int irc_on_eof(void *client_data, int idx, int err, const char *errmsg);
00059 static int irc_on_delete(event_owner_t *owner, void *client_data);
00060 static int irc_pm_delete(event_owner_t *owner, void *client_data);
00061
00062 static int ident_result(void *client_data, const char *ip, int port, const char *reply);
00063 static int dns_result(void *client_data, const char *ip, char **hosts);
00064 static int process_results(irc_session_t *session);
00065
00066 static bind_list_t ircparty_binds[] = {
00067 {NULL, "PRIVMSG", got_privmsg},
00068 {NULL, "JOIN", got_join},
00069 {NULL, "PART", got_part},
00070 {NULL, "QUIT", got_quit},
00071 {NULL, "MODE", got_mode},
00072 {NULL, "WHO", got_who},
00073 {0}
00074 };
00075
00076 static event_owner_t irc_generic_owner = {
00077 "ircparty", 0,
00078 0, 0,
00079 0
00080 };
00081
00082 static event_owner_t irc_sock_owner = {
00083 "ircparty", 0,
00084 0, 0,
00085 irc_on_delete
00086 };
00087
00088 static event_owner_t irc_pm_owner = {
00089 "ircparty", 0,
00090 0, 0,
00091 irc_pm_delete
00092 };
00093
00094 static sockbuf_handler_t server_handler = {
00095 "ircparty server",
00096 NULL, NULL, irc_on_newclient,
00097 NULL, NULL
00098 };
00099
00100 static sockbuf_handler_t client_handler = {
00101 "ircparty",
00102 NULL, irc_on_eof, NULL,
00103 irc_on_read, NULL
00104 };
00105
00106 int irc_init()
00107 {
00108 BT_ircparty = bind_table_add("ircparty", 5, "PisiS", MATCH_MASK, BIND_STACKABLE);
00109 bind_add_list("ircparty", ircparty_binds);
00110
00111 irc_idx = egg_server(irc_config.vhost, irc_config.port, &irc_port);
00112 sockbuf_set_handler(irc_idx, &server_handler, NULL, NULL);
00113 return(0);
00114 }
00115
00116 static void kill_session(irc_session_t *session)
00117 {
00118 if (session->ident_id != -1) egg_ident_cancel(session->ident_id, 0);
00119 if (session->dns_id != -1) egg_dns_cancel(session->dns_id, 0);
00120 if (session->ip) free(session->ip);
00121 if (session->host) free(session->host);
00122 if (session->ident) free(session->ident);
00123 if (session->nick) free(session->nick);
00124 if (session->pass) free(session->pass);
00125 free(session);
00126 }
00127
00128 static int irc_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port)
00129 {
00130 irc_session_t *session;
00131
00132 session = calloc(1, sizeof(*session));
00133 session->ip = strdup(peer_ip);
00134 session->port = peer_port;
00135 session->idx = newidx;
00136
00137 sockbuf_set_handler(newidx, &client_handler, session, &irc_sock_owner);
00138 socktimer_on(newidx, 60, 0, NULL, NULL, &irc_generic_owner);
00139 linemode_on(newidx);
00140
00141
00142
00143 if (irc_config.stealth) {
00144 session->state = STATE_RESOLVE;
00145 session->flags |= STEALTH_LOGIN;
00146 }
00147 else {
00148 egg_iprintf(newidx, ":eggdrop.bot NOTICE AUTH :*** Hello %s/%d!\r\n", peer_ip, peer_port);
00149 sockbuf_write(newidx, ":eggdrop.bot NOTICE AUTH :*** Don't forget to use the /PASS command to send your password in addition to normal registration!\r\n", -1);
00150 session->state = STATE_UNREGISTERED;
00151 }
00152
00153
00154 session->ident_id = egg_ident_lookup(peer_ip, peer_port, irc_port, -1, ident_result, session, &irc_generic_owner);
00155 session->dns_id = egg_dns_reverse(peer_ip, -1, dns_result, session, &irc_generic_owner);
00156
00157 return(0);
00158 }
00159
00160 static int ident_result(void *client_data, const char *ip, int port, const char *reply)
00161 {
00162 irc_session_t *session = client_data;
00163
00164 session->ident_id = -1;
00165 if (reply) session->ident = strdup(reply);
00166 else session->ident = strdup("~ircparty");
00167 process_results(session);
00168 return(0);
00169 }
00170
00171 static int dns_result(void *client_data, const char *ip, char **hosts)
00172 {
00173 irc_session_t *session = client_data;
00174 const char *host;
00175
00176 session->dns_id = -1;
00177 if (!hosts || !hosts[0]) host = ip;
00178 else host = hosts[0];
00179
00180 session->host = strdup(host);
00181 process_results(session);
00182 return(0);
00183 }
00184
00185 static int process_results(irc_session_t *session)
00186 {
00187 char fakehost[512];
00188
00189 if (!session->ident || !session->host) return(0);
00190
00191 if (session->state == STATE_PARTYLINE) {
00192 partyline_update_info(session->party, session->ident, session->host);
00193 return(0);
00194 }
00195 if (session->flags & STEALTH_LOGIN) {
00196 snprintf(fakehost, sizeof(fakehost), "-ircparty!%s@%s", session->ident, session->host);
00197 fakehost[sizeof(fakehost)-1] = 0;
00198 if (!user_lookup_by_irchost(fakehost)) {
00199 sockbuf_delete(session->idx);
00200 return(0);
00201 }
00202 sockbuf_write(session->idx, ":eggdrop.bot NOTICE AUTH :*** Don't forget to use the /PASS command to send your password in addition to normal registration!\r\n", -1);
00203 session->state = STATE_UNREGISTERED;
00204 }
00205 return(0);
00206 }
00207
00208 static void irc_greet(irc_session_t *session)
00209 {
00210 egg_iprintf(session->idx, ":eggdrop.bot 001 %s :Welcome to the Eggdrop Partyline!\r\n", session->nick);
00211 egg_iprintf(session->idx, ":eggdrop.bot 375 %s :Message of the Day\r\n", session->nick);
00212 egg_iprintf(session->idx, ":eggdrop.bot 372 %s :There isn't one.\r\n", session->nick);
00213 egg_iprintf(session->idx, ":eggdrop.bot 376 %s :End of /MOTD command.\r\n", session->nick);
00214 }
00215
00216 static int got_join(partymember_t *p, int idx, char *cmd, int nargs, char *args[])
00217 {
00218 if (nargs != 1 || strlen(args[0]) < 2) egg_iprintf(idx, ":eggdrop.bot 461 %s JOIN :Not enough parameters.\r\n", p->nick);
00219 else partychan_join_name(args[0]+1, p, 0);
00220 return(0);
00221 }
00222
00223 static int got_part(partymember_t *p, int idx, char *cmd, int nargs, char *args[])
00224 {
00225 if (nargs != 1 || strlen(args[0]) < 2) egg_iprintf(idx, ":eggdrop.bot 461 %s PART :Not enough parameters.\r\n", p->nick);
00226 else partychan_part_name(args[0]+1, p, args[1]);
00227 return(0);
00228 }
00229
00230 static int got_mode(partymember_t *p, int idx, char *cmd, int nargs, char *args[])
00231 {
00232 if (nargs != 1) return(0);
00233 if (*args[0] == '#') egg_iprintf(idx, ":eggdrop.bot 324 %s %s +tn\r\n", p->nick, args[0]);
00234 else egg_iprintf(idx, ":eggdrop.bot 221 %s +i\r\n", p->nick);
00235 return(0);
00236 }
00237
00238 static int got_privmsg(partymember_t *p, int idx, char *cmd, int nargs, char *args[])
00239 {
00240 if (nargs != 2) {
00241 egg_iprintf(idx, ":eggdrop.bot 461 %s PRIVMSG :Not enough parameters.\r\n", p->nick);
00242 return(0);
00243 }
00244
00245 if (*args[0] == '#') {
00246 partychan_t *chan = partychan_lookup_name(args[0]+1);
00247 if (!chan) egg_iprintf(idx, ":eggdrop.bot 401 %s %s :No such nick/channel\r\n", p->nick, args[0]);
00248 else partyline_on_input(partychan_lookup_name(args[0]+1), p, args[1], -1);
00249 }
00250 else {
00251 botnet_entity_t src = user_entity(p);
00252
00253 partymember_t *dest = partymember_lookup(args[0], NULL, -1);
00254 if (!dest) egg_iprintf(idx, ":eggdrop.bot 401 %s %s :No such nick/channel\r\n", p->nick, args[0]);
00255 else partymember_msg(dest, &src, args[1], -1);
00256 }
00257 return(0);
00258 }
00259
00260 static int got_who(partymember_t *p, int idx, char *cmd, int nargs, char *args[])
00261 {
00262 partychan_t *chan;
00263 partychan_member_t *m;
00264 partymember_t *q;
00265 int i;
00266
00267 if (nargs != 1 || strlen(args[0]) < 2) return(0);
00268 chan = partychan_lookup_name(args[0]+1);
00269 if (!chan) return(0);
00270
00271 for (i = 0; i < chan->nmembers; i++) {
00272 m = chan->members+i;
00273 if (chan->members[i].flags & PARTY_DELETED) continue;
00274 q = m->p;
00275 egg_iprintf(idx, ":eggdrop.bot 352 %s %s %s %s eggdrop.bot %s H :0 real name\r\n", p->nick, args[0], q->ident, q->host, q->nick);
00276 putlog(LOG_MISC, "ircpartylog", ":eggdrop.bot 352 %s %s %s %s eggdrop.bot %s H :0 real name\r\n", p->nick, args[0], q->ident, q->host, q->nick);
00277 }
00278
00279 egg_iprintf(idx, ":eggdrop.bot 315 %s %s :End of /WHO list.\r\n", p->nick, args[0]);
00280 return(0);
00281 }
00282
00283 static int got_quit(partymember_t *p, int idx, char *cmd, int nargs, char *args[])
00284 {
00285 sockbuf_delete(idx);
00286 return(0);
00287 }
00288
00289 static int irc_on_read(void *client_data, int idx, char *data, int len)
00290 {
00291 irc_session_t *session = client_data;
00292 irc_msg_t msg;
00293 int i;
00294
00295 irc_msg_parse(data, &msg);
00296 putlog(LOG_MISC, "ircpartylog", "%d, '%s'", msg.nargs, msg.cmd);
00297 for (i = 0; i < msg.nargs; i++) {
00298 putlog(LOG_MISC, "ircpartylog", "--> '%s'", msg.args[i]);
00299 }
00300
00301 switch (session->state) {
00302 case STATE_PARTYLINE:
00303 bind_check(BT_ircparty, NULL, msg.cmd, session->party, idx, msg.cmd, msg.nargs, msg.args);
00304 break;
00305 case STATE_UNREGISTERED:
00306 if (!msg.cmd) break;
00307 if (!strcasecmp(msg.cmd, "nick") && msg.nargs == 1) {
00308 if (session->nick) egg_iprintf(session->idx, ":%s NICK %s\r\n", session->nick, msg.args[0]);
00309 str_redup(&session->nick, msg.args[0]);
00310 }
00311 else if (!strcasecmp(msg.cmd, "pass") && msg.nargs == 1) {
00312 str_redup(&session->pass, msg.args[0]);
00313 }
00314 else break;
00315 if (session->nick && session->pass) {
00316 session->user = user_lookup_authed(session->nick, session->pass);
00317 if (!session->user) {
00318 sockbuf_write(session->idx, ":eggdrop.bot NOTICE AUTH :*** Invalid username/password.\r\n", -1);
00319 sockbuf_delete(session->idx);
00320 break;
00321 }
00322 free(session->pass);
00323 session->pass = NULL;
00324 session->party = partymember_new(-1, session->user, NULL, session->nick, session->ident ? session->ident : "~ircparty", session->host ? session->host : session->ip, &irc_party_handler, session, &irc_pm_owner);
00325 session->state = STATE_PARTYLINE;
00326 irc_greet(session);
00327 socktimer_off(idx);
00328 partychan_join_name("*", session->party, 0);
00329 }
00330 break;
00331 }
00332 irc_msg_cleanup(&msg);
00333 return(0);
00334 }
00335
00336 static int irc_on_eof(void *client_data, int idx, int err, const char *errmsg)
00337 {
00338 irc_session_t *session = client_data;
00339
00340 if (session->party) {
00341 if (!err) errmsg = "Client disconnected";
00342 else if (!errmsg) errmsg = "Unknown error";
00343 partymember_delete(session->party, NULL, errmsg);
00344
00345
00346
00347 } else {
00348 sockbuf_delete(idx);
00349 }
00350 return(0);
00351 }
00352
00353 static int irc_pm_delete(event_owner_t *owner, void *client_data)
00354 {
00355 irc_session_t *session = client_data;
00356
00357 session->party = NULL;
00358 sockbuf_delete(session->idx);
00359
00360 return 0;
00361 }
00362
00363 static int irc_on_delete(event_owner_t *owner, void *client_data)
00364 {
00365 irc_session_t *session = client_data;
00366
00367 if (session->party) {
00368 partymember_delete(session->party, NULL, "Deleted!");
00369 session->party = NULL;
00370 }
00371 kill_session(session);
00372 return(0);
00373 }
00374
00375 static int ircparty_close(int why)
00376 {
00377 void *config_root;
00378
00379 config_root = config_get_root("eggdrop");
00380 config_unlink_table(irc_config_vars, config_root, "ircparty", 0, NULL);
00381
00382 sockbuf_delete(irc_idx);
00383 return(0);
00384 }
00385
00386 int ircparty_LTX_start(egg_module_t *modinfo)
00387 {
00388 void *config_root;
00389
00390 irc_generic_owner.module = irc_sock_owner.module = irc_pm_owner.module = modinfo;
00391
00392 modinfo->name = "ircparty";
00393 modinfo->author = "eggdev";
00394 modinfo->version = "1.0.0";
00395 modinfo->description = "irc client support for the partyline";
00396 modinfo->close_func = ircparty_close;
00397
00398
00399 memset(&irc_config, 0, sizeof(irc_config));
00400
00401
00402 config_root = config_get_root("eggdrop");
00403 config_link_table(irc_config_vars, config_root, "ircparty", 0, NULL);
00404 config_update_table(irc_config_vars, config_root, "ircparty", 0, NULL);
00405
00406 irc_init();
00407 return(0);
00408 }