processone / ejabberd

Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
https://www.process-one.net/ejabberd/
Other
6.12k stars 1.51k forks source link

PEP and pubsub#publish_model results in forbidden #3139

Open COM8 opened 4 years ago

COM8 commented 4 years ago

Environment

Configuration

hosts:
  - "xmpp.example.org"
loglevel: 4
log_rotate_size: 10485760
log_rotate_date: ""
log_rotate_count: 1
log_rate_limit: 100
certfiles:
    - "/etc/letsencrypt/live/server.example.org/ejabberd.pem"
ca_file: "/etc/letsencrypt/live/server.example.org/ejabberd.pem"
listen:
  -
    port: 5222
    ip: "::"
    module: ejabberd_c2s
    max_stanza_size: 262144
    shaper: c2s_shaper
    access: c2s
    starttls: true
  -
    port: 5269
    ip: "::"
    module: ejabberd_s2s_in
    max_stanza_size: 524288
  -
    port: 5443
    ip: "::"
    module: ejabberd_http
    tls: true
    request_handlers:
      "/admin": ejabberd_web_admin
      "/api": mod_http_api
      "/bosh": mod_bosh
      "/captcha": ejabberd_captcha
      "/upload": mod_http_upload
      "/ws": ejabberd_http_ws
      "/oauth": ejabberd_oauth
  -
    port: 5280
    ip: "::"
    module: ejabberd_http
    request_handlers:
      "/admin": ejabberd_web_admin
  -
    port: 1883
    ip: "::"
    module: mod_mqtt
    backlog: 1000
s2s_use_starttls: optional
acl:
  local:
    user_regexp: ""
  loopback:
    ip:
      - 127.0.0.0/8
      - ::1/128
      - ::FFFF:127.0.0.1/128
  admin:
    user:
      - "admin@xmpp.example.org"
access_rules:
  local:
    allow: local
  c2s:
    deny: blocked
    allow: all
  announce:
    allow: admin
  configure:
    allow: admin
  muc_create:
    allow: local
  pubsub_createnode:
    allow: local
  trusted_network:
    allow: loopback
api_permissions:
  "console commands":
    from:
      - ejabberd_ctl
    who: all
    what: "*"
  "admin access":
    who:
      access:
        allow:
          acl: loopback
          acl: admin
      oauth:
        scope: "ejabberd:admin"
        access:
          allow:
            acl: loopback
            acl: admin
    what:
      - "*"
      - "!stop"
      - "!start"
  "public commands":
    who:
      ip: 127.0.0.1/8
    what:
      - status
      - connected_users_number
shaper:
  normal: 1000
  fast: 50000
shaper_rules:
  max_user_sessions: 10
  max_user_offline_messages:
    5000: admin
    100: all
  c2s_shaper:
    none: admin
    normal: all
  s2s_shaper: fast
max_fsm_queue: 10000
acme:
   contact: "mailto:support@example.org"
   ca_url: "https://acme-v01.api.letsencrypt.org"
modules:
  mod_adhoc: {}
  mod_admin_extra: {}
  mod_announce:
    access: announce
  mod_avatar: {}
  mod_blocking: {}
  mod_bosh: {}
  mod_caps: {}
  mod_carboncopy: {}
  mod_client_state: {}
  mod_configure: {}
  mod_disco: {}
  mod_fail2ban: {}
  mod_http_api: {}
  mod_http_upload:
    put_url: https://@HOST@:5443/upload
  mod_last: {}
  mod_mam:
    assume_mam_usage: true
    default: never
  mod_mqtt: {}
  mod_muc:
    access:
      - allow
    access_admin:
      - allow: admin
    access_create: muc_create
    access_persistent: muc_create
    access_mam:
      - allow
    default_room_options:
      allow_subscription: true  # enable MucSub
      mam: false
  mod_muc_admin: {}
  mod_offline:
    access_max_user_messages: max_user_offline_messages
  mod_ping: {}
  mod_privacy: {}
  mod_private: {}
  mod_proxy65:
    access: local
    max_connections: 5
  mod_pubsub:
    access_createnode: pubsub_createnode
    plugins:
      - flat
      - pep
    force_node_config:
      storage:bookmarks:
        access_model: whitelist
      "xmpp.iot.**":
        access_model: presence
        publish_model: open
        persist_items: true
      "eu.siacs.conversations.axolotl.*":
        access_model: open
  mod_push: {}
  mod_push_keepalive: {}
  mod_register:
    ip_access: trusted_network
  mod_roster:
    versioning: true
  mod_s2s_dialback: {}
  mod_shared_roster: {}
  mod_stream_mgmt:
    resend_on_timeout: if_offline
  mod_vcard: {}
  mod_vcard_xupdate: {}
  mod_version:
    show_os: false
