Software /
code /
prosody
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 |