Comparison

plugins/muc/muc.lib.lua @ 6135:6b061f8c6e11

plugins/muc/muc.lib: Add muc-occupant-prejoin events; Use it for banned, members-only, password, nick-conflict and lock checks This reorders some of the checks. Importantly; affiliations are checked first: this means banned users cannot try and guess passwords
author daurnimator <quae@daurnimator.com>
date Mon, 24 Mar 2014 10:25:43 -0400
parent 6134:48b6ef993888
child 6136:2068242028ff
comparison
equal deleted inserted replaced
6134:48b6ef993888 6135:6b061f8c6e11
467 self:broadcast_presence(pr, from); 467 self:broadcast_presence(pr, from);
468 return true; 468 return true;
469 end 469 end
470 end 470 end
471 471
472 function room_mt:handle_join(origin, stanza) 472 module:hook("muc-occupant-pre-join", function(event)
473 return module:fire_event("muc-occupant-pre-join/affiliation", event)
474 or module:fire_event("muc-occupant-pre-join/password", event)
475 or module:fire_event("muc-occupant-pre-join/locked", event)
476 or module:fire_event("muc-occupant-pre-join/nick-conflict", event)
477 end, -1)
478
479 module:hook("muc-occupant-pre-join/password", function(event)
480 local room, stanza = event.room, event.stanza;
473 local from, to = stanza.attr.from, stanza.attr.to; 481 local from, to = stanza.attr.from, stanza.attr.to;
474 log("debug", "%s joining as %s", from, to);
475 local password = stanza:get_child("x", "http://jabber.org/protocol/muc"); 482 local password = stanza:get_child("x", "http://jabber.org/protocol/muc");
476 password = password and password:get_child("password", "http://jabber.org/protocol/muc"); 483 password = password and password:get_child("password", "http://jabber.org/protocol/muc");
477 password = password and password[1] ~= "" and password[1]; 484 password = password and password[1] ~= "" and password[1];
478 if self:get_password() and self:get_password() ~= password then 485 if room:get_password() and room:get_password() ~= password then
486 local from, to = stanza.attr.from, stanza.attr.to;
479 log("debug", "%s couldn't join due to invalid password: %s", from, to); 487 log("debug", "%s couldn't join due to invalid password: %s", from, to);
480 local reply = st.error_reply(stanza, "auth", "not-authorized"):up(); 488 local reply = st.error_reply(stanza, "auth", "not-authorized"):up();
481 reply.tags[1].attr.code = "401"; 489 reply.tags[1].attr.code = "401";
482 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); 490 event.origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
483 return true; 491 return true;
484 elseif self._occupants[to] -- occupant already exists 492 end
485 and jid_bare(from) ~= jid_bare(self._occupants[to].jid) then -- and has different bare real jid 493 end, -1)
494
495 module:hook("muc-occupant-pre-join/nick-conflict", function(event)
496 local room, stanza = event.room, event.stanza;
497 local from, to = stanza.attr.from, stanza.attr.to;
498 local occupant = room._occupants[to]
499 if occupant -- occupant already exists
500 and jid_bare(from) ~= jid_bare(occupant.jid) then -- and has different bare real jid
486 log("debug", "%s couldn't join due to nick conflict: %s", from, to); 501 log("debug", "%s couldn't join due to nick conflict: %s", from, to);
487 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); 502 local reply = st.error_reply(stanza, "cancel", "conflict"):up();
488 reply.tags[1].attr.code = "409"; 503 reply.tags[1].attr.code = "409";
489 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); 504 event.origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
490 return true; 505 return true;
491 end 506 end
492 if not next(self._affiliations) then -- new room, no owners 507 end, -1)
493 self._affiliations[jid_bare(from)] = "owner"; 508
509 module:hook("muc-occupant-pre-join/locked", function(event)
510 if event.room:is_locked() then -- Deny entry
511 event.origin.send(st.error_reply(event.stanza, "cancel", "item-not-found"));
512 return true;
513 end
514 end, -1)
515
516 function room_mt:handle_join(origin, stanza)
517 local from, to = stanza.attr.from, stanza.attr.to;
518 local affiliation = self:get_affiliation(from);
519 if affiliation == nil and next(self._affiliations) == nil then -- new room, no owners
520 affiliation = "owner";
521 self._affiliations[jid_bare(from)] = affiliation;
494 if self:is_locked() and not stanza:get_child("x", "http://jabber.org/protocol/muc") then 522 if self:is_locked() and not stanza:get_child("x", "http://jabber.org/protocol/muc") then
495 self:unlock(); -- Older groupchat protocol doesn't lock 523 self:unlock(); -- Older groupchat protocol doesn't lock
496 end 524 end
497 elseif self:is_locked() then -- Deny entry 525 end
498 origin.send(st.error_reply(stanza, "cancel", "item-not-found")); 526 if module:fire_event("muc-occupant-pre-join", {
499 return true; 527 room = self;
500 end 528 origin = origin;
501 local affiliation = self:get_affiliation(from); 529 stanza = stanza;
530 affiliation = affiliation;
531 }) then return true; end
532 log("debug", "%s joining as %s", from, to);
533
502 local role = self:get_default_role(affiliation) 534 local role = self:get_default_role(affiliation)
503 if role then -- new occupant 535 if role then -- new occupant
504 local is_merge = not not self._occupants[to] 536 local is_merge = not not self._occupants[to]
505 if not is_merge then 537 if not is_merge then
506 self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}}; 538 self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}};
526 pr.attr.to = from; 558 pr.attr.to = from;
527 self:_route_stanza(pr); 559 self:_route_stanza(pr);
528 self:send_history(from, stanza); 560 self:send_history(from, stanza);
529 self:send_subject(from); 561 self:send_subject(from);
530 return true; 562 return true;
531 elseif not affiliation then -- registration required for entering members-only room 563 end
532 local reply = st.error_reply(stanza, "auth", "registration-required"):up(); 564 end
565
566 -- registration required for entering members-only room
567 module:hook("muc-occupant-pre-join/affiliation", function(event)
568 if event.affiliation == nil and event.room:get_members_only() then
569 local reply = st.error_reply(event.stanza, "auth", "registration-required"):up();
533 reply.tags[1].attr.code = "407"; 570 reply.tags[1].attr.code = "407";
534 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); 571 event.origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
535 return true; 572 return true;
536 else -- banned 573 end
537 local reply = st.error_reply(stanza, "auth", "forbidden"):up(); 574 end, -1)
575
576 -- banned
577 module:hook("muc-occupant-pre-join/affiliation", function(event)
578 if event.affiliation == "outcast" then
579 local reply = st.error_reply(event.stanza, "auth", "forbidden"):up();
538 reply.tags[1].attr.code = "403"; 580 reply.tags[1].attr.code = "403";
539 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); 581 event.origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"}));
540 return true; 582 return true;
541 end 583 end
542 end 584 end, -1)
543 585
544 function room_mt:handle_available_to_occupant(origin, stanza) 586 function room_mt:handle_available_to_occupant(origin, stanza)
545 local from, to = stanza.attr.from, stanza.attr.to; 587 local from, to = stanza.attr.from, stanza.attr.to;
546 local current_nick = self:get_occupant_jid(from); 588 local current_nick = self:get_occupant_jid(from);
547 if current_nick then 589 if current_nick then