...

Errors from error.log/crash.log

No errors

Bug description

It looks like the pubsub#publish_model property is ignored for PEP nodes.

When I publish a node with pubsub#publish_model set to open it succeeds. But when I then try to change this node from an other user I get error 403 (forbidden).

I also tried to enforce pubsub#publish_model to open by setting it in the ejabberd.yml

Publishing a Node

<iq type="set" from="testiot0@xmpp.example.org/3764522561" id="1650341405-4133679099-2011477782-1192158923-3764522561">
    <pubsub xmlns="http://jabber.org/protocol/pubsub">
        <publish node="xmpp.iot.actuators">
            <item id="xmpp.iot.actuator.speaker">
                <val xmlns="urn:xmpp:uwpx:iot" type="bool">false</val>
            </item>
        </publish>
        <publish-options>
            <x xmlns="jabber:x:data" type="submit"/>
            <field var="FORM_TYPE" type="hidden">
                <value>http://jabber.org/protocol/pubsub#publish-options</value>
            </field>
            <field var="pubsub#persist_items">
                <value>true</value>
            </field>
            <field var="pubsub#access_model">
                <value>presence</value>
            </field>
            <field var="pubsub#publish_model">
                <value>open</value>
            </field>
        </publish-options>
    </pubsub>
</iq>

Publishing a new Value from an other User

<iq type="set" id="fbba1c4e-d7df-45ec-b9a7-9897fea4788b" to="testiot0@xmpp.example.org" from="user1@xmpp.example.org/UWPX_938455955">
  <pubsub xmlns="http://jabber.org/protocol/pubsub">
    <publish node="xmpp.iot.actuators">
      <item id="xmpp.iot.actuator.speaker">
        <var xmlns="urn:xmpp:uwpx:iot" type="bool">False</var>
      </item>
    </publish>
  </pubsub>
</iq>

Server Response

<iq xml:lang='en' to='user1@xmpp.example.org/UWPX_938455955' from='testiot0@xmpp.example.org' type='error' id='fbba1c4e-d7df-45ec-b9a7-9897fea4788b'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='xmpp.iot.actuators'>
      <item id='xmpp.iot.actuator.speaker'>
        <var xmlns="urn:xmpp:uwpx:iot" type="bool">False</var>
      </item>
    </publish>
  </pubsub>
  <error code='403' type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq> 
weiss commented 4 years ago
    force_node_config:
      storage:bookmarks:
        access_model: whitelist
      "xmpp.iot.**": # [...]

"xmpp.iot.**" looks wrong. Does it work if you match "xmpp.iot.*"?

 <publish-options>

Why do you use publishing options? Does it work as expected if you explicitly configure the node (during creation or afterwards)? (However, I do agree that your traffic looks wrong, as I'd either expect your own publish request to fail or the other user's request to succeed.)

COM8 commented 4 years ago

"xmpp.iot.**" was a typo. But it does not change the result. I'm using publish options as a quick way to test node publishing without having to create nodes first. When I request the node configuration, pubsub#publish_model is set to open.

Request

<iq type="get" from="testiot0@xmpp.example.org/2234684552" id="2601013173-1448578218-1105205319-3440505447-2234684552">
    <pubsub xmlns="http://jabber.org/protocol/pubsub#owner">
        <configure node="xmpp.iot.actuators"/>
    </pubsub>
</iq>

Short Response

<field var='pubsub#publish_model' type='list-single' label='Specify the publisher model'>
    <value>open</value>
</field>

Long Response

<iq xml:lang='en' to='testiot0@xmpp.example.org/2234684552' from='testiot0@xmpp.example.org' type='result' id='2601013173-1448578218-1105205319-3440505447-2234684552'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
        <configure node='xmpp.iot.actuators'>
            <x type='form' 
                xmlns='jabber:x:data'>
                <field var='FORM_TYPE' type='hidden'>
                    <value>http://jabber.org/protocol/pubsub#node_config</value>
                </field>
                <field var='pubsub#access_model' type='list-single' label='Specify the access model'>
                    <value>presence</value>
                    <option label='Subscription requests must be approved and only subscribers may retrieve items'>
                        <value>authorize</value>
                    </option>
                    <option label='Anyone may subscribe and retrieve items'>
                        <value>open</value>
                    </option>
                    <option label='Anyone with a presence subscription of both or from may subscribe and retrieve items'>
                        <value>presence</value>
                    </option>
                    <option label='Anyone in the specified roster group(s) may subscribe and retrieve items'>
                        <value>roster</value>
                    </option>
                    <option label='Only those on a whitelist may subscribe and retrieve items'>
                        <value>whitelist</value>
                    </option>
                </field>
                <field var='pubsub#deliver_notifications' type='boolean' label='Deliver event notifications'>
                    <value>1</value>
                </field>
                <field var='pubsub#deliver_payloads' type='boolean' label='Deliver payloads with event notifications'>
                    <value>1</value>
                </field>
                <field var='pubsub#itemreply' type='list-single' label='Whether owners or publisher should receive replies to items'>
                    <value>none</value>
                    <option label='Statically specify a replyto of the node owner(s)'>
                        <value>owner</value>
                    </option>
                    <option label='Dynamically specify a replyto of the item publisher'>
                        <value>publisher</value>
                    </option>
                    <option>
                        <value>none</value>
                    </option>
                </field>
                <field var='pubsub#max_items' type='text-single' label='Max # of items to persist'>
                    <value>1</value>
                </field>
                <field var='pubsub#max_payload_size' type='text-single' label='Max payload size in bytes'>
                    <value>250000</value>
                </field>
                <field var='pubsub#notification_type' type='list-single' label='Specify the event message type'>
                    <value>headline</value>
                    <option label='Messages of type normal'>
                        <value>normal</value>
                    </option>
                    <option label='Messages of type headline'>
                        <value>headline</value>
                    </option>
                </field>
                <field var='pubsub#notify_config' type='boolean' label='Notify subscribers when the node configuration changes'>
                    <value>0</value>
                </field>
                <field var='pubsub#notify_delete' type='boolean' label='Notify subscribers when the node is deleted'>
                    <value>0</value>
                </field>
                <field var='pubsub#notify_retract' type='boolean' label='Notify subscribers when items are removed from the node'>
                    <value>0</value>
                </field>
                <field var='pubsub#persist_items' type='boolean' label='Persist items to storage'>
                    <value>1</value>
                </field>
                <field var='pubsub#presence_based_delivery' type='boolean' label='Only deliver notifications to available users'>
                    <value>1</value>
                </field>
                <field var='pubsub#publish_model' type='list-single' label='Specify the publisher model'>
                    <value>open</value>
                    <option label='Only publishers may publish'>
                        <value>publishers</value>
                    </option>
                    <option label='Subscribers may publish'>
                        <value>subscribers</value>
                    </option>
                    <option label='Anyone may publish'>
                        <value>open</value>
                    </option>
                </field>
                <field var='pubsub#purge_offline' type='boolean' label='Purge all items when the relevant publisher goes offline'>
                    <value>0</value>
                </field>
                <field var='pubsub#roster_groups_allowed' type='list-multi' label='Roster groups allowed to subscribe'/>
                <field var='pubsub#send_last_published_item' type='list-single' label='When to send the last published item'>
                    <value>on_sub_and_presence</value>
                    <option label='Never'>
                        <value>never</value>
                    </option>
                    <option label='When a new subscription is processed'>
                        <value>on_sub</value>
                    </option>
                    <option label='When a new subscription is processed and whenever a subscriber comes online'>
                        <value>on_sub_and_presence</value>
                    </option>
                </field>
                <field var='pubsub#subscribe' type='boolean' label='Whether to allow subscriptions'>
                    <value>1</value>
                </field>
            </x>
        </configure>
    </pubsub>
</iq>