Compare commits

...

178 Commits

Author SHA1 Message Date
Paweł Chmielowski c526b0e8ff Update mix.lock 2018-06-28 12:11:44 +02:00
Paweł Chmielowski 35136f47ed Bump version in mix.exs 2018-06-28 10:57:09 +02:00
Paweł Chmielowski 8f2233eff7 Update deps 2018-06-28 10:56:59 +02:00
Evgeniy Khramtsov 8879d1d533 Avoid code duplication when checking presence subscription 2018-06-28 10:37:20 +03:00
Evgeniy Khramtsov 71ae7e9fd9 Work-around against public_key incompatibility introduced in OTP21
The commit introduced the incompatility is
https://github.com/erlang/otp/commit/304dd8f81e28ed04cde9f6f7ac1f79870da1c2cd

Thanks to Stu Tomlinson for spotting the issue.

Fixes #2488
2018-06-27 19:40:03 +03:00
Evgeniy Khramtsov 644873dae9 Don't check packets sent to self 2018-06-27 15:02:03 +03:00
Evgeniy Khramtsov 9a11db91f9 Use lists:foldl/3 2018-06-27 13:36:58 +03:00
Evgeniy Khramtsov af8c6d2428 Generate HTTP Upload form using xdata codec 2018-06-27 13:29:38 +03:00
Evgeniy Khramtsov 87357c700f Do not ignore a certificate containing no domain names
Log a warning instead and assign it to an "empty" domain
2018-06-27 11:27:39 +03:00
Evgeniy Khramtsov 7881c5670c Don't replace valid certificates with invalid ones
When building the certificates chains, if several certificates
are found matching the same domain their validity is checked:

* the invalid one is ignored and the valid one is picked
* if both are valid or both are invalid, then the one with
  sooner expiration is ignored.

Fixes #2454
2018-06-27 10:55:37 +03:00
Evgeniy Khramtsov 881e02632b Improve error formatting in mod_http_upload 2018-06-26 19:32:29 +03:00
Evgeniy Khramtsov 47d117c1bf Support SASL PLAIN by xmpp_stream_out
Also, SASL mechanisms chaining is now supported:
if several mechanisms are supported and authentication
fails, next mechanism in the list is picked, until the
list is exhausted. In the case of a failure, the latest
SASL failure reason is returned within handle_auth_failure/3
callback.
2018-06-25 19:16:33 +03:00
Evgeniy Khramtsov cf6f540d53 Don't pass sockmod to xmpp_stream_out 2018-06-25 15:28:02 +03:00
Evgeniy Khramtsov 557e6ecdd0 Introduce resolve/2 and connect_options/3 callbacks for xmpp_stream_out 2018-06-25 15:19:49 +03:00
Evgeniy Khramtsov 5dd3f4c22b Allow gen_server process registration 2018-06-25 14:55:33 +03:00
Evgeniy Khramtsov e7c3b57b8b Allow reconnecting from disconnected state 2018-06-25 14:52:33 +03:00
Evgeniy Khramtsov c907915695 Intercept EXIT signal 2018-06-25 14:46:31 +03:00
Evgeniy Khramtsov 911ed4a7ca Add Resource Binding support to xmpp_stream_out 2018-06-25 13:50:35 +03:00
Evgeniy Khramtsov 499ae96254 Don't use 'unsupported-version' inside SM <failed/> element
This error condition is defined within stream errors, however,
XEP-0198 says:

> This element SHOULD contain an error condition, which MUST
> be one of the **stanza** error conditions defined in RFC 6120.
2018-06-25 09:56:44 +03:00
Evgeniy Khramtsov ac31c85866 Use error formatting functions from xmpp library 2018-06-25 09:45:45 +03:00
Evgeniy Khramtsov c4c91cc956 Generate SASL failures on unencrypted connections only for s2s 2018-06-23 20:31:01 +03:00
Evgeniy Khramtsov d809aafba0 Fix Erlang limits in ejabberdctl.cfg.example to reflect current situation 2018-06-23 20:01:21 +03:00
Evgeniy Khramtsov 6ffb120fce Fix typo 2018-06-21 15:14:19 +03:00
Evgeniy Khramtsov 55f8aa1b22 Add new options for OOM watchdog
* oom_watermark: 1..100
  Start OOM watchdog only when system memory usage exceeds
  this value in percents. When the usage drops below the value,
  OOM watchdog is stopped. The default is 80 (percents).
  Note that once OOM watchdog is started, it performs full garbage
  collection periodically: this can be seen as spikes in CPU
  utilization and drops in RAM usage. If your system is permanently
  above the watermark, it may cause significant CPU overhead.

* oom_queue: positive integer
  Only trigger OOM killer when total amount of messages in all queues
  of all Erlang processes is above this value. The default is 10000.
  Note that this value only takes effect when `oom_killer` is set
  to `true` (this is the default). Otherwise, only a warning will
  be logged.
2018-06-21 14:35:19 +03:00
Paweł Chmielowski 274e9fe7b5 Guard against pres_last=undefined in mod_offline 2018-06-20 12:16:10 +02:00
Evgeniy Khramtsov f465742f2c Remove lowercased duplicates from ejabberd.pot 2018-06-20 13:02:06 +03:00
Evgeniy Khramtsov 9e83c45b3c Restore forgotten translations from previous commit 2018-06-20 12:50:36 +03:00
Evgeniy Khramtsov 446e6e6f3b Update ejabberd.pot 2018-06-20 12:32:10 +03:00
Evgeniy Khramtsov 3a5d2dbed8 Move mod_irc to ejabberd-contrib 2018-06-20 12:27:44 +03:00
Holger Weiss aea6166efe Omit summary form for push tests 2018-06-20 00:15:56 +02:00
Holger Weiss 23cc0f8c3c mod_push: Include a static body text by default
Set the 'include_body' option to a static text by default.  Some app
servers check for the presence of a 'last-message-body' field to
distinguish between notifications generated for actual chat messages and
notifications triggered by other types of traffic.
2018-06-19 23:12:27 +02:00
Holger Weiss 81f4dd0e6a mod_push_keepalive: Increase default timeout
Set the default session timeout to three days.  This way, sessions will
survive a weekend without traffic, for example.
2018-06-19 22:26:08 +02:00
Paweł Chmielowski dee3081df1 Fix reset_stream in websocket using pre-rfc protocol 2018-06-19 17:51:09 +02:00
Evgeniy Khramtsov 6acac7c93f Render roomname, allowinvites and allowpm in room disco#info 2018-06-19 14:02:45 +03:00
Holger Weiss c2f664f941 mod_push_mnesia: Simplify record matching
Omit record fields that aren't used for matching.
2018-06-18 23:12:27 +02:00
Holger Weiss 75127a0deb mod_push_mnesia: Fix lookup of all host sessions 2018-06-18 23:05:08 +02:00
Holger Weiss bb76da03ea mod_mam: Don't replace existing stanza ID
Preserve the original stanza ID for resent messages.  This avoids
storing duplicates in the MAM archive.
2018-06-16 00:43:22 +02:00
Paweł Chmielowski 3099702039 New shaper implementation 2018-06-15 11:56:46 +02:00
Badlop 3ec623f329 Make connected_users_info and user_sessions_info DB-agnostic (#2448)
The result returned by connected_users_info command has changed,
and is now similar to the result of user_sessions_info.

Notice that num_active_users and process_rosteritems still require Mnesia.
2018-06-15 11:28:57 +02:00
Evgeniy Khramtsov 6c323b729b Improve type spec 2018-06-14 19:51:50 +03:00
Evgeniy Khramtsov 17b05ff4b7 Get rid of all calls to jlib.erl module 2018-06-14 19:49:27 +03:00
Evgeniy Khramtsov 7bd5c7fe59 Update mod_muc_room.hrl 2018-06-14 19:19:09 +03:00
Evgeniy Khramtsov 7b04a625be Get rid of jlib.hrl/jlib.erl 2018-06-14 19:11:43 +03:00
Evgeniy Khramtsov 49b08949b1 Do not check for deprecated types
Since we support only Erlang >= OTP-17.5, the check for old-style
dict/queue/etc types is no longer needed
2018-06-14 18:58:35 +03:00
Evgeniy Khramtsov 141be53c21 Get rid of ejabberd.hrl reference from the test suite 2018-06-14 14:24:15 +03:00
Evgeniy Khramtsov fd8e07af47 Get rid of ejabberd.hrl header
The header consisted of too many unrelated stuff and macros misuse.
Some stuff is moved into scram.hrl and type_compat.hrl.
All macros have been replaced with the corresponding function calls.

TODO: probably type_compat.hrl is not even needed anymore since
we support only Erlang >= OTP 17.5
2018-06-14 14:00:47 +03:00
Evgeniy Khramtsov c3c75affa9 Log modules startup 2018-06-14 10:18:10 +03:00
Holger Weiss 85f09b365f mod_push: Omit summary for outgoing messages
Don't include a urn:xmpp:push:summary form in push notifications that
are triggered by outgoing messages.  App servers might use the form
fields to generate user-visible notifications directly (as opposed to
just waking the client app).  This is usually not desired for outgoing
messages.
2018-06-13 21:43:40 +02:00
Evgeniy Khramtsov 645f11d79d Advertise disco#info and disco#items features in mod_disco
Fixes #2470
2018-06-13 14:55:06 +03:00
Holger Weiss 0a20e45690 mod_push: Further improve handling of carbons
Also check for carbon-copied messages (with a body) in the queue of
unacknowledged stanzas.
2018-06-13 00:25:14 +02:00
Holger Weiss 0a9f522222 mod_push: Also include sender/body for carbons
If the 'include_sender' and/or 'include_body' options are specified,
also include a urn:xmpp:push:summary form in push notifications that are
generated for carbon-copied messages (with a body).
2018-06-12 22:47:23 +02:00
Christophe Romain 4f293751f0 Update mix deps 2018-06-11 14:21:35 +02:00
Evgeniy Khramtsov 6f481e3ceb Avoid lager crash on external authentication failure
Fixes #2463
2018-06-08 09:51:26 +03:00
Holger Weiss 00534d4566 Increase start-up/stop timeout in systemd unit
On slow systems, it can take quite a while for "ejabberdctl started"
and/or "ejabberdctl stopped" to return.
2018-06-07 17:40:05 +02:00
Paweł Chmielowski 40185b6bd3 Add ability to modify version string 2018-06-07 15:38:33 +02:00
Evgeny Khramtsov 1de407c420 Merge pull request #2460 from imShara/patch-1
OMEMO enable HOWTO added
2018-06-06 20:05:42 +03:00
imShara 815b95c623 OMEMO enable HOWTO added
Depend on #2425
2018-06-06 20:03:42 +03:00
Holger Weiss 8e1a13b259 upload_tests: Make size error check stricter 2018-06-04 23:29:24 +02:00
Holger Weiss a4049d9418 Omit 'xmlns' field from 'feature_csi' record
The 'xmpp' library has been updated to omit the 'xmlns' field from the
'feature_csi' record.
2018-06-04 23:05:11 +02:00
Holger Weiss ba30ac8ce8 Return detailed error if HTTP upload is too large
If the file size specified in an HTTP upload slot request exceeds the
the configured maximum size, include the limit with the stanza error.
2018-06-04 22:18:56 +02:00
Evgeniy Khramtsov 43c3134f55 Also format gracefully errors returned during module reload 2018-06-03 18:53:30 +03:00
Paweł Chmielowski 67fc2015de Fix problem in commit 548ef7b835 2018-06-01 18:36:39 +02:00
Paweł Chmielowski 548ef7b835 Don't crash in bosh when we receive request with RID < prev_rid 2018-06-01 16:12:22 +02:00
Evgeniy Khramtsov 4337300fce Always display room's xdata in disco#info 2018-06-01 09:07:16 +03:00
Evgeniy Khramtsov cab8005bf3 Display muc#roomconfig_changesubject in room's disco#info
Fixes #2449
2018-06-01 08:56:56 +03:00
Evgeniy Khramtsov 4fc8d1c4a4 Send trailer and close socket explicitly on stream end 2018-06-01 07:58:03 +03:00
Evgeniy Khramtsov 1261502f6a Improve indentation 2018-05-30 22:53:34 +03:00
Holger Weiss dacba3ec00 Merge remote-tracking branch 'processone/pr/2446'
* processone/pr/2446:
  Fix authentication for usernames containing uppercase characters
2018-05-30 20:53:11 +02:00
Stu Tomlinson 4f8af723c6 Fix authentication for usernames containing uppercase characters
Applies to authentication methods that compare User (normalized)
and AuthzId (was not being normalized). These are external, ldap & pam.

Fixes #2280
2018-05-30 18:43:26 +01:00
Evgeniy Khramtsov 5e446d50a8 Get rid of direct calls to 'session' Mnesia table
Fixes #2439
2018-05-30 19:21:56 +03:00
Evgeniy Khramtsov 22d76659c0 Bump xmpp version in order to support language tags validation 2018-05-30 09:54:26 +03:00
Evgeniy Khramtsov 0f9db50c8d Support for roomconfig_lang/roominfo_lang
Now room owners are able to set a preferred language
for the discussions in the room, so other users can
discover rooms based on the language they wish to talk.

TODO: the language format should conform to RFC 5646.
      This check should be implemented in 'xmpp' library.

Fixes #2436
2018-05-30 08:11:58 +03:00
Evgeniy Khramtsov 52b8226671 Use 'list-multi' type for XEP-0157 xdata fields
Thanks to Jonas Wielicki for spotting this
2018-05-29 19:37:24 +03:00
Evgeny Khramtsov 3b9e6eaa95 Merge pull request #2438 from licaon-kter/patch-3
Add default_db in the example config
2018-05-28 16:22:30 +03:00
Licaon_Kter 2c18f89d5b Add default_db in the example config
I only found it in the docs after setting up per module db_
2018-05-28 13:19:59 +00:00
Evgeniy Khramtsov 0381ce1e75 Better report errors of module startup 2018-05-28 09:19:49 +03:00
Evgeniy Khramtsov fc77051b68 Don't call Mod:function() in xmpp_stream callbacks
If a callback function is not defined by the `Mod` then
a call to code_server process is performed. Under heavy load
this may cause code_server to get overloaded. We now avoid this.
2018-05-26 09:06:24 +03:00
Holger Weiss bfe2545c01 mod_muc_sql: Fix export to SQL
The "host" column is supposed to hold the MUC host name.
2018-05-24 01:28:29 +02:00
Holger Weiss c6a9c30f1c mod_push_mnesia: Apply cosmetic changes
Improve the readability of the 'max_user_sessions' check.
2018-05-23 21:40:54 +02:00
Holger Weiss 508f3ef88d mod_push_sql: Check 'max_user_sessions' limit
Remove the oldest push session(s) of a user if the number of enabled
sessions exceeds the 'max_user_sessions' limit.
2018-05-23 20:02:52 +02:00
Paweł Chmielowski 97f7d99007 Handle "Expect: 100-continue" request header in ejabberd_http 2018-05-23 14:52:47 +02:00
Evgeny Khramtsov 2bbfc0b79e Merge pull request #2431 from yokomizor/fix-xmpp-commit
Missing #block_item{} record building with mix
2018-05-22 17:45:53 +03:00
Evgeny Khramtsov 10a5a5eb01 Merge pull request #2430 from yokomizor/ext_mod-export-add_sources_1
Export ext_mod:add_sources/1
2018-05-22 17:39:27 +03:00
Rogério da Silva Yokomizo 2e529f5826 Missing #block_item{} record building with mix
Ref: #638f2d2
2018-05-22 16:37:39 +02:00
Rogério da Silva Yokomizo 4a4cc32650 Export ext_mod:add_sources/1 2018-05-22 16:16:13 +02:00
Evgeniy Khramtsov d2114be6f3 Correctly calculate remaining bytes on file upload 2018-05-19 18:29:33 +03:00
Christophe Romain db51d522e8 Add support for REST API custom headers
ext_api_headers can be defined as a single string. Headers are separated
by comma. Definition MUST NOT contain spaces. Example
"X-MyHead:test,X-Token:082748"
2018-05-17 14:47:21 +02:00
Evgeniy Khramtsov 82c42051c3 Correctly resolve upload.localhost for the test suite 2018-05-17 13:24:23 +03:00
Evgeniy Khramtsov e4c106e0dd Add tests for mod_http_upload 2018-05-17 12:02:00 +03:00
Evgeniy Khramtsov b64e1d95d2 Fix typo file:read() -> file:open() 2018-05-17 12:00:06 +03:00
Paweł Chmielowski c41bab9ca0 Clean state between requests in ejabberd_http 2018-05-15 14:25:19 +02:00
Evgeniy Khramtsov 063737e4f5 Optimize HTTP requests memory usage
Due to historical reasons, ejabberd loads the whole file/data
into the memory when serving an HTTP request. This is now improved:

1) For GET requests ejabberd uses sendfile(2) if the underlying
   connection is HTTP and falls back to read/write loop with 64kb
   buffer for HTTPS connections. This type of requests are handled
   by mod_http_fileserver, mod_http_upload, ejabberd_captcha, etc
2) POST requests are now limited to 20Mb and are fully downloaded
   into the memory for further processing (by ejabberd_web_admin,
   mod_bosh, etc)
3) PUT requests (e.g. for mod_http_upload) are handled by read/write
   loop with 64kb buffer
2018-05-14 19:39:58 +03:00
Badlop cb3bb710bd Handle muc_register_nick success correctly (#2415) 2018-05-14 12:24:56 +02:00
Evgeniy Khramtsov c30715e67b Disable thumbnails creation by default 2018-05-11 18:56:31 +03:00
Evgeniy Khramtsov 27594db029 Support IPv6 connections for PostgreSQL, MySQL and LDAP
Fixes #2411
2018-05-11 16:43:49 +03:00
Paweł Chmielowski 6ac8f6eaee Relax check for valid command name in access_persmissions 2018-05-11 12:24:00 +02:00
Paweł Chmielowski 338d27b45b Use never version of moka 2018-05-09 10:58:00 +02:00
Evgeniy Khramtsov 35a076c251 Stop ejabberd initialization on invalid/unknown options
Since now, ejabberd doesn't ignore unknown options and doesn't
allow to have options with malformed values. The rationale for
this is to avoid unexpected behaviour during runtime, i.e. to
conform to "fail early" approach. Note that it's safe to reload
a configuration with potentialy invalid and/or unknown options:
this will not halt ejabberd, but will only prevent the configuration
from loading.

***NOTE FOR PACKAGE BUILDERS***
This new behaviour should be documented in the upgrade notes.
2018-05-09 11:44:24 +03:00
Evgeniy Khramtsov 680384c342 Reduce IQ handler code copying 2018-05-09 10:30:00 +03:00
Evgeniy Khramtsov 11ff2a1ccf Fix a typo 2018-05-09 09:44:26 +03:00
Evgeniy Khramtsov 3ac1675919 Option watchdog_admins has no effect anymore 2018-05-08 23:47:37 +03:00
Badlop de85c1718e Bypass account creation error when password is empty, caused by extauth 2018-05-08 18:19:07 +02:00
Evgeniy Khramtsov 46f47db512 Get rid of unused rebar instructions 2018-05-08 16:17:07 +03:00
Paweł Chmielowski 6811b92a80 Don't use warnings_as_errors in samerlib 2018-05-08 11:37:20 +02:00
Evgeniy Khramtsov 8766854870 Get rid of ?FUNCTION_NAME macro (it's OTP19+ feature) 2018-05-08 12:06:58 +03:00
Evgeniy Khramtsov 61ae0ff02c Improve logging of external authentication failures 2018-05-08 09:36:34 +03:00
Evgeniy Khramtsov 5522403e8e Don't stop on out-of-date requests 2018-05-07 22:43:01 +03:00
Evgeniy Khramtsov b23d5754e8 Improve robustness of external authentication backends
Now all external ports are attached to supervising processes
and requests are balanced in round-robin manner until the pool
is exhausted.

The commit also deprecates `extauth_instances` option and introduces
`extauth_pool_size` option instead, with the default value of a number
of logical processors (i.e. CPU cores).

Fixes #2403
2018-05-07 19:27:18 +03:00
Paweł Chmielowski b1a03cc346 Make trusted_proxied ejabberd_http option accept ip masks 2018-05-04 09:53:07 +02:00
Paweł Chmielowski ca94cbfd31 Teach acl ip matching about ipv4 mapped ipv6 addresses 2018-05-04 09:52:06 +02:00
Holger Weiss 410db89167 ejabberd_auth: Don't use cache if it's disabled
Don't let the check whether a user exists use the cache if caching was
disabled in the configuration.
2018-05-03 00:31:33 +02:00
Holger Weiss 638f2d2e67 mod_blocking: Use #block_item{} record 2018-05-02 22:17:32 +02:00
Evgeniy Khramtsov 56ee6f0518 Ignore any policy when signing a certificate for the test suite 2018-05-02 10:52:46 +03:00
Evgeniy Khramtsov 4e83fc41d4 Also generate CA certificates for the test suite 2018-05-02 10:28:22 +03:00
Evgeniy Khramtsov 4ea481d1dd Add validator for 'accept_interval' listening option 2018-04-30 11:52:00 +03:00
Christophe Romain 0bd4d1aade Update mix.exs version 2018-04-25 12:30:36 +02:00
Paweł Chmielowski d49aa429ca Update deps 2018-04-25 10:45:18 +02:00
Christophe Romain 316a19d600 Merge pull request #2399 from 4z3/ejabberdctl-fix-parser
ejabberdctl: fix parameters parsing
2018-04-25 10:39:19 +02:00
tv c43037887a ejabberdctl: fix parameter parsing 2018-04-25 00:41:30 +02:00
Holger Weiss 538e0d4844 misc: Catch all Base64 decoding errors 2018-04-24 18:29:10 +02:00
Holger Weiss f3795e9d03 mod_http_upload: Add MIME type for M4A files 2018-04-24 18:16:16 +02:00
Christophe Romain 3df919244c PubSub purge_node must use a transaction (#2231) 2018-04-24 15:58:56 +02:00
Christophe Romain 67773c5174 Merge branch 'master' of github.com:processone/ejabberd 2018-04-24 14:44:58 +02:00
Christophe Romain 61dee97738 Pubsub creation/modification use varchar (#2397) 2018-04-24 14:44:52 +02:00
Evgeniy Khramtsov 6774418a7f Introduce new mod_muc option: access_register
The option is an ACL rule defining who is able to register
nicknames within the conference service. The default is `all`
(for backward compatibility).
2018-04-24 12:29:59 +03:00
Evgeniy Khramtsov ad6fcc7865 Get rid of useless memory/disk usage warnings 2018-04-24 12:12:48 +03:00
Evgeniy Khramtsov ca28faa51a Fix get_affiliation/2 2018-04-24 12:07:10 +03:00
Paweł Chmielowski 5b730cdbf2 Use httpc directly instead of using p1_http wrapper 2018-04-23 17:40:44 +02:00
Paweł Chmielowski 9ed0357760 Use correct headers in rest calls 2018-04-23 12:29:56 +02:00
Evgeniy Khramtsov 06ce884aa8 Add stubs for affiliation-specific backend callbacks 2018-04-23 11:35:43 +03:00
Paweł Chmielowski 3fc0eb4f5b Use correct db backend for remove_mam_for_user_with_peer 2018-04-20 14:06:23 +02:00
Paweł Chmielowski 3bfa683586 Fix mnesia call in mam archive management function 2018-04-20 13:36:54 +02:00
Paweł Chmielowski 5be49cc0fa Add commands for cleaning up mam archive 2018-04-20 13:27:46 +02:00
Christophe Romain 42c029d5f7 Fix type of rest:url/2 2018-04-19 13:21:33 +02:00
Christophe Romain a567abcfdf Fix deprecated call injected by 265c7b62 2018-04-18 14:16:56 +02:00
Christophe Romain 265c7b62c7 Add flexibility on rest url config 2018-04-18 13:16:08 +02:00
Holger Weiss 332567693c mod_push_keepalive: Reset timeout on messages only
Some mobile apps might only be notified on actual chat messages with
a body, so don't let mod_push_keepalive reset the stream management
timeout on other types of traffic.
2018-04-17 00:27:07 +02:00
Holger Weiss de7dc4affa mod_push: Optionally include message sender/body
Add 'include_sender' and 'include_body' options.  If one or both of them
are set to 'true', a urn:xmpp:push:summary form with the enabled
field(s) is included in push notifications that are generated for
messages with a body.

The 'include_body' option can instead be set to a static text.  In this
case, the specified text will be included in place of the actual message
body.  This can be useful to signal the push service whether the
notification was triggered by a message with body (as opposed to other
types of traffic) without leaking actual message contents.
2018-04-16 23:18:03 +02:00
Holger Weiss 48c5ab59f1 mod_http_upload*: Remove empty lines after specs
Remove blank lines following function specifications in mod_http_upload
and mod_http_upload_quota for consistency with other modules.
2018-04-16 18:22:54 +02:00
Holger Weiss b2855d63a7 mod_http_upload*: Add function specifications 2018-04-16 18:17:28 +02:00
Holger Weiss 0282cf64a0 mod_push: Add function specification 2018-04-16 18:14:07 +02:00
Holger Weiss e5cb9dad40 mod_push: Add/adjust debug messages 2018-04-16 18:12:46 +02:00
Evgeniy Khramtsov ec819b4002 Update MUC MAM tests 2018-04-16 16:10:44 +03:00
Evgeniy Khramtsov acc162f4f4 Carefully validate options list 2018-04-16 15:48:06 +03:00
Evgeniy Khramtsov b8505f3e78 Don't crash on invalid module's sub-options
Fixes #2387
2018-04-16 11:06:57 +03:00
Holger Weiss 8a71e2e4f7 mod_push: Don't notify on stream errors
If a pending stream management session is closed with a stream error,
this is usually due to the client opening a new stream that conflicts
with the old one.  Don't generate a push notification in this situation.
2018-04-16 01:08:56 +02:00
Evgeniy Khramtsov a5284229cb Merge branch 'muc-self-presence' 2018-04-14 18:32:12 +03:00
Evgeniy Khramtsov d0f36537fb Clear fast_tls cache on configuration reload 2018-04-13 11:10:20 +03:00
Holger Weiss 3cf4fbc7b0 mod_roster: Use 'lserver' for configuration lookup 2018-04-13 00:12:07 +02:00
Paweł Chmielowski fe4b1a492c Fix notification payload generated by pubsub 2018-04-12 18:02:32 +02:00
Paweł Chmielowski c3b4b4ce4f Pass access option from websocket to c2s
This fixes issue #2223
2018-04-12 17:42:59 +02:00
Paweł Chmielowski 95244c3b6f Fix csi tests 2018-04-12 17:08:27 +02:00
a-iv 89d91b609a New schema support for tests. (#2355) 2018-04-12 15:42:43 +02:00
Christophe Romain d28064518b Improve pubsub#itemreply implementation (#2325) 2018-04-12 15:38:12 +02:00
Evgeniy Khramtsov 7627575856 Update the xmpp dependency to support 'parent' attribute
Fixes #2375
2018-04-11 09:34:06 +03:00
Christophe Romain 99444f2d0e Fix illegal match on previous commit 2018-04-10 15:02:03 +02:00
Christophe Romain 4c0f87b2ff Improve fix for #2288, don't mask errors on get_item 2018-04-10 14:47:18 +02:00
Holger Weiss 54363f8476 gen_mod: Support global module processes 2018-04-04 18:25:19 +02:00
Holger Weiss 094f586811 gen_mod: Remove frontend process support
ejabberd doesn't support frontend processes anymore.
2018-04-04 18:22:59 +02:00
Paweł Chmielowski 45a3c7e0ce Improve mod_multicast 2018-04-04 12:06:35 +02:00
Holger Weiss e2652ce02f mod_http_upload: Accept characters of any script
Accept all alphanumeric characters of any script in user and file names
rather than replacing non-ASCII characters with underscores.  However,
non-alphanumeric characters are still replaced, except for "." and "-".

Closes #2346.
2018-04-03 21:00:15 +02:00
Holger Weiss df651d893e Remove old hex conversion functions
Depend on list_to_integer/2 and integer_to_list/2 being available.
2018-04-03 00:21:33 +02:00
Holger Weiss a2e1f5c882 Move ejabberd_http:url_encode/1 to 'misc' module 2018-04-03 00:12:43 +02:00
Badlop 7f5796fe31 Fix Code format when logging a MUC room kick/ban 2018-04-02 13:51:19 +02:00
Holger Weiss 5f1191b9f5 mod_client_state: Add 'csi_activity' hook
Closes #2358.
2018-04-01 17:13:04 +02:00
Evgeny Khramtsov 0041a11c4a Merge pull request #2357 from Pouriya-Jahanbakhsh/component-send-packet-hook
feat: add hook for sending packet from component
2018-03-30 21:51:03 +03:00
Pouriya Jahanbakhsh e17a16a300 fix: run 'component_send_packet' hook in global mode 2018-03-30 23:19:33 +04:30
Pouriya Jahanbakhsh 7b3d26992b feat: add hook for sending packet from component
New hook 'component_send_packet' added.
Callback function must accept one argument {Pkt, ComponentState} and should yield 'drop' or {NewPkt, NewComponentState}.
2018-03-30 21:31:30 +04:30
Evgeniy Khramtsov 9373ad20ca Don't produce a crash dump during intentional exit
Also halt faster without relying on timeouts for buffers flushing
2018-03-29 12:14:31 +03:00
Evgeniy Khramtsov b283cfa6f2 Remove unused variable 2018-03-29 10:34:09 +03:00
Evgeny Khramtsov a84771fd14 Merge pull request #2351 from rom1dep/config-order_c2s-direct
config: move section about direct-tls for c2s just under regular c2s config
2018-03-29 08:32:13 +03:00
Romain DEP. 2bb6782bee config: move section about direct-tls for c2s just under regular c2s config (to ease parameters comparison) 2018-03-28 23:17:43 +02:00
Mickael Remond ae151927ae Add support for PATCH http method
This is needed to improve out APIs.
2018-03-28 17:34:47 +02:00
Paweł Chmielowski dfbdffad44 Fix process_discoitems_result in mod_multicast 2018-03-28 11:23:28 +02:00
Paweł Chmielowski d71bc73271 Update eimp 2018-03-26 16:18:29 +02:00
Evgeniy Khramtsov ea9c3fd8f7 Fix returning value from mod_vcard_ldap's search() callback
Fixes #2335
2018-03-25 10:53:46 +03:00
Evgeniy Khramtsov 63dba3fd64 Merge branch 'master' into muc-self-presence 2018-03-03 21:09:27 +03:00
Evgeniy Khramtsov ffe02c46e4 Let a MUC room to route presences from its bare JID
The goal for this is to provide entity capabilities (XEP-0115) and
vCard-based avatar hash (XEP-0153)
2018-02-12 17:37:36 +03:00
216 changed files with 5600 additions and 8170 deletions
-3
View File
@@ -93,7 +93,6 @@ Moreover, ejabberd comes with a wide range of other state-of-the-art features:
- Users Directory based on users vCards.
- Publish-Subscribe component with support for Personal Eventing.
- Support for web clients: HTTP Polling and HTTP Binding (BOSH).
- IRC transport.
- Component support: interface with networks such as AIM, ICQ and MSN.
@@ -112,8 +111,6 @@ To compile ejabberd you need:
- OpenSSL 1.0.0 or higher, for STARTTLS, SASL and SSL encryption.
- Zlib 1.2.3 or higher, for Stream Compression support (XEP-0138). Optional.
- PAM library. Optional. For Pluggable Authentication Modules (PAM).
- GNU Iconv 1.8 or higher, for the IRC Transport (mod_irc). Optional. Not
needed on systems with GNU Libc.
- ImageMagick's Convert program. Optional. For CAPTCHA challenges.
If your system splits packages in libraries and development headers, you must
-3
View File
@@ -94,9 +94,6 @@ defmodule Ejabberd.ConfigFile do
module :mod_disco do
end
module :mod_irc do
end
module :mod_http_bind do
end
-1
View File
@@ -565,7 +565,6 @@ modules:
mod_configure: {} # requires mod_adhoc
mod_disco: {}
## mod_echo: {}
mod_irc: {}
mod_http_bind: {}
## mod_http_fileserver:
## docroot: "/var/www"
+2 -4
View File
@@ -197,12 +197,12 @@ AC_ARG_ENABLE(elixir,
esac],[if test "x$elixir" = "x"; then elixir=false; fi])
AC_ARG_ENABLE(iconv,
[AC_HELP_STRING([--enable-iconv], [enable iconv support (default: yes)])],
[AC_HELP_STRING([--enable-iconv], [enable iconv support (default: no)])],
[case "${enableval}" in
yes) iconv=true ;;
no) iconv=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-iconv) ;;
esac],[if test "x$iconv" = "x"; then iconv=true; fi])
esac],[if test "x$iconv" = "x"; then iconv=false; fi])
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug], [enable debug information (default: yes)])],
@@ -275,8 +275,6 @@ if test "$ENABLEGROUP" != ""; then
AC_SUBST([INSTALLGROUP], [$ENABLEGROUP])
fi
ERLANG_DEPRECATED_TYPES_CHECK
if test "$sqlite" = "true"; then
AX_LIB_SQLITE3([3.6.19])
if test "x$SQLITE3_VERSION" = "x"; then
+1
View File
@@ -13,6 +13,7 @@ ExecStart=/bin/sh -c '@ctlscriptpath@/ejabberdctl start && @ctlscriptpath@/ejabb
ExecStop=/bin/sh -c '@ctlscriptpath@/ejabberdctl stop && @ctlscriptpath@/ejabberdctl stopped'
ExecReload=@ctlscriptpath@/ejabberdctl reload_config
PrivateDevices=true
TimeoutSec=300
[Install]
WantedBy=multi-user.target
+24 -24
View File
@@ -64,14 +64,6 @@ log_rotate_count: 1
## 100 is ejabberd's default.
log_rate_limit: 100
##
## watchdog_admins: Only useful for developers: if an ejabberd process
## consumes a lot of memory, send live notifications to these XMPP
## accounts.
##
## watchdog_admins:
## - "bob@example.com"
###. ===============
###' NODE PARAMETERS
@@ -169,6 +161,20 @@ listen:
max_stanza_size: 65536
shaper: c2s_shaper
access: c2s
##
## Direct-TLS for C2S (XEP-0368). A good practice is to forward
## traffic from port 443 to this port, possibly multiplexing it
## with HTTP using e.g. sslh [https://wiki.xmpp.org/web/Tech_pages/XEP-0368],
## so modern clients can bypass restrictive firewalls (in airports, hotels, etc.).
##
## -
## port: 5223
## ip: "::"
## module: ejabberd_c2s
## tls: true
## max_stanza_size: 65536
## shaper: c2s_shaper
## access: c2s
-
port: 5269
ip: "::"
@@ -185,20 +191,6 @@ listen:
web_admin: true
## register: true
captcha: true
##
## Direct-TLS for C2S (XEP-0368). A good practice is to forward
## traffic from port 443 to this port, possibly multiplexing it
## with HTTP using e.g. sslh [https://wiki.xmpp.org/web/Tech_pages/XEP-0368],
## so modern clients can bypass restrictive firewalls (in airports, hotels, etc.).
##
## -
## port: 5223
## ip: "::"
## module: ejabberd_c2s
## tls: true
## max_stanza_size: 65536
## shaper: c2s_shaper
## access: c2s
##
## ejabberd_service: Interact with external components (transports, ...)
@@ -450,6 +442,14 @@ auth_method: internal
##
## new_sql_schema: true
##
## A database can also can be used to store information from several
## modules. To enable storage to the database, just make sure it is
## setup above and set default_db: sql if you want to use SQL for
## all modules.
##
## default_db: sql
###. ===============
###' TRAFFIC SHAPERS
@@ -734,7 +734,6 @@ modules:
## mod_delegation: {} # for xep0356
mod_disco: {}
mod_echo: {}
mod_irc: {}
mod_bosh: {}
## mod_http_fileserver:
## docroot: "/var/www"
@@ -783,7 +782,8 @@ modules:
- "pep" # pep requires mod_caps
force_node_config:
## Avoid using OMEMO by default because it
## introduces a lot of hard-to-track problems
## introduces a lot of hard-to-track problems.
## Comment out the following lines to enable OMEMO support
"eu.siacs.conversations.axolotl.*":
access_model: whitelist
## Avoid buggy clients to make their bookmarks public
+6 -6
View File
@@ -33,10 +33,10 @@
# from a client or from another Jabber server. So take this into
# account when setting this limit.
#
# Default: 32000
# Default: 65536 (or 8196 on Windows)
# Maximum: 268435456
#
#ERL_MAX_PORTS=32000
#ERL_MAX_PORTS=65536
#.
#' FIREWALL_WINDOW: Range of allowed ports to pass through a firewall
@@ -85,10 +85,10 @@
# Erlang, and therefore not related to the operating system processes, you do
# not have to worry about allowing a huge number of them.
#
# Default: 250000
# Default: 262144
# Maximum: 268435456
#
#ERL_PROCESSES=250000
#ERL_PROCESSES=262144
#.
#' ERL_MAX_ETS_TABLES: Maximum number of ETS and Mnesia tables
@@ -99,9 +99,9 @@
# You can safely increase this limit when starting ejabberd. It impacts memory
# consumption but the difference will be quite small.
#
# Default: 1400
# Default: 2053
#
#ERL_MAX_ETS_TABLES=1400
#ERL_MAX_ETS_TABLES=2053
#.
#' ERL_OPTIONS: Additional Erlang options
+9 -11
View File
@@ -41,19 +41,17 @@ case $(id -un) in
esac
# parse command line parameters
for arg; do
case $arg in
-n|--node) ERLANG_NODE_ARG=$2; shift;;
-s|--spool) SPOOL_DIR=$2; shift;;
-l|--logs) LOGS_DIR=$2; shift;;
-f|--config) EJABBERD_CONFIG_PATH=$2; shift;;
-c|--ctl-config) EJABBERDCTL_CONFIG_PATH=$2; shift;;
-d|--config-dir) ETC_DIR=$2; shift;;
-t|--no-timeout) NO_TIMEOUT="--no-timeout";;
--) :;;
while [ $# -gt 0 ]; do
case $1 in
-n|--node) ERLANG_NODE_ARG=$2; shift 2;;
-s|--spool) SPOOL_DIR=$2; shift 2;;
-l|--logs) LOGS_DIR=$2; shift 2;;
-f|--config) EJABBERD_CONFIG_PATH=$2; shift 2;;
-c|--ctl-config) EJABBERDCTL_CONFIG_PATH=$2; shift 2;;
-d|--config-dir) ETC_DIR=$2; shift 2;;
-t|--no-timeout) NO_TIMEOUT="--no-timeout"; shift;;
*) break;;
esac
shift
done
# define ejabberd variables if not already defined from the command line
+1 -1
View File
@@ -70,7 +70,7 @@ done
echo '7. compile ejabberd'
gmake
for A in mod_irc mod_muc mod_pubsub; do
for A in mod_muc mod_pubsub; do
(cd $A; gmake)
done
-1
View File
@@ -51,7 +51,6 @@ override_acls.
{mod_offline, []},
{mod_echo, [{host, "echo.jabber.dbc.mtview.ca.us"}]},
{mod_private, []},
% {mod_irc, []},
{mod_muc, []},
{mod_pubsub, []},
{mod_time, []},
-72
View File
@@ -1,72 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2018 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License along
%%% with this program; if not, write to the Free Software Foundation, Inc.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%----------------------------------------------------------------------
-ifndef(EJABBERD_HRL).
-define(EJABBERD_HRL, true).
-define(VERSION, ejabberd_config:get_version()).
-define(MYHOSTS, ejabberd_config:get_myhosts()).
-define(MYNAME, hd(ejabberd_config:get_myhosts())).
-define(MYLANG, ejabberd_config:get_mylang()).
-define(MSGS_DIR, filename:join(["priv", "msgs"])).
-define(SQL_DIR, filename:join(["priv", "sql"])).
-define(CONFIG_PATH, <<"ejabberd.yml">>).
-define(LOG_PATH, "ejabberd.log").
-define(EJABBERD_URI, <<"http://www.process-one.net/en/ejabberd/">>).
-define(COPYRIGHT, "Copyright (c) ProcessOne").
%%-define(DBGFSM, true).
-record(scram,
{storedkey = <<"">>,
serverkey = <<"">>,
salt = <<"">>,
iterationcount = 0 :: integer()}).
-type scram() :: #scram{}.
-define(SCRAM_DEFAULT_ITERATION_COUNT, 4096).
-ifdef(ERL_DEPRECATED_TYPES).
-define(TDICT, dict()).
-define(TGB_TREE, gb_tree()).
-define(TGB_SET, gb_set()).
-define(TQUEUE, queue()).
-else.
-define(TDICT, dict:dict()).
-define(TGB_TREE, gb_trees:tree()).
-define(TGB_SET, gb_sets:set()).
-define(TQUEUE, queue:queue()).
-endif.
-endif.
+5 -2
View File
@@ -31,7 +31,10 @@
port = 5280 :: inet:port_number(),
opts = [] :: list(),
tp = http :: protocol(),
headers = [] :: [{atom() | binary(), binary()}]}).
headers = [] :: [{atom() | binary(), binary()}],
length = 0 :: non_neg_integer(),
sockmod :: gen_tcp | fast_tls,
socket :: inet:socket() | fast_tls:tls_socket()}).
-record(ws,
{socket :: inet:socket() | fast_tls:tls_socket(),
@@ -46,6 +49,6 @@
buf :: binary(),
http_opts = [] :: list()}).
-type method() :: 'GET' | 'HEAD' | 'DELETE' | 'OPTIONS' | 'PUT' | 'POST' | 'TRACE'.
-type method() :: 'GET' | 'HEAD' | 'DELETE' | 'OPTIONS' | 'PUT' | 'POST' | 'TRACE' | 'PATCH'.
-type protocol() :: http | https.
-type http_request() :: #request{}.
-501
View File
@@ -1,501 +0,0 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2018 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License along
%%% with this program; if not, write to the Free Software Foundation, Inc.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%----------------------------------------------------------------------
-include("ns.hrl").
-include("fxml.hrl").
-define(STANZA_ERROR(Code, Type, Condition),
#xmlel{name = <<"error">>,
attrs = [{<<"code">>, Code}, {<<"type">>, Type}],
children =
[#xmlel{name = Condition,
attrs = [{<<"xmlns">>, ?NS_STANZAS}],
children = []}]}).
-define(ERR_BAD_FORMAT,
?STANZA_ERROR(<<"406">>, <<"modify">>,
<<"bad-format">>)).
-define(ERR_BAD_REQUEST,
?STANZA_ERROR(<<"400">>, <<"modify">>,
<<"bad-request">>)).
-define(ERR_CONFLICT,
?STANZA_ERROR(<<"409">>, <<"cancel">>, <<"conflict">>)).
-define(ERR_FEATURE_NOT_IMPLEMENTED,
?STANZA_ERROR(<<"501">>, <<"cancel">>,
<<"feature-not-implemented">>)).
-define(ERR_FORBIDDEN,
?STANZA_ERROR(<<"403">>, <<"auth">>, <<"forbidden">>)).
-define(ERR_GONE,
?STANZA_ERROR(<<"302">>, <<"modify">>, <<"gone">>)).
-define(ERR_INTERNAL_SERVER_ERROR,
?STANZA_ERROR(<<"500">>, <<"wait">>,
<<"internal-server-error">>)).
-define(ERR_ITEM_NOT_FOUND,
?STANZA_ERROR(<<"404">>, <<"cancel">>,
<<"item-not-found">>)).
-define(ERR_JID_MALFORMED,
?STANZA_ERROR(<<"400">>, <<"modify">>,
<<"jid-malformed">>)).
-define(ERR_NOT_ACCEPTABLE,
?STANZA_ERROR(<<"406">>, <<"modify">>,
<<"not-acceptable">>)).
-define(ERR_NOT_ALLOWED,
?STANZA_ERROR(<<"405">>, <<"cancel">>,
<<"not-allowed">>)).
-define(ERR_NOT_AUTHORIZED,
?STANZA_ERROR(<<"401">>, <<"auth">>,
<<"not-authorized">>)).
-define(ERR_PAYMENT_REQUIRED,
?STANZA_ERROR(<<"402">>, <<"auth">>,
<<"payment-required">>)).
-define(ERR_RECIPIENT_UNAVAILABLE,
?STANZA_ERROR(<<"404">>, <<"wait">>,
<<"recipient-unavailable">>)).
-define(ERR_REDIRECT,
?STANZA_ERROR(<<"302">>, <<"modify">>, <<"redirect">>)).
-define(ERR_REGISTRATION_REQUIRED,
?STANZA_ERROR(<<"407">>, <<"auth">>,
<<"registration-required">>)).
-define(ERR_REMOTE_SERVER_NOT_FOUND,
?STANZA_ERROR(<<"404">>, <<"cancel">>,
<<"remote-server-not-found">>)).
-define(ERR_REMOTE_SERVER_TIMEOUT,
?STANZA_ERROR(<<"504">>, <<"wait">>,
<<"remote-server-timeout">>)).
-define(ERR_RESOURCE_CONSTRAINT,
?STANZA_ERROR(<<"500">>, <<"wait">>,
<<"resource-constraint">>)).
-define(ERR_SERVICE_UNAVAILABLE,
?STANZA_ERROR(<<"503">>, <<"cancel">>,
<<"service-unavailable">>)).
-define(ERR_SUBSCRIPTION_REQUIRED,
?STANZA_ERROR(<<"407">>, <<"auth">>,
<<"subscription-required">>)).
-define(ERR_UNEXPECTED_REQUEST,
?STANZA_ERROR(<<"400">>, <<"wait">>,
<<"unexpected-request">>)).
-define(ERR_UNEXPECTED_REQUEST_CANCEL,
?STANZA_ERROR(<<"401">>, <<"cancel">>,
<<"unexpected-request">>)).
%-define(ERR_,
% ?STANZA_ERROR("", "", "")).
-define(STANZA_ERRORT(Code, Type, Condition, Lang,
Text),
#xmlel{name = <<"error">>,
attrs = [{<<"code">>, Code}, {<<"type">>, Type}],
children =
[#xmlel{name = Condition,
attrs = [{<<"xmlns">>, ?NS_STANZAS}], children = []},
#xmlel{name = <<"text">>,
attrs = [{<<"xmlns">>, ?NS_STANZAS}],
children =
[{xmlcdata,
translate:translate(Lang, Text)}]}]}).
-define(ERRT_BAD_FORMAT(Lang, Text),
?STANZA_ERRORT(<<"406">>, <<"modify">>,
<<"bad-format">>, Lang, Text)).
-define(ERRT_BAD_REQUEST(Lang, Text),
?STANZA_ERRORT(<<"400">>, <<"modify">>,
<<"bad-request">>, Lang, Text)).
-define(ERRT_CONFLICT(Lang, Text),
?STANZA_ERRORT(<<"409">>, <<"cancel">>, <<"conflict">>,
Lang, Text)).
-define(ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Text),
?STANZA_ERRORT(<<"501">>, <<"cancel">>,
<<"feature-not-implemented">>, Lang, Text)).
-define(ERRT_FORBIDDEN(Lang, Text),
?STANZA_ERRORT(<<"403">>, <<"auth">>, <<"forbidden">>,
Lang, Text)).
-define(ERRT_GONE(Lang, Text),
?STANZA_ERRORT(<<"302">>, <<"modify">>, <<"gone">>,
Lang, Text)).
-define(ERRT_INTERNAL_SERVER_ERROR(Lang, Text),
?STANZA_ERRORT(<<"500">>, <<"wait">>,
<<"internal-server-error">>, Lang, Text)).
-define(ERRT_ITEM_NOT_FOUND(Lang, Text),
?STANZA_ERRORT(<<"404">>, <<"cancel">>,
<<"item-not-found">>, Lang, Text)).
-define(ERRT_JID_MALFORMED(Lang, Text),
?STANZA_ERRORT(<<"400">>, <<"modify">>,
<<"jid-malformed">>, Lang, Text)).
-define(ERRT_NOT_ACCEPTABLE(Lang, Text),
?STANZA_ERRORT(<<"406">>, <<"modify">>,
<<"not-acceptable">>, Lang, Text)).
-define(ERRT_NOT_ALLOWED(Lang, Text),
?STANZA_ERRORT(<<"405">>, <<"cancel">>,
<<"not-allowed">>, Lang, Text)).
-define(ERRT_NOT_AUTHORIZED(Lang, Text),
?STANZA_ERRORT(<<"401">>, <<"auth">>,
<<"not-authorized">>, Lang, Text)).
-define(ERRT_PAYMENT_REQUIRED(Lang, Text),
?STANZA_ERRORT(<<"402">>, <<"auth">>,
<<"payment-required">>, Lang, Text)).
-define(ERRT_RECIPIENT_UNAVAILABLE(Lang, Text),
?STANZA_ERRORT(<<"404">>, <<"wait">>,
<<"recipient-unavailable">>, Lang, Text)).
-define(ERRT_REDIRECT(Lang, Text),
?STANZA_ERRORT(<<"302">>, <<"modify">>, <<"redirect">>,
Lang, Text)).
-define(ERRT_REGISTRATION_REQUIRED(Lang, Text),
?STANZA_ERRORT(<<"407">>, <<"auth">>,
<<"registration-required">>, Lang, Text)).
-define(ERRT_REMOTE_SERVER_NOT_FOUND(Lang, Text),
?STANZA_ERRORT(<<"404">>, <<"cancel">>,
<<"remote-server-not-found">>, Lang, Text)).
-define(ERRT_REMOTE_SERVER_TIMEOUT(Lang, Text),
?STANZA_ERRORT(<<"504">>, <<"wait">>,
<<"remote-server-timeout">>, Lang, Text)).
-define(ERRT_RESOURCE_CONSTRAINT(Lang, Text),
?STANZA_ERRORT(<<"500">>, <<"wait">>,
<<"resource-constraint">>, Lang, Text)).
-define(ERRT_SERVICE_UNAVAILABLE(Lang, Text),
?STANZA_ERRORT(<<"503">>, <<"cancel">>,
<<"service-unavailable">>, Lang, Text)).
-define(ERRT_SUBSCRIPTION_REQUIRED(Lang, Text),
?STANZA_ERRORT(<<"407">>, <<"auth">>,
<<"subscription-required">>, Lang, Text)).
-define(ERRT_UNEXPECTED_REQUEST(Lang, Text),
?STANZA_ERRORT(<<"400">>, <<"wait">>,
<<"unexpected-request">>, Lang, Text)).
-define(ERR_AUTH_NO_RESOURCE_PROVIDED(Lang),
?ERRT_NOT_ACCEPTABLE(Lang, <<"No resource provided">>)).
-define(ERR_AUTH_BAD_RESOURCE_FORMAT(Lang),
?ERRT_NOT_ACCEPTABLE(Lang,
<<"Illegal resource format">>)).
-define(ERR_AUTH_RESOURCE_CONFLICT(Lang),
?ERRT_CONFLICT(Lang, <<"Resource conflict">>)).
-define(STREAM_ERROR(Condition, Cdata),
#xmlel{name = <<"stream:error">>, attrs = [],
children =
[#xmlel{name = Condition,
attrs = [{<<"xmlns">>, ?NS_STREAMS}],
children = [{xmlcdata, Cdata}]}]}).
-define(SERR_BAD_FORMAT,
?STREAM_ERROR(<<"bad-format">>, <<"">>)).
-define(SERR_BAD_NAMESPACE_PREFIX,
?STREAM_ERROR(<<"bad-namespace-prefix">>, <<"">>)).
-define(SERR_CONFLICT,
?STREAM_ERROR(<<"conflict">>, <<"">>)).
-define(SERR_CONNECTION_TIMEOUT,
?STREAM_ERROR(<<"connection-timeout">>, <<"">>)).
-define(SERR_HOST_GONE,
?STREAM_ERROR(<<"host-gone">>, <<"">>)).
-define(SERR_HOST_UNKNOWN,
?STREAM_ERROR(<<"host-unknown">>, <<"">>)).
-define(SERR_IMPROPER_ADDRESSING,
?STREAM_ERROR(<<"improper-addressing">>, <<"">>)).
-define(SERR_INTERNAL_SERVER_ERROR,
?STREAM_ERROR(<<"internal-server-error">>, <<"">>)).
-define(SERR_INVALID_FROM,
?STREAM_ERROR(<<"invalid-from">>, <<"">>)).
-define(SERR_INVALID_ID,
?STREAM_ERROR(<<"invalid-id">>, <<"">>)).
-define(SERR_INVALID_NAMESPACE,
?STREAM_ERROR(<<"invalid-namespace">>, <<"">>)).
-define(SERR_INVALID_XML,
?STREAM_ERROR(<<"invalid-xml">>, <<"">>)).
-define(SERR_NOT_AUTHORIZED,
?STREAM_ERROR(<<"not-authorized">>, <<"">>)).
-define(SERR_POLICY_VIOLATION,
?STREAM_ERROR(<<"policy-violation">>, <<"">>)).
-define(SERR_REMOTE_CONNECTION_FAILED,
?STREAM_ERROR(<<"remote-connection-failed">>, <<"">>)).
-define(SERR_RESOURSE_CONSTRAINT,
?STREAM_ERROR(<<"resource-constraint">>, <<"">>)).
-define(SERR_RESTRICTED_XML,
?STREAM_ERROR(<<"restricted-xml">>, <<"">>)).
-define(SERR_SEE_OTHER_HOST(Host),
?STREAM_ERROR(<<"see-other-host">>, Host)).
-define(SERR_SYSTEM_SHUTDOWN,
?STREAM_ERROR(<<"system-shutdown">>, <<"">>)).
-define(SERR_UNSUPPORTED_ENCODING,
?STREAM_ERROR(<<"unsupported-encoding">>, <<"">>)).
-define(SERR_UNSUPPORTED_STANZA_TYPE,
?STREAM_ERROR(<<"unsupported-stanza-type">>, <<"">>)).
-define(SERR_UNSUPPORTED_VERSION,
?STREAM_ERROR(<<"unsupported-version">>, <<"">>)).
-define(SERR_XML_NOT_WELL_FORMED,
?STREAM_ERROR(<<"xml-not-well-formed">>, <<"">>)).
%-define(SERR_,
% ?STREAM_ERROR("", "")).
-define(STREAM_ERRORT(Condition, Cdata, Lang, Text),
#xmlel{name = <<"stream:error">>, attrs = [],
children =
[#xmlel{name = Condition,
attrs = [{<<"xmlns">>, ?NS_STREAMS}],
children = [{xmlcdata, Cdata}]},
#xmlel{name = <<"text">>,
attrs =
[{<<"xml:lang">>, Lang},
{<<"xmlns">>, ?NS_STREAMS}],
children =
[{xmlcdata,
translate:translate(Lang, Text)}]}]}).
-define(SERRT_BAD_FORMAT(Lang, Text),
?STREAM_ERRORT(<<"bad-format">>, <<"">>, Lang, Text)).
-define(SERRT_BAD_NAMESPACE_PREFIX(Lang, Text),
?STREAM_ERRORT(<<"bad-namespace-prefix">>, <<"">>, Lang,
Text)).
-define(SERRT_CONFLICT(Lang, Text),
?STREAM_ERRORT(<<"conflict">>, <<"">>, Lang, Text)).
-define(SERRT_CONNECTION_TIMEOUT(Lang, Text),
?STREAM_ERRORT(<<"connection-timeout">>, <<"">>, Lang,
Text)).
-define(SERRT_HOST_GONE(Lang, Text),
?STREAM_ERRORT(<<"host-gone">>, <<"">>, Lang, Text)).
-define(SERRT_HOST_UNKNOWN(Lang, Text),
?STREAM_ERRORT(<<"host-unknown">>, <<"">>, Lang, Text)).
-define(SERRT_IMPROPER_ADDRESSING(Lang, Text),
?STREAM_ERRORT(<<"improper-addressing">>, <<"">>, Lang,
Text)).
-define(SERRT_INTERNAL_SERVER_ERROR(Lang, Text),
?STREAM_ERRORT(<<"internal-server-error">>, <<"">>,
Lang, Text)).
-define(SERRT_INVALID_FROM(Lang, Text),
?STREAM_ERRORT(<<"invalid-from">>, <<"">>, Lang, Text)).
-define(SERRT_INVALID_ID(Lang, Text),
?STREAM_ERRORT(<<"invalid-id">>, <<"">>, Lang, Text)).
-define(SERRT_INVALID_NAMESPACE(Lang, Text),
?STREAM_ERRORT(<<"invalid-namespace">>, <<"">>, Lang,
Text)).
-define(SERRT_INVALID_XML(Lang, Text),
?STREAM_ERRORT(<<"invalid-xml">>, <<"">>, Lang, Text)).
-define(SERRT_NOT_AUTHORIZED(Lang, Text),
?STREAM_ERRORT(<<"not-authorized">>, <<"">>, Lang,
Text)).
-define(SERRT_POLICY_VIOLATION(Lang, Text),
?STREAM_ERRORT(<<"policy-violation">>, <<"">>, Lang,
Text)).
-define(SERRT_REMOTE_CONNECTION_FAILED(Lang, Text),
?STREAM_ERRORT(<<"remote-connection-failed">>, <<"">>,
Lang, Text)).
-define(SERRT_RESOURSE_CONSTRAINT(Lang, Text),
?STREAM_ERRORT(<<"resource-constraint">>, <<"">>, Lang,
Text)).
-define(SERRT_RESTRICTED_XML(Lang, Text),
?STREAM_ERRORT(<<"restricted-xml">>, <<"">>, Lang,
Text)).
-define(SERRT_SEE_OTHER_HOST(Host, Lang, Text),
?STREAM_ERRORT(<<"see-other-host">>, Host, Lang, Text)).
-define(SERRT_SYSTEM_SHUTDOWN(Lang, Text),
?STREAM_ERRORT(<<"system-shutdown">>, <<"">>, Lang,
Text)).
-define(SERRT_UNSUPPORTED_ENCODING(Lang, Text),
?STREAM_ERRORT(<<"unsupported-encoding">>, <<"">>, Lang,
Text)).
-define(SERRT_UNSUPPORTED_STANZA_TYPE(Lang, Text),
?STREAM_ERRORT(<<"unsupported-stanza-type">>, <<"">>,
Lang, Text)).
-define(SERRT_UNSUPPORTED_VERSION(Lang, Text),
?STREAM_ERRORT(<<"unsupported-version">>, <<"">>, Lang,
Text)).
-define(SERRT_XML_NOT_WELL_FORMED(Lang, Text),
?STREAM_ERRORT(<<"xml-not-well-formed">>, <<"">>, Lang,
Text)).
-record(jid, {user = <<"">> :: binary(),
server = <<"">> :: binary(),
resource = <<"">> :: binary(),
luser = <<"">> :: binary(),
lserver = <<"">> :: binary(),
lresource = <<"">> :: binary()}).
-type(jid() :: #jid{}).
-type(ljid() :: {binary(), binary(), binary()}).
-record(iq, {id = <<"">> :: binary(),
type = get :: get | set | result | error,
xmlns = <<"">> :: binary(),
lang = <<"">> :: binary(),
sub_el = #xmlel{} :: xmlel() | [xmlel()]}).
-type(iq_get()
:: #iq{
id :: binary(),
type :: get,
xmlns :: binary(),
lang :: binary(),
sub_el :: xmlel()
}
).
-type(iq_set()
:: #iq{
id :: binary(),
type :: set,
xmlns :: binary(),
lang :: binary(),
sub_el :: xmlel()
}
).
-type iq_request() :: iq_get() | iq_set().
-type(iq_result()
:: #iq{
id :: binary(),
type :: result,
xmlns :: binary(),
lang :: binary(),
sub_el :: [xmlel()]
}
).
-type(iq_error()
:: #iq{
id :: binary(),
type :: error,
xmlns :: binary(),
lang :: binary(),
sub_el :: [xmlel()]
}
).
-type iq_reply() :: iq_result() | iq_error() .
-type(iq() :: iq_request() | iq_reply()).
-record(rsm_in, {max :: integer() | error | undefined,
direction :: before | aft | undefined,
id :: binary() | undefined,
index :: integer() | error | undefined}).
-record(rsm_out, {count :: integer() | undefined,
index :: integer() | undefined,
first :: binary() | undefined,
last :: binary() | undefined}).
-type(rsm_in() :: #rsm_in{}).
-type(rsm_out() :: #rsm_out{}).
-type broadcast() :: {broadcast, broadcast_data()}.
-type broadcast_data() ::
{rebind, pid(), binary()} | %% ejabberd_c2s
{item, ljid(), mod_roster:subscription()} | %% mod_roster/mod_shared_roster
{exit, binary()} | %% mod_roster/mod_shared_roster
{privacy_list, mod_privacy:userlist(), binary()} | %% mod_privacy
{blocking, unblock_all | {block | unblock, [ljid()]}}. %% mod_blocking
-record(xmlelement, {name = "" :: string(),
attrs = [] :: [{string(), string()}],
children = [] :: [{xmlcdata, iodata()} | xmlelement()]}).
-type xmlelement() :: #xmlelement{}.
+3
View File
@@ -42,3 +42,6 @@
false -> ok;
_ -> 'Elixir.Logger':bare_log(error, io_lib:format(Format, Args), [?MODULE])
end).
%% Uncomment if you want to debug p1_fsm/gen_fsm
%%-define(DBGFSM, true).
+10 -10
View File
@@ -18,8 +18,6 @@
%%%
%%%----------------------------------------------------------------------
-include("ejabberd.hrl").
-define(MAX_USERS_DEFAULT, 200).
-define(SETS, gb_sets).
@@ -63,9 +61,11 @@
max_users = ?MAX_USERS_DEFAULT :: non_neg_integer() | none,
logging = false :: boolean(),
vcard = <<"">> :: binary(),
captcha_whitelist = (?SETS):empty() :: ?TGB_SET,
vcard_xupdate = undefined :: undefined | external | binary(),
captcha_whitelist = (?SETS):empty() :: gb_sets:set(),
mam = false :: boolean(),
pubsub = <<"">> :: binary()
pubsub = <<"">> :: binary(),
lang = ejabberd_config:get_mylang() :: binary()
}).
-type config() :: #config{}.
@@ -105,13 +105,13 @@
access = {none,none,none,none} :: {atom(), atom(), atom(), atom()},
jid = #jid{} :: jid(),
config = #config{} :: config(),
users = (?DICT):new() :: ?TDICT,
subscribers = (?DICT):new() :: ?TDICT,
subscriber_nicks = (?DICT):new() :: ?TDICT,
users = (?DICT):new() :: dict:dict(),
subscribers = (?DICT):new() :: dict:dict(),
subscriber_nicks = (?DICT):new() :: dict:dict(),
last_voice_request_time = treap:empty() :: treap:treap(),
robots = (?DICT):new() :: ?TDICT,
nicks = (?DICT):new() :: ?TDICT,
affiliations = (?DICT):new() :: ?TDICT,
robots = (?DICT):new() :: dict:dict(),
nicks = (?DICT):new() :: dict:dict(),
affiliations = (?DICT):new() :: dict:dict(),
history :: lqueue(),
subject = [] :: [text()],
subject_author = <<"">> :: binary(),
-2
View File
@@ -18,8 +18,6 @@
%%%
%%%----------------------------------------------------------------------
-include("ejabberd.hrl").
%% -------------------------------
%% Pubsub constants
-define(ERR_EXTENDED(E, C), mod_pubsub:extended_error(E, C)).
+6 -13
View File
@@ -18,18 +18,11 @@
%%%
%%%----------------------------------------------------------------------
-type conn_param() :: {binary(), binary(), inet:port_number(), binary()} |
{binary(), binary(), inet:port_number()} |
{binary(), binary()} |
{binary()}.
-record(scram, {storedkey = <<"">> :: binary(),
serverkey = <<"">> :: binary(),
salt = <<"">> :: binary(),
iterationcount = 0 :: integer()}).
-type irc_data() :: [{username, binary()} | {connections_params, [conn_param()]}].
-type scram() :: #scram{}.
-record(irc_connection,
{jid_server_host = {#jid{}, <<"">>, <<"">>} :: {jid(), binary(), binary()},
pid = self() :: pid()}).
-record(irc_custom,
{us_host = {{<<"">>, <<"">>}, <<"">>} :: {{binary(), binary()},
binary()},
data = [] :: irc_data()}).
-define(SCRAM_DEFAULT_ITERATION_COUNT, 4096).
-17
View File
@@ -84,20 +84,3 @@ EOF
AC_MSG_RESULT([ok])
fi
]) dnl ERLANG_VERSION_CHECK
AC_DEFUN([ERLANG_DEPRECATED_TYPES_CHECK],
[ AC_MSG_CHECKING([whether Erlang is using deprecated types])
cat > conftest.erl <<EOF
-module(conftest).
-record(state, {host = dict:new() :: dict:dict()}).
EOF
if $ERLC conftest.erl > /dev/null 2>&1; then
AC_MSG_RESULT([no])
AC_SUBST(erlang_deprecated_types, false)
else
AC_MSG_RESULT([yes])
AC_SUBST(erlang_deprecated_types, true)
fi
])
+3 -3
View File
@@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do
def project do
[app: :ejabberd,
version: "18.3.0",
version: "18.6.0",
description: description(),
elixir: "~> 1.4",
elixirc_paths: ["lib"],
@@ -61,7 +61,7 @@ defmodule Ejabberd.Mixfile do
[{:lager, "~> 3.4.0"},
{:p1_utils, "~> 1.0"},
{:fast_xml, "~> 1.1"},
{:xmpp, "~> 1.1"},
{:xmpp, "~> 1.2"},
{:cache_tab, "~> 1.0"},
{:stringprep, "~> 1.0"},
{:fast_yaml, "~> 1.0"},
@@ -125,7 +125,7 @@ defmodule Ejabberd.Mixfile do
defp vars do
case :file.consult("vars.config") do
{:ok,config} -> config
_ -> [zlib: true, iconv: true]
_ -> [zlib: true, iconv: false]
end
end
+17 -17
View File
@@ -1,35 +1,35 @@
%{
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
"cache_tab": {:hex, :cache_tab, "1.0.13", "e09857af9b7ba89428227d3801256852cb0d51a4de47e4edcb160d96cc96f8eb", [:rebar3], [{:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [:mix], [], "hexpm"},
"earmark": {:hex, :earmark, "1.2.4", "99b637c62a4d65a20a9fb674b8cffb8baa771c04605a80c911c4418c69b75439", [:mix], [], "hexpm"},
"eimp": {:hex, :eimp, "1.0.3", "e40108d622d672cf6003d279d98fc46a98df182dbe8756857896ffd28883090d", [:rebar3], [{:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"cache_tab": {:hex, :cache_tab, "1.0.14", "e68d24789ff596a7cb4f08780f72a725f3f18e93dee486559b261df904234871", [:rebar3], [{:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"distillery": {:hex, :distillery, "1.5.3", "b2f4fc34ec71ab4f1202a796f9290e068883b042319aa8c9aa45377ecac8597a", [:mix], [], "hexpm"},
"earmark": {:hex, :earmark, "1.2.5", "4d21980d5d2862a2e13ec3c49ad9ad783ffc7ca5769cf6ff891a4553fbaae761", [:mix], [], "hexpm"},
"eimp": {:hex, :eimp, "1.0.6", "087fc92daf7b03bac4aada8ea6063d9034d4b9088be24e050ff73323c8444a04", [:rebar3], [{:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"epam": {:hex, :epam, "1.0.4", "2a5e40cbf9b2cf41df515782894c3b33c81b8ad32fff2fc847c3f725071dfaed", [:rebar3], [], "hexpm"},
"eredis": {:hex, :eredis, "1.1.0", "8d8d74496f35216679b97726b75fb1c8715e99dd7f3ef9f9824a2264c3e0aac0", [:rebar3], [], "hexpm"},
"esip": {:hex, :esip, "1.0.22", "3e387312614762fb84d3f77ba4f17650faf52510482521300b3d98ecdcbec21d", [:rebar3], [{:fast_tls, "1.0.21", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.21", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm"},
"esip": {:hex, :esip, "1.0.24", "c14efd0817012721dad3d1c36816e4d113adc86d185503f8c08f7faa11082018", [:rebar3], [{:fast_tls, "1.0.23", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.23", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.18.3", "f4b0e4a2ec6f333dccf761838a4b253d75e11f714b85ae271c9ae361367897b7", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"},
"ezlib": {:hex, :ezlib, "1.0.4", "2434e4bb549cb060d5ac02261ba48fbe1a69b2ae4e1bf7485a3b27b3f3ec618d", [:rebar3], [], "hexpm"},
"fast_tls": {:hex, :fast_tls, "1.0.21", "7005fe030c0472643314c9c31e7627bb296dcb96a9ce0b5dd8ccb34273f4c1ff", [:rebar3], [{:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_xml": {:hex, :fast_xml, "1.1.29", "c6356d28f0f76ffefc68b5eb65916f0b8ca513bab71db8ad95bd8577c47e30e2", [:rebar3], [{:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_yaml": {:hex, :fast_yaml, "1.0.13", "adcb8db20bb96d4e56b63b48c75d47ca15a6bd409da0200ffbd32db382131e22", [:rebar3], [{:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_tls": {:hex, :fast_tls, "1.0.23", "5fd44b84b60f1caeb82270aae842599997e2ef70a628c954e494a6613cc6f026", [:rebar3], [{:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_xml": {:hex, :fast_xml, "1.1.31", "7d85dd50533737adbaa95472c962ff8ad3d434ced1dbd04b83465edc2a4363b6", [:rebar3], [{:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"fast_yaml": {:hex, :fast_yaml, "1.0.15", "55a8ff117e2bb44fda5ca96c53473799f864c865dc63a3b598cb626001207cab", [:rebar3], [{:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm"},
"hamcrest": {:hex, :basho_hamcrest, "0.4.1", "fb7b2c92d252a1e9db936750b86089addaebeb8f87967fb4bbdda61e8863338e", [:make, :mix, :rebar3], [], "hexpm"},
"iconv": {:hex, :iconv, "1.0.7", "f81eb6b8c977b1fd078515937fdce64292d64c6102353fbbfe57db580f4689d1", [:rebar3], [{:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"iconv": {:hex, :iconv, "1.0.8", "772a19153e9546b9f17206931ece321220feccfd0b3f5a5509dc92108326c2f9", [:rebar3], [{:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"jiffy": {:hex, :jiffy, "0.14.13", "225a9a35e26417832c611526567194b4d3adc4f0dfa5f2f7008f4684076f2a01", [:rebar3], [], "hexpm"},
"jose": {:hex, :jose, "1.8.4", "7946d1e5c03a76ac9ef42a6e6a20001d35987afd68c2107bcd8f01a84e75aa73", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm"},
"lager": {:hex, :lager, "3.4.2", "150b9a17b23ae6d3265cc10dc360747621cf217b7a22b8cddf03b2909dbf7aa5", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm"},
"luerl": {:hex, :luerl, "0.3.1", "5412807630aac1aaf59ffe5a1bc09259c447b4faeb1d3fe2d4ef41b87676cb04", [:rebar3], [], "hexpm"},
"meck": {:hex, :meck, "0.8.9", "64c5c0bd8bcca3a180b44196265c8ed7594e16bcc845d0698ec6b4e577f48188", [:rebar3], [], "hexpm"},
"meck": {:hex, :meck, "0.8.10", "455aaef8403be46752272206613e7a15467c014d40994b22fb54cde4d1ff7075", [:rebar3], [], "hexpm"},
"moka": {:git, "https://github.com/processone/moka.git", "3eed3a6dd7dedb70a6cd18f86c7561a18626eb3b", [tag: "1.0.5c"]},
"p1_mysql": {:hex, :p1_mysql, "1.0.5", "2a9644d27050a6aa9e7eb70a0620043f93655212b15f3620dc12f2fbd1a8c43a", [:rebar3], [], "hexpm"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.2", "cc381038920e3d34ef32aa10ba7eb637bdff38a946748c4fd99329ff484a3889", [:rebar3], [], "hexpm"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.5", "1e1bef6e6d906e10552a608b9fe5ef39b3099caf0f44c07d3d9e18ac4dee34d1", [:rebar3], [], "hexpm"},
"p1_utils": {:hex, :p1_utils, "1.0.11", "a471f80644d4b464fa67572affddda7e95df5d4b099624b8907f5726e8a1769c", [:rebar3], [], "hexpm"},
"p1_mysql": {:hex, :p1_mysql, "1.0.6", "1fb48a907a7fe214a78be15a08f8ebfae2db424c4d9886891a298a395cc3afce", [:rebar3], [], "hexpm"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.3", "fbd91ba86bd7f03d2a4f6e62affa86bab9930abfd6b473d61eefb148f246cd46", [:rebar3], [], "hexpm"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.6", "631004602b06ca6f55d759001f180185685c7097e583f3b0f7dd9b8e05ba5db1", [:rebar3], [], "hexpm"},
"p1_utils": {:hex, :p1_utils, "1.0.12", "4304223a2b78d8031e980ae18d6b6d83f764cf2a91c779b2df7cbdfde73acbf8", [:rebar3], [], "hexpm"},
"riak_pb": {:hex, :riak_pb, "2.3.2", "48ffbf66dbb3f136ab9a7134bac4e496754baa5ef58c4f50a61326736d996390", [:make, :mix, :rebar3], [{:hamcrest, "~> 0.4.1", [hex: :basho_hamcrest, repo: "hexpm", optional: false]}], "hexpm"},
"riakc": {:hex, :riakc, "2.5.3", "6132d9e687a0dfd314b2b24c4594302ca8b55568a5d733c491d8fb6cd4004763", [:make, :mix, :rebar3], [{:riak_pb, "~> 2.3", [hex: :riak_pb, repo: "hexpm", optional: false]}], "hexpm"},
"samerlib": {:git, "https://github.com/processone/samerlib", "fbbba035b1548ac4e681df00d61bf609645333a0", [tag: "0.8.0c"]},
"sqlite3": {:hex, :sqlite3, "1.1.6", "4ea71af0b45908b5f02c9b09e4c87177039ef404f20accb35049cd8924cc417c", [:rebar3], [], "hexpm"},
"stringprep": {:hex, :stringprep, "1.0.11", "002e6972ab36c35f3dd88c11725014e62608c45a00399c083681879973fa8026", [:rebar3], [{:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"stun": {:hex, :stun, "1.0.21", "087fb20497081927690ef9d70b5bd6f9f4bea256ad758c500842722c0b6bb6ab", [:rebar3], [{:fast_tls, "1.0.21", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"xmpp": {:hex, :xmpp, "1.1.20", "33ddcc698518061f5051b98a6f731eef9342799f0c276a9debdfffe85c32fe6d", [:rebar3], [{:fast_xml, "1.1.29", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.11", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.11", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm"},
"stringprep": {:hex, :stringprep, "1.0.12", "3364897b9a376b2fb5e429944fd34ca0b562b44c9e5acf4e0299564371a6fbef", [:rebar3], [{:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"stun": {:hex, :stun, "1.0.23", "79982f6a26dc65b58bb24082e8bbfba83a5228ddd6407753e9c3092fb45ba916", [:rebar3], [{:fast_tls, "1.0.23", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
"xmpp": {:hex, :xmpp, "1.2.1", "9c94ab556559dc6c3bf4963f756a02e9771dd220f5891d57fc30b76c3d71cb06", [:rebar3], [{:fast_xml, "1.1.31", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.12", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.12", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm"},
}
+1707 -1251
View File
File diff suppressed because it is too large Load Diff
+15 -19
View File
@@ -20,23 +20,23 @@
{deps, [{lager, ".*", {git, "https://github.com/erlang-lager/lager",
{tag, {if_version_above, "17", "3.4.2", "3.2.1"}}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.11"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.13"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.21"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.11"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.29"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.1.20"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.13"}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.12"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.14"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.23"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.12"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.31"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.2.1"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.15"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.8"}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.2"}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.3"}}},
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.8.4"}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.3"}}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.21"}}}},
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.22"}}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.6"}}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.23"}}}},
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.24"}}}},
{if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql",
{tag, "1.0.5"}}}},
{tag, "1.0.6"}}}},
{if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql",
{tag, "1.1.5"}}}},
{tag, "1.1.6"}}}},
{if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3",
{tag, "1.1.6"}}}},
{if_var_true, pam, {epam, ".*", {git, "https://github.com/processone/epam",
@@ -52,13 +52,13 @@
{if_not_rebar3, {if_var_true, elixir, {rebar_elixir_plugin, ".*",
{git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}},
{if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv",
{tag, "1.0.7"}}}},
{tag, "1.0.8"}}}},
{if_var_true, tools, {luerl, ".*", {git, "https://github.com/rvirding/luerl",
{tag, "v0.3"}}}},
{if_var_true, tools, {meck, "0.8.*", {git, "https://github.com/eproxus/meck",
{tag, "0.8.4"}}}},
{if_var_true, tools, {moka, ".*", {git, "https://github.com/processone/moka",
{tag, "1.0.5c"}}}},
{tag, "1.0.5d"}}}},
{if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis",
{tag, "v1.0.8"}}}}]}.
@@ -96,7 +96,6 @@
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}},
{if_var_match, db_type, mssql, {d, 'mssql'}},
{if_var_true, elixir, {d, 'ELIXIR_ENABLED'}},
{if_var_true, erlang_deprecated_types, {d, 'ERL_DEPRECATED_TYPES'}},
{if_have_fun, {crypto, strong_rand_bytes, 1}, {d, 'STRONG_RAND_BYTES'}},
{if_have_fun, {rand, uniform, 1}, {d, 'RAND_UNIFORM'}},
{if_have_fun, {gb_sets, iterator_from, 2}, {d, 'GB_SETS_ITERATOR_FROM'}},
@@ -165,9 +164,6 @@
{if_var_true, zlib, {"ezlib", []}},
{if_var_true, iconv, {"iconv", []}}]}.
{port_env, [{"CFLAGS", "-g -O2 -Wall"}]}.
{port_specs, [{"priv/lib/jid.so", ["c_src/jid.c"]}]}.
%% Local Variables:
%% mode: erlang
%% End:
+2 -12
View File
@@ -259,8 +259,8 @@ CREATE TABLE pubsub_item (
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
itemid text NOT NULL,
publisher text NOT NULL,
creation text NOT NULL,
modification text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
payload text NOT NULL DEFAULT ''
);
CREATE INDEX i_pubsub_item_itemid ON pubsub_item (itemid);
@@ -329,16 +329,6 @@ CREATE TABLE muc_room_subscribers (
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers(host, jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers(host, room, jid);
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
server_host text NOT NULL,
data text NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom (jid, host);
CREATE TABLE motd (
username text NOT NULL,
server_host text NOT NULL,
+2 -11
View File
@@ -236,8 +236,8 @@ CREATE TABLE pubsub_item (
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
itemid text NOT NULL,
publisher text NOT NULL,
creation text NOT NULL,
modification text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
payload text NOT NULL DEFAULT ''
);
CREATE INDEX i_pubsub_item_itemid ON pubsub_item (itemid);
@@ -302,15 +302,6 @@ CREATE TABLE muc_room_subscribers (
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers(host, jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers(host, room, jid);
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
data text NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom (jid, host);
CREATE TABLE motd (
username text PRIMARY KEY,
xml text,
+2 -12
View File
@@ -72,16 +72,6 @@ CREATE TABLE [dbo].[caps_features] (
CREATE CLUSTERED INDEX [caps_features_node_subnode] ON [caps_features] (node, subnode)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
CREATE TABLE [dbo].[irc_custom] (
[jid] [varchar] (255) NOT NULL,
[host] [varchar] (255) NOT NULL,
[data] [text] NOT NULL,
[created_at] [datetime] NOT NULL DEFAULT GETDATE()
) TEXTIMAGE_ON [PRIMARY];
CREATE UNIQUE CLUSTERED INDEX [irc_custom_jid_host] ON [irc_custom] (jid, host)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
CREATE TABLE [dbo].[last] (
[username] [varchar] (250) NOT NULL,
[seconds] [text] NOT NULL,
@@ -220,8 +210,8 @@ CREATE TABLE [dbo].[pubsub_item] (
[nodeid] [bigint] NULL,
[itemid] [varchar] (255) NOT NULL,
[publisher] [text] NOT NULL,
[creation] [text] NOT NULL,
[modification] [varchar] (255) NOT NULL,
[creation] [varchar] (32) NOT NULL,
[modification] [varchar] (32) NOT NULL,
[payload] [text] NOT NULL DEFAULT ''
) TEXTIMAGE_ON [PRIMARY];
+2 -12
View File
@@ -274,8 +274,8 @@ CREATE TABLE pubsub_item (
nodeid bigint,
itemid text NOT NULL,
publisher text NOT NULL,
creation text NOT NULL,
modification text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
payload text NOT NULL
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE INDEX i_pubsub_item_itemid ON pubsub_item(itemid(36));
@@ -345,16 +345,6 @@ CREATE TABLE muc_room_subscribers (
CREATE INDEX i_muc_room_subscribers_host_jid USING BTREE ON muc_room_subscribers(host, jid);
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
server_host text NOT NULL,
data text NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE UNIQUE INDEX i_irc_custom_jid_host USING BTREE ON irc_custom(jid(75), host(75));
CREATE TABLE motd (
username varchar(191) NOT NULL,
server_host text NOT NULL,
+2 -11
View File
@@ -251,8 +251,8 @@ CREATE TABLE pubsub_item (
nodeid bigint,
itemid text NOT NULL,
publisher text NOT NULL,
creation text NOT NULL,
modification text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
payload text NOT NULL
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE INDEX i_pubsub_item_itemid ON pubsub_item(itemid(36));
@@ -318,15 +318,6 @@ CREATE TABLE muc_room_subscribers (
CREATE INDEX i_muc_room_subscribers_host_jid USING BTREE ON muc_room_subscribers(host, jid);
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
data text NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE UNIQUE INDEX i_irc_custom_jid_host USING BTREE ON irc_custom(jid(75), host(75));
CREATE TABLE motd (
username varchar(191) PRIMARY KEY,
xml text,
+2 -15
View File
@@ -144,9 +144,6 @@
-- ALTER TABLE muc_online_users ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
-- ALTER TABLE muc_online_users ALTER COLUMN server_host DROP DEFAULT;
-- ALTER TABLE irc_custom ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
-- ALTER TABLE irc_custom ALTER COLUMN server_host DROP DEFAULT;
-- ALTER TABLE motd ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
-- ALTER TABLE motd DROP CONSTRAINT motd_pkey;
-- ALTER TABLE motd ADD PRIMARY KEY (server_host, username);
@@ -428,8 +425,8 @@ CREATE TABLE pubsub_item (
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
itemid text NOT NULL,
publisher text NOT NULL,
creation text NOT NULL,
modification text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
payload text NOT NULL DEFAULT ''
);
CREATE INDEX i_pubsub_item_itemid ON pubsub_item USING btree (itemid);
@@ -498,16 +495,6 @@ CREATE TABLE muc_room_subscribers (
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers USING btree (host, jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers USING btree (host, room, jid);
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
server_host text NOT NULL,
data text NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom USING btree (jid, host);
CREATE TABLE motd (
username text NOT NULL,
server_host text NOT NULL,
+2 -11
View File
@@ -254,8 +254,8 @@ CREATE TABLE pubsub_item (
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
itemid text NOT NULL,
publisher text NOT NULL,
creation text NOT NULL,
modification text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
payload text NOT NULL DEFAULT ''
);
CREATE INDEX i_pubsub_item_itemid ON pubsub_item USING btree (itemid);
@@ -320,15 +320,6 @@ CREATE TABLE muc_room_subscribers (
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers USING btree (host, jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers USING btree (host, room, jid);
CREATE TABLE irc_custom (
jid text NOT NULL,
host text NOT NULL,
data text NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom USING btree (jid, host);
CREATE TABLE motd (
username text PRIMARY KEY,
xml text,
+23 -12
View File
@@ -36,14 +36,13 @@
any_rules_allowed/3, transform_options/1, opt_type/1,
acl_rule_matches/3, acl_rule_verify/1, access_matches/3,
transform_access_rules_config/1,
parse_ip_netmask/1,
parse_ip_netmask/1, ip_matches_mask/3,
access_rules_validator/1, shaper_rules_validator/1,
normalize_spec/1, resolve_access/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("jid.hrl").
@@ -195,7 +194,7 @@ add_access(Host, Access, Rules) ->
-spec load_from_config() -> ok.
load_from_config() ->
Hosts = [global|?MYHOSTS],
Hosts = [global|ejabberd_config:get_myhosts()],
lists:foreach(
fun(Host) ->
ACLs = ejabberd_config:get_option(
@@ -447,13 +446,13 @@ acl_rule_matches({acl, Name}, Data, Host) ->
RawACLs = lists:map(fun(#acl{aclspec = R}) -> R end, ACLs),
any_acl_rules_matches(RawACLs, Data, Host);
acl_rule_matches({ip, {Net, Mask}}, #{ip := {IP, _Port}}, _Host) ->
is_ip_match(IP, Net, Mask);
ip_matches_mask(IP, Net, Mask);
acl_rule_matches({ip, {Net, Mask}}, #{ip := IP}, _Host) ->
is_ip_match(IP, Net, Mask);
ip_matches_mask(IP, Net, Mask);
acl_rule_matches({user, {U, S}}, #{usr := {U, S, _}}, _Host) ->
true;
acl_rule_matches({user, U}, #{usr := {U, S, _}}, _Host) ->
lists:member(S, ?MYHOSTS);
lists:member(S, ejabberd_config:get_myhosts());
acl_rule_matches({server, S}, #{usr := {_, S, _}}, _Host) ->
true;
acl_rule_matches({resource, R}, #{usr := {_, _, R}}, _Host) ->
@@ -467,7 +466,7 @@ acl_rule_matches({shared_group, G}, #{usr := {U, S, _}}, Host) ->
acl_rule_matches({user_regexp, {UR, S}}, #{usr := {U, S, _}}, _Host) ->
is_regexp_match(U, UR);
acl_rule_matches({user_regexp, UR}, #{usr := {U, S, _}}, _Host) ->
lists:member(S, ?MYHOSTS) andalso is_regexp_match(U, UR);
lists:member(S, ejabberd_config:get_myhosts()) andalso is_regexp_match(U, UR);
acl_rule_matches({server_regexp, SR}, #{usr := {_, S, _}}, _Host) ->
is_regexp_match(S, SR);
acl_rule_matches({resource_regexp, RR}, #{usr := {_, _, R}}, _Host) ->
@@ -477,7 +476,7 @@ acl_rule_matches({node_regexp, {UR, SR}}, #{usr := {U, S, _}}, _Host) ->
acl_rule_matches({user_glob, {UR, S}}, #{usr := {U, S, _}}, _Host) ->
is_glob_match(U, UR);
acl_rule_matches({user_glob, UR}, #{usr := {U, S, _}}, _Host) ->
lists:member(S, ?MYHOSTS) andalso is_glob_match(U, UR);
lists:member(S, ejabberd_config:get_myhosts()) andalso is_glob_match(U, UR);
acl_rule_matches({server_glob, SR}, #{usr := {_, S, _}}, _Host) ->
is_glob_match(S, SR);
acl_rule_matches({resource_glob, RR}, #{usr := {_, _, R}}, _Host) ->
@@ -549,18 +548,30 @@ is_glob_match(String, Glob) ->
is_regexp_match(String,
ejabberd_regexp:sh_to_awk(Glob)).
is_ip_match({_, _, _, _} = IP, {_, _, _, _} = Net, Mask) ->
ip_matches_mask({_, _, _, _} = IP, {_, _, _, _} = Net, Mask) ->
IPInt = ip_to_integer(IP),
NetInt = ip_to_integer(Net),
M = bnot (1 bsl (32 - Mask) - 1),
IPInt band M =:= NetInt band M;
is_ip_match({_, _, _, _, _, _, _, _} = IP,
{_, _, _, _, _, _, _, _} = Net, Mask) ->
ip_matches_mask({_, _, _, _, _, _, _, _} = IP,
{_, _, _, _, _, _, _, _} = Net, Mask) ->
IPInt = ip_to_integer(IP),
NetInt = ip_to_integer(Net),
M = bnot (1 bsl (128 - Mask) - 1),
IPInt band M =:= NetInt band M;
is_ip_match(_, _, _) ->
ip_matches_mask({_, _, _, _} = IP,
{0, 0, 0, 0, 0, 16#FFFF, _, _} = Net, Mask) ->
IPInt = ip_to_integer({0, 0, 0, 0, 0, 16#FFFF, 0, 0}) + ip_to_integer(IP),
NetInt = ip_to_integer(Net),
M = bnot (1 bsl (128 - Mask) - 1),
IPInt band M =:= NetInt band M;
ip_matches_mask({0, 0, 0, 0, 0, 16#FFFF, _, _} = IP,
{_, _, _, _} = Net, Mask) ->
IPInt = ip_to_integer(IP) - ip_to_integer({0, 0, 0, 0, 0, 16#FFFF, 0, 0}),
NetInt = ip_to_integer(Net),
M = bnot (1 bsl (32 - Mask) - 1),
IPInt band M =:= NetInt band M;
ip_matches_mask(_, _, _) ->
false.
ip_to_integer({IP1, IP2, IP3, IP4}) ->
-1
View File
@@ -14,7 +14,6 @@
%% 3. tls-sni-01: https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-7.4
%% 4. (?) oob-01: https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-7.5
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-include("ejabberd_http.hrl").
-1
View File
@@ -35,7 +35,6 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
-record(state, {}).
-1
View File
@@ -32,7 +32,6 @@
-export([start/1, stop/0, mech_new/4, mech_step/2,
parse/1, format_error/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-behaviour(cyrsasl).
+1 -1
View File
@@ -31,7 +31,7 @@
-export([start/1, stop/0, mech_new/4, mech_step/2, format_error/1]).
-include("ejabberd.hrl").
-include("scram.hrl").
-include("logger.hrl").
-behaviour(cyrsasl).
+8 -3
View File
@@ -25,6 +25,7 @@
-module(ejabberd).
-author('alexey@process-one.net').
-compile({no_auto_import, [{halt, 0}]}).
-protocol({xep, 4, '2.9'}).
-protocol({xep, 86, '1.0'}).
@@ -36,7 +37,7 @@
-protocol({xep, 243, '1.0'}).
-protocol({xep, 270, '1.0'}).
-export([start/0, stop/0, start_app/1, start_app/2,
-export([start/0, stop/0, halt/0, start_app/1, start_app/2,
get_pid_file/0, check_app/1, module_name/1]).
-include("logger.hrl").
@@ -49,6 +50,11 @@ stop() ->
application:stop(ejabberd).
%%ejabberd_cover:stop().
halt() ->
application:stop(lager),
application:stop(sasl),
erlang:halt(1, [{flush, true}]).
%% @spec () -> false | string()
get_pid_file() ->
case os:getenv("EJABBERD_PID_PATH") of
@@ -131,8 +137,7 @@ exit_or_halt(Reason, StartFlag) ->
?CRITICAL_MSG(Reason, []),
if StartFlag ->
%% Wait for the critical message is written in the console/log
timer:sleep(1000),
halt(string:substr(lists:flatten(Reason), 1, 199));
halt();
true ->
erlang:error(application_start_failed)
end.
+1 -1
View File
@@ -506,7 +506,7 @@ is_valid_command_name2(<<>>) ->
true;
is_valid_command_name2(<<K:8, Rest/binary>>) when (K >= $a andalso K =< $z)
orelse (K >= $0 andalso K =< $9)
orelse K == $_ ->
orelse K == $_ orelse K == $- ->
is_valid_command_name2(Rest);
is_valid_command_name2(_) ->
false.
-1
View File
@@ -19,7 +19,6 @@
terminate/2, code_change/3]).
-export([start_link/0, opt_type/1, register_certfiles/0]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-include("ejabberd_commands.hrl").
-1
View File
@@ -22,7 +22,6 @@
%% delete_authz/3
]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
+6 -8
View File
@@ -61,7 +61,6 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_commands.hrl").
@@ -412,7 +411,7 @@ stop_kindly(DelaySeconds, AnnouncementTextString) ->
ejabberd_listener, stop_listeners, []},
{"Sending announcement to connected users",
mod_announce, send_announcement_to_all,
[?MYNAME, Subject, AnnouncementText]},
[ejabberd_config:get_myname(), Subject, AnnouncementText]},
{"Sending service message to MUC rooms",
ejabberd_admin, send_service_message_all_mucs,
[Subject, AnnouncementText]},
@@ -446,7 +445,7 @@ send_service_message_all_mucs(Subject, AnnouncementText) ->
ServerHost, mod_muc, <<"conference.@HOST@">>),
mod_muc:broadcast_service_message(ServerHost, MUCHost, Message)
end,
?MYHOSTS).
ejabberd_config:get_myhosts()).
%%%
%%% ejabberd_update
@@ -499,7 +498,7 @@ registered_users(Host) ->
lists:map(fun({U, _S}) -> U end, SUsers).
registered_vhosts() ->
?MYHOSTS.
ejabberd_config:get_myhosts().
reload_config() ->
ejabberd_config:reload_file().
@@ -549,13 +548,13 @@ delete_expired_messages() ->
lists:foreach(
fun(Host) ->
{atomic, ok} = mod_offline:remove_expired_messages(Host)
end, ?MYHOSTS).
end, ejabberd_config:get_myhosts()).
delete_old_messages(Days) ->
lists:foreach(
fun(Host) ->
{atomic, _} = mod_offline:remove_old_messages(Days, Host)
end, ?MYHOSTS).
end, ejabberd_config:get_myhosts()).
%%%
%%% Mnesia management
@@ -622,13 +621,12 @@ keep_tables() ->
%% loaded modules
keep_modules_tables() ->
lists:map(fun(Module) -> module_tables(Module) end,
gen_mod:loaded_modules(?MYNAME)).
gen_mod:loaded_modules(ejabberd_config:get_myname())).
%% TODO: This mapping should probably be moved to a callback function in each
%% module.
%% Mapping between modules and their tables
module_tables(mod_announce) -> [motd, motd_users];
module_tables(mod_irc) -> [irc_custom];
module_tables(mod_last) -> [last_activity];
module_tables(mod_muc) -> [muc_room, muc_registered];
module_tables(mod_offline) -> [offline_msg];
+25 -20
View File
@@ -31,7 +31,6 @@
-export([start/2, prep_stop/1, stop/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
%%%
@@ -46,24 +45,29 @@ start(normal, _Args) ->
start_elixir_application(),
ejabberd:check_app(ejabberd),
setup_if_elixir_conf_used(),
ejabberd_config:start(),
ejabberd_mnesia:start(),
file_queue_init(),
maybe_add_nameservers(),
ejabberd_system_monitor:start(),
case ejabberd_sup:start_link() of
{ok, SupPid} ->
register_elixir_config_hooks(),
ejabberd_cluster:wait_for_sync(infinity),
{T2, _} = statistics(wall_clock),
?INFO_MSG("ejabberd ~s is started in the node ~p in ~.2fs",
[?VERSION, node(), (T2-T1)/1000]),
lists:foreach(fun erlang:garbage_collect/1, processes()),
{ok, SupPid};
Err ->
?CRITICAL_MSG("Failed to start ejabberd application: ~p", [Err]),
timer:sleep(1000),
halt("Refer to ejabberd log files to diagnose the problem")
case ejabberd_config:start() of
ok ->
ejabberd_mnesia:start(),
file_queue_init(),
maybe_add_nameservers(),
case ejabberd_sup:start_link() of
{ok, SupPid} ->
ejabberd_system_monitor:start(),
register_elixir_config_hooks(),
ejabberd_cluster:wait_for_sync(infinity),
{T2, _} = statistics(wall_clock),
?INFO_MSG("ejabberd ~s is started in the node ~p in ~.2fs",
[ejabberd_config:get_version(),
node(), (T2-T1)/1000]),
lists:foreach(fun erlang:garbage_collect/1, processes()),
{ok, SupPid};
Err ->
?CRITICAL_MSG("Failed to start ejabberd application: ~p", [Err]),
ejabberd:halt()
end;
{error, Reason} ->
?CRITICAL_MSG("Failed to start ejabberd application: ~p", [Reason]),
ejabberd:halt()
end;
start(_, _) ->
{error, badarg}.
@@ -79,7 +83,8 @@ prep_stop(State) ->
%% All the processes were killed when this function is called
stop(_State) ->
?INFO_MSG("ejabberd ~s is stopped in the node ~p", [?VERSION, node()]),
?INFO_MSG("ejabberd ~s is stopped in the node ~p",
[ejabberd_config:get_version(), node()]),
delete_pid_file(),
%%ejabberd_debug:stop(),
ok.
+54 -28
View File
@@ -48,7 +48,7 @@
-export([auth_modules/1, opt_type/1]).
-include("ejabberd.hrl").
-include("scram.hrl").
-include("logger.hrl").
-define(AUTH_CACHE, auth_cache).
@@ -69,6 +69,7 @@
-callback start(binary()) -> any().
-callback stop(binary()) -> any().
-callback reload(binary()) -> any().
-callback plain_password_required(binary()) -> boolean().
-callback store_type(binary()) -> plain | external | scram.
-callback set_password(binary(), binary(), binary()) -> ok | {error, atom()}.
@@ -82,7 +83,8 @@
-callback use_cache(binary()) -> boolean().
-callback cache_nodes(binary()) -> boolean().
-optional_callbacks([set_password/3,
-optional_callbacks([reload/1,
set_password/3,
remove_user/2,
user_exists/2,
check_password/4,
@@ -105,7 +107,7 @@ init([]) ->
fun(Host, Acc) ->
Modules = auth_modules(Host),
maps:put(Host, Modules, Acc)
end, #{}, ?MYHOSTS),
end, #{}, ejabberd_config:get_myhosts()),
lists:foreach(
fun({Host, Modules}) ->
start(Host, Modules)
@@ -130,14 +132,16 @@ handle_cast({host_down, Host}, #state{host_modules = HostModules} = State) ->
init_cache(NewHostModules),
{noreply, State#state{host_modules = NewHostModules}};
handle_cast(config_reloaded, #state{host_modules = HostModules} = State) ->
NewHostModules = lists:foldl(
fun(Host, Acc) ->
OldModules = maps:get(Host, HostModules, []),
NewModules = auth_modules(Host),
start(Host, NewModules -- OldModules),
stop(Host, OldModules -- NewModules),
maps:put(Host, NewModules, Acc)
end, HostModules, ?MYHOSTS),
NewHostModules =
lists:foldl(
fun(Host, Acc) ->
OldModules = maps:get(Host, HostModules, []),
NewModules = auth_modules(Host),
start(Host, NewModules -- OldModules),
stop(Host, OldModules -- NewModules),
reload(Host, lists_intersection(OldModules, NewModules)),
maps:put(Host, NewModules, Acc)
end, HostModules, ejabberd_config:get_myhosts()),
init_cache(NewHostModules),
{noreply, State#state{host_modules = NewHostModules}};
handle_cast(Msg, State) ->
@@ -165,6 +169,15 @@ start(Host, Modules) ->
stop(Host, Modules) ->
lists:foreach(fun(M) -> M:stop(Host) end, Modules).
reload(Host, Modules) ->
lists:foreach(
fun(M) ->
case erlang:function_exported(M, reload, 1) of
true -> M:reload(Host);
false -> ok
end
end, Modules).
host_up(Host) ->
gen_server:cast(?MODULE, {host_up, Host}).
@@ -217,19 +230,22 @@ check_password_with_authmodule(User, AuthzId, Server, Password) ->
check_password_with_authmodule(User, AuthzId, Server, Password, Digest, DigestGen) ->
case validate_credentials(User, Server) of
{ok, LUser, LServer} ->
lists:foldl(
fun(Mod, false) ->
case db_check_password(
LUser, AuthzId, LServer, Password,
Digest, DigestGen, Mod) of
true -> {true, Mod};
false -> false
end;
(_, Acc) ->
Acc
end, false, auth_modules(LServer));
_ ->
false
case jid:nodeprep(AuthzId) of
error ->
false;
LAuthzId ->
lists:foldl(
fun(Mod, false) ->
case db_check_password(
LUser, LAuthzId, LServer, Password,
Digest, DigestGen, Mod) of
true -> {true, Mod};
false -> false
end;
(_, Acc) ->
Acc
end, false, auth_modules(LServer))
end
end.
-spec set_password(binary(), binary(), password()) -> ok | {error, atom()}.
@@ -545,8 +561,8 @@ db_user_exists(User, Server, Mod) ->
{ok, _} ->
true;
error ->
case Mod:store_type(Server) of
external ->
case {Mod:store_type(Server), use_cache(Mod, Server)} of
{external, true} ->
case ets_cache:lookup(
?AUTH_CACHE, {User, Server},
fun() ->
@@ -559,8 +575,12 @@ db_user_exists(User, Server, Mod) ->
{ok, _} ->
true;
error ->
false
false;
{error, _} = Err ->
Err
end;
{external, false} ->
Mod:user_exists(User, Server);
_ ->
false
end
@@ -744,7 +764,7 @@ auth_modules() ->
lists:flatmap(
fun(Host) ->
[{Host, Mod} || Mod <- auth_modules(Host)]
end, ?MYHOSTS).
end, ejabberd_config:get_myhosts()).
-spec auth_modules(binary()) -> [module()].
auth_modules(Server) ->
@@ -814,6 +834,12 @@ validate_credentials(User, Server, Password) ->
end
end.
lists_intersection(L1, L2) ->
lists:filter(
fun(E) ->
lists:member(E, L2)
end, L1).
import_info() ->
[{<<"users">>, 3}].
-1
View File
@@ -44,7 +44,6 @@
get_users/2, count_users/2, store_type/1,
plain_password_required/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("jid.hrl").
+43 -22
View File
@@ -31,23 +31,24 @@
-behaviour(ejabberd_auth).
-export([start/1, stop/1, set_password/3, check_password/4,
-export([start/1, stop/1, reload/1, set_password/3, check_password/4,
try_register/3, user_exists/2, remove_user/2,
store_type/1, plain_password_required/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start(Host) ->
Cmd = ejabberd_config:get_option({extauth_program, Host}, "extauth"),
extauth:start(Host, Cmd).
extauth:start(Host).
stop(Host) ->
extauth:stop(Host).
reload(Host) ->
extauth:reload(Host).
plain_password_required(_) -> true.
store_type(_) -> external.
@@ -61,37 +62,48 @@ check_password(User, AuthzId, Server, Password) ->
set_password(User, Server, Password) ->
case extauth:set_password(User, Server, Password) of
true -> ok;
_ -> {error, db_failure}
Res when is_boolean(Res) -> ok;
{error, Reason} -> failure(User, Server, set_password, Reason)
end.
try_register(User, Server, Password) ->
extauth:try_register(User, Server, Password).
case extauth:try_register(User, Server, Password) of
true -> ok;
false -> {error, not_allowed};
{error, Reason} -> failure(User, Server, try_register, Reason)
end.
user_exists(User, Server) ->
try extauth:user_exists(User, Server) of
Res -> Res
catch
_:Error ->
?ERROR_MSG("external authentication program failure: ~p",
[Error]),
{error, db_failure}
case extauth:user_exists(User, Server) of
Res when is_boolean(Res) -> Res;
{error, Reason} -> failure(User, Server, user_exists, Reason)
end.
remove_user(User, Server) ->
case extauth:remove_user(User, Server) of
false -> {error, not_allowed};
true -> ok
true -> ok;
{error, Reason} -> failure(User, Server, remove_user, Reason)
end.
check_password_extauth(User, _AuthzId, Server, Password) ->
extauth:check_password(User, Server, Password) andalso
Password /= <<"">>.
if Password /= <<"">> ->
case extauth:check_password(User, Server, Password) of
Res when is_boolean(Res) -> Res;
{error, Reason} ->
failure(User, Server, check_password, Reason),
false
end;
true ->
false
end.
-spec failure(binary(), binary(), atom(), any()) -> {error, db_failure}.
failure(User, Server, Fun, Reason) ->
?ERROR_MSG("External authentication program failed when calling "
"'~s' for ~s@~s: ~p", [Fun, User, Server, Reason]),
{error, db_failure}.
-spec opt_type(extauth_cache) -> fun((false | non_neg_integer()) ->
false | non_neg_integer());
(extauth_program) -> fun((binary()) -> string());
(atom()) -> [atom()].
opt_type(extauth_cache) ->
?WARNING_MSG("option 'extauth_cache' is deprecated and has no effect, "
"use authentication or global cache configuration "
@@ -100,6 +112,15 @@ opt_type(extauth_cache) ->
fun (false) -> false;
(I) when is_integer(I), I >= 0 -> I
end;
opt_type(extauth_instances) ->
?WARNING_MSG("option 'extauth_instances' is deprecated and has no effect, "
"use 'extauth_pool_size'", []),
fun (V) when is_integer(V), V > 0 -> V end;
opt_type(extauth_program) ->
fun (V) -> binary_to_list(iolist_to_binary(V)) end;
opt_type(_) -> [extauth_cache, extauth_program].
opt_type(extauth_pool_size) ->
fun(I) when is_integer(I), I>0 -> I end;
opt_type(_) ->
[extauth_program, extauth_pool_size,
%% Deprecated:
extauth_cache, extauth_instances].
-1
View File
@@ -42,7 +42,6 @@
store_type/1, plain_password_required/1,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("eldap.hrl").
+1 -1
View File
@@ -38,8 +38,8 @@
plain_password_required/1, use_cache/1]).
-export([need_transform/1, transform/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("scram.hrl").
-include("ejabberd_auth.hrl").
-record(reg_users_counter, {vhost = <<"">> :: binary(),
+1 -1
View File
@@ -38,8 +38,8 @@
plain_password_required/1]).
-export([passwd_schema/0]).
-include("ejabberd.hrl").
-include("ejabberd_sql_pt.hrl").
-include("scram.hrl").
-include("ejabberd_auth.hrl").
start(_Host) ->
+1 -1
View File
@@ -37,7 +37,7 @@
remove_user/2, store_type/1, plain_password_required/1,
convert_to_scram/1, opt_type/1, export/1]).
-include("ejabberd.hrl").
-include("scram.hrl").
-include("logger.hrl").
-include("ejabberd_sql_pt.hrl").
-include("ejabberd_auth.hrl").
+12 -15
View File
@@ -44,13 +44,9 @@
handle_sync_event/4, handle_info/3, terminate/3,
code_change/4]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-include("ejabberd_http.hrl").
-include("bosh.hrl").
%%-define(DBGFSM, true).
@@ -103,8 +99,8 @@
prev_key = <<"">> :: binary(),
prev_poll :: erlang:timestamp() | undefined,
max_concat = unlimited :: unlimited | non_neg_integer(),
responses = gb_trees:empty() :: ?TGB_TREE,
receivers = gb_trees:empty() :: ?TGB_TREE,
responses = gb_trees:empty() :: gb_trees:tree(),
receivers = gb_trees:empty() :: gb_trees:tree(),
shaped_receivers :: p1_queue:queue(),
ip :: inet:ip_address(),
max_requests = 1 :: non_neg_integer()}).
@@ -452,7 +448,7 @@ active1(#body{attrs = Attrs} = Req, From, State) ->
{next_state, active,
do_reply(State, From, PrevBody, RID)};
none ->
State1 = drop_holding_receiver(State),
State1 = drop_holding_receiver(State, RID),
State2 = stop_inactivity_timer(State1),
State3 = restart_wait_timer(State2),
Receivers = gb_trees:insert(RID, {From, Req},
@@ -688,15 +684,16 @@ reply_stop(State, Body, From, RID) ->
{stop, normal, do_reply(State, From, Body, RID)}.
drop_holding_receiver(State) ->
RID = State#state.prev_rid,
drop_holding_receiver(State, State#state.prev_rid).
drop_holding_receiver(State, RID) ->
case gb_trees:lookup(RID, State#state.receivers) of
{value, {From, Body}} ->
State1 = restart_inactivity_timer(State),
Receivers = gb_trees:delete_any(RID,
State1#state.receivers),
State2 = State1#state{receivers = Receivers},
do_reply(State2, From, Body, RID);
none -> State
{value, {From, Body}} ->
State1 = restart_inactivity_timer(State),
Receivers = gb_trees:delete_any(RID,
State1#state.receivers),
State2 = State1#state{receivers = Receivers},
do_reply(State2, From, Body, RID);
none -> State
end.
do_reply(State, From, Body, RID) ->
+8 -7
View File
@@ -51,7 +51,6 @@
reply/2, copy_state/2, set_timeout/2, route/2,
host_up/1, host_down/1]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
-include("logger.hrl").
-include("mod_roster.hrl").
@@ -415,7 +414,7 @@ bind(R, #{user := U, server := S, access := Access, lang := Lang,
handle_stream_start(StreamStart, #{lserver := LServer} = State) ->
case ejabberd_router:is_my_host(LServer) of
false ->
send(State#{lserver => ?MYNAME}, xmpp:serr_host_unknown());
send(State#{lserver => ejabberd_config:get_myname()}, xmpp:serr_host_unknown());
true ->
State1 = change_shaper(State),
Opts = ejabberd_config:codec_options(LServer),
@@ -526,9 +525,9 @@ init([State, Opts]) ->
tls_verify => TLSVerify,
pres_a => ?SETS:new(),
zlib => Zlib,
lang => ?MYLANG,
server => ?MYNAME,
lserver => ?MYNAME,
lang => ejabberd_config:get_mylang(),
server => ejabberd_config:get_myname(),
lserver => ejabberd_config:get_myname(),
access => Access,
shaper => Shaper},
State2 = xmpp_stream_in:set_timeout(State1, Timeout),
@@ -1038,14 +1037,16 @@ listen_opt_type(inet) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(inet6) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(backlog) ->
fun(I) when is_integer(I), I>0 -> I end;
listen_opt_type(accept_interval) ->
fun(I) when is_integer(I), I>=0 -> I end;
listen_opt_type(O) ->
StreamOpts = mod_stream_mgmt:mod_options(?MYNAME),
StreamOpts = mod_stream_mgmt:mod_options(ejabberd_config:get_myname()),
case lists:keyfind(O, 1, StreamOpts) of
false ->
[access, shaper, certfile, ciphers, dhfile, cafile,
protocol_options, tls, tls_compression, starttls,
starttls_required, tls_verify, zlib, max_fsm_queue,
backlog, inet, inet6];
backlog, inet, inet6, accept_interval];
_ ->
?ERROR_MSG("Listening option '~s' is ignored: use '~s' "
"option from mod_stream_mgmt module", [O, O]),
+3 -4
View File
@@ -45,7 +45,6 @@
config_reloaded/0, process_iq/1]).
-include("xmpp.hrl").
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_http.hrl").
@@ -365,12 +364,12 @@ terminate(_Reason, #state{enabled = Enabled}) ->
register_handlers() ->
ejabberd_hooks:add(host_up, ?MODULE, host_up, 50),
ejabberd_hooks:add(host_down, ?MODULE, host_down, 50),
lists:foreach(fun host_up/1, ?MYHOSTS).
lists:foreach(fun host_up/1, ejabberd_config:get_myhosts()).
unregister_handlers() ->
ejabberd_hooks:delete(host_up, ?MODULE, host_up, 50),
ejabberd_hooks:delete(host_down, ?MODULE, host_down, 50),
lists:foreach(fun host_down/1, ?MYHOSTS).
lists:foreach(fun host_down/1, ejabberd_config:get_myhosts()).
code_change(_OldVsn, State, _Extra) -> {ok, State}.
@@ -445,7 +444,7 @@ get_url(Str) ->
<<TransferProt/binary, ":", Host/binary, ":",
PortString/binary, "/captcha/", Str/binary>>;
_ ->
<<"http://", (?MYNAME)/binary, "/captcha/", Str/binary>>
<<"http://", (ejabberd_config:get_myname())/binary, "/captcha/", Str/binary>>
end.
get_transfer_protocol(PortString) ->
-1
View File
@@ -31,7 +31,6 @@
get_known_nodes/0, node_id/0, get_node_by_id/1,
send/2, wait_for_sync/1, subscribe/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-spec init() -> ok.
-1
View File
@@ -240,7 +240,6 @@
terminate/2, code_change/3]).
-include("ejabberd_commands.hrl").
-include("ejabberd.hrl").
-include("logger.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-1
View File
@@ -30,7 +30,6 @@
-export([generate_md_output/3]).
-include("ejabberd_commands.hrl").
-include("ejabberd.hrl").
-define(RAW(V), if HTMLOutput -> fxml:crypt(iolist_to_binary(V)); true -> iolist_to_binary(V) end).
-define(TAG(N), if HTMLOutput -> [<<"<", ??N, "/>">>]; true -> md_tag(N, <<"">>) end).
+96 -67
View File
@@ -28,7 +28,8 @@
-export([start/0, load_file/1, reload_file/0, read_file/1,
get_option/1, get_option/2, add_option/2, has_option/1,
get_version/0, get_myhosts/0, get_mylang/0, get_lang/1,
get_version/0, get_myhosts/0, get_myname/0,
get_mylang/0, get_lang/1, get_uri/0, get_copyright/0,
get_ejabberd_config_path/0, is_using_elixir_config/0,
prepare_opt_val/4, transform_options/1, collect_options/1,
convert_to_yaml/1, convert_to_yaml/2, v_db/2,
@@ -53,21 +54,15 @@
{get_global_option, 3}, {get_local_option, 3},
{get_option, 3}, {is_file_readable, 1}]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_config.hrl").
-include_lib("kernel/include/file.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-callback opt_type(atom()) -> function() | [atom()].
-type bad_option() :: invalid_option | unknown_option.
%% @type macro() = {macro_key(), macro_value()}
%% @type macro_key() = atom().
%% The atom must have all characters in uppercase.
%% @type macro_value() = term().
-spec start() -> ok | {error, bad_option()}.
start() ->
ConfigFile = get_ejabberd_config_path(),
?INFO_MSG("Loading configuration from ~s", [ConfigFile]),
@@ -75,17 +70,23 @@ start() ->
[named_table, public, {read_concurrency, true}]),
catch ets:new(ejabberd_db_modules,
[named_table, public, {read_concurrency, true}]),
State1 = load_file(ConfigFile),
UnixTime = p1_time_compat:system_time(seconds),
SharedKey = case erlang:get_cookie() of
nocookie ->
str:sha(randoms:get_string());
Cookie ->
str:sha(misc:atom_to_binary(Cookie))
end,
State2 = set_option({node_start, global}, UnixTime, State1),
State3 = set_option({shared_key, global}, SharedKey, State2),
set_opts(State3).
case load_file(ConfigFile) of
{ok, State1} ->
UnixTime = p1_time_compat:system_time(seconds),
SharedKey = case erlang:get_cookie() of
nocookie ->
str:sha(randoms:get_string());
Cookie ->
str:sha(misc:atom_to_binary(Cookie))
end,
State2 = set_option({node_start, global}, UnixTime, State1),
State3 = set_option({shared_key, global}, SharedKey, State2),
set_opts(State3),
ok;
{error, _} = Err ->
?ERROR_MSG("Failed to load configuration file ~s", [ConfigFile]),
Err
end.
%% When starting ejabberd for testing, we sometimes want to start a
%% subset of hosts from the one define in the config file.
@@ -135,7 +136,7 @@ get_ejabberd_config_path() ->
undefined ->
case os:getenv("EJABBERD_CONFIG_PATH") of
false ->
?CONFIG_PATH;
"ejabberd.yml";
Path ->
Path
end
@@ -189,7 +190,7 @@ read_file(File, Opts) ->
State1 = lists:foldl(fun process_term/2, State, Head ++ Tail),
State1#state{opts = compact(State1#state.opts)}.
-spec load_file(string()) -> #state{}.
-spec load_file(string()) -> {ok, #state{}} | {error, bad_option()}.
load_file(File) ->
State0 = read_file(File),
@@ -199,23 +200,27 @@ load_file(File) ->
ModOpts = get_modules_with_options(AllMods),
validate_opts(State1, ModOpts).
-spec reload_file() -> ok.
-spec reload_file() -> ok | {error, bad_option()}.
reload_file() ->
Config = get_ejabberd_config_path(),
OldHosts = get_myhosts(),
State = load_file(Config),
set_opts(State),
NewHosts = get_myhosts(),
lists:foreach(
fun(Host) ->
ejabberd_hooks:run(host_up, [Host])
end, NewHosts -- OldHosts),
lists:foreach(
fun(Host) ->
ejabberd_hooks:run(host_down, [Host])
end, OldHosts -- NewHosts),
ejabberd_hooks:run(config_reloaded, []).
case load_file(Config) of
{error, _} = Err ->
Err;
{ok, State} ->
set_opts(State),
NewHosts = get_myhosts(),
lists:foreach(
fun(Host) ->
ejabberd_hooks:run(host_up, [Host])
end, NewHosts -- OldHosts),
lists:foreach(
fun(Host) ->
ejabberd_hooks:run(host_down, [Host])
end, OldHosts -- NewHosts),
ejabberd_hooks:run(config_reloaded, [])
end.
-spec convert_to_yaml(file:filename()) -> ok | {error, any()}.
@@ -455,8 +460,7 @@ get_config_lines2(Fd, Data, CurrLine, [NextWanted | LNumbers], R) when is_list(D
exit_or_halt(ExitText) ->
case [Vsn || {ejabberd, _Desc, Vsn} <- application:which_applications()] of
[] ->
timer:sleep(1000),
halt(string:substr(ExitText, 1, 199));
ejabberd:halt();
[_] ->
exit(ExitText)
end.
@@ -1018,33 +1022,39 @@ get_modules_with_options(Modules) ->
end
end, dict:new(), Modules).
-spec validate_opts(#state{}, dict:dict()) -> {ok, #state{}} | {error, bad_option()}.
validate_opts(#state{opts = Opts} = State, ModOpts) ->
NewOpts = lists:filtermap(
fun(#local_config{key = {Opt, _Host}, value = Val} = In) ->
case dict:find(Opt, ModOpts) of
{ok, [Mod|_]} ->
VFun = Mod:opt_type(Opt),
try VFun(Val) of
NewVal ->
{true, In#local_config{value = NewVal}}
catch {invalid_syntax, Error} ->
?ERROR_MSG("ignoring option '~s' with "
"invalid value: ~p: ~s",
[Opt, Val, Error]),
false;
_:_ ->
?ERROR_MSG("ignoring option '~s' with "
"invalid value: ~p",
[Opt, Val]),
false
end;
_ ->
?ERROR_MSG("unknown option '~s' will be likely"
" ignored", [Opt]),
true
end
end, Opts),
State#state{opts = NewOpts}.
try
NewOpts = lists:map(
fun(#local_config{key = {Opt, _Host}, value = Val} = In) ->
case dict:find(Opt, ModOpts) of
{ok, [Mod|_]} ->
VFun = Mod:opt_type(Opt),
try VFun(Val) of
NewVal ->
In#local_config{value = NewVal}
catch {invalid_syntax, Error} ->
?ERROR_MSG("Invalid value '~p' for "
"option '~s': ~s",
[Val, Opt, Error]),
erlang:error(invalid_option);
_:_ ->
?ERROR_MSG("Invalid value '~p' for "
"option '~s'",
[Val, Opt]),
erlang:error(invalid_option)
end;
_ ->
?ERROR_MSG("Unknown option '~s'", [Opt]),
erlang:error(unknown_option)
end
end, Opts),
{ok, State#state{opts = NewOpts}}
catch _:invalid_option ->
{error, invalid_option};
_:unknown_option ->
{error, unknown_option}
end.
%% @spec (Path::string()) -> true | false
is_file_readable(Path) ->
@@ -1060,9 +1070,16 @@ is_file_readable(Path) ->
end.
get_version() ->
case application:get_key(ejabberd, vsn) of
undefined -> "";
{ok, Vsn} -> list_to_binary(Vsn)
case application:get_env(ejabberd, custom_vsn) of
{ok, Vsn0} when is_list(Vsn0) ->
list_to_binary(Vsn0);
{ok, Vsn1} when is_binary(Vsn1) ->
Vsn1;
_ ->
case application:get_key(ejabberd, vsn) of
undefined -> "";
{ok, Vsn} -> list_to_binary(Vsn)
end
end.
-spec get_myhosts() -> [binary()].
@@ -1070,6 +1087,11 @@ get_version() ->
get_myhosts() ->
get_option(hosts).
-spec get_myname() -> binary().
get_myname() ->
hd(get_myhosts()).
-spec get_mylang() -> binary().
get_mylang() ->
@@ -1079,10 +1101,17 @@ get_mylang() ->
get_lang(Host) ->
get_option({language, Host}, <<"en">>).
-spec get_uri() -> binary().
get_uri() ->
<<"http://www.process-one.net/en/ejabberd/">>.
-spec get_copyright() -> binary().
get_copyright() ->
<<"Copyright (c) ProcessOne">>.
replace_module(mod_announce_odbc) -> {mod_announce, sql};
replace_module(mod_blocking_odbc) -> {mod_blocking, sql};
replace_module(mod_caps_odbc) -> {mod_caps, sql};
replace_module(mod_irc_odbc) -> {mod_irc, sql};
replace_module(mod_last_odbc) -> {mod_last, sql};
replace_module(mod_muc_odbc) -> {mod_muc, sql};
replace_module(mod_offline_odbc) -> {mod_offline, sql};
-1
View File
@@ -58,7 +58,6 @@
-include("ejabberd_ctl.hrl").
-include("ejabberd_commands.hrl").
-include("ejabberd.hrl").
-include("logger.hrl").
-define(DEFAULT_VERSION, 1000000).
+234 -202
View File
@@ -31,17 +31,15 @@
%% External exports
-export([start/2, start_link/2, become_controller/1,
socket_type/0, receive_headers/1, url_encode/1,
socket_type/0, receive_headers/1, recv_file/2,
transform_listen_option/2, listen_opt_type/1]).
-export([init/2, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-include("ejabberd_http.hrl").
-include_lib("kernel/include/file.hrl").
-record(state, {sockmod,
socket,
@@ -50,7 +48,7 @@
request_path,
request_auth,
request_keepalive,
request_content_length,
request_content_length = 0,
request_lang = <<"en">>,
%% XXX bard: request handlers are configured in
%% ejabberd.cfg under the HTTP service. For example,
@@ -85,6 +83,10 @@
"org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
"">>).
-define(RECV_BUF, 65536).
-define(SEND_BUF, 65536).
-define(MAX_POST_SIZE, 20971520). %% 20Mb
start(SockData, Opts) ->
{ok,
proc_lib:spawn(ejabberd_http, init,
@@ -113,7 +115,7 @@ init({SockMod, Socket}, Opts) ->
end,
TLSOpts = [verify_none | TLSOpts3],
{SockMod1, Socket1} = if TLSEnabled ->
inet:setopts(Socket, [{recbuf, 8192}]),
inet:setopts(Socket, [{recbuf, ?RECV_BUF}]),
{ok, TLSSocket} = fast_tls:tcp_to_tls(Socket,
TLSOpts),
{fast_tls, TLSSocket};
@@ -168,18 +170,44 @@ become_controller(_Pid) ->
socket_type() ->
raw.
send_text(_State, none) ->
ok;
send_text(State, Text) ->
case catch
(State#state.sockmod):send(State#state.socket, Text)
of
ok -> ok;
{error, timeout} ->
?INFO_MSG("Timeout on ~p:send", [State#state.sockmod]),
exit(normal);
Error ->
?DEBUG("Error in ~p:send: ~p",
[State#state.sockmod, Error]),
exit(normal)
case (State#state.sockmod):send(State#state.socket, Text) of
ok -> ok;
{error, timeout} ->
?INFO_MSG("Timeout on ~p:send", [State#state.sockmod]),
exit(normal);
Error ->
?DEBUG("Error in ~p:send: ~p",
[State#state.sockmod, Error]),
exit(normal)
end.
send_file(State, Fd, Size, FileName) ->
try
case State#state.sockmod of
gen_tcp ->
case file:sendfile(Fd, State#state.socket, 0, Size, []) of
{ok, _} -> ok
end;
_ ->
case file:read(Fd, ?SEND_BUF) of
{ok, Data} ->
send_text(State, Data),
send_file(State, Fd, Size, FileName);
eof ->
ok
end
end
catch _:{case_clause, {error, Why}} ->
if Why /= closed ->
?INFO_MSG("Failed to read ~s: ~s",
[FileName, file_format_error(Why)]),
exit(normal);
true ->
ok
end
end.
receive_headers(#state{trail = Trail} = State) ->
@@ -348,8 +376,8 @@ get_transfer_protocol(RE, SockMod, HostPort) ->
%% matches the requested URL path, and pass control to it. If none is
%% found, answer with HTTP 404.
process([], _, _, _, _) -> ejabberd_web:error(not_found);
process(Handlers, Request, Socket, SockMod, Trail) ->
process([], _) -> ejabberd_web:error(not_found);
process(Handlers, Request) ->
{HandlerPathPrefix, HandlerModule, HandlerOpts, HandlersLeft} =
case Handlers of
[{Pfx, Mod} | Tail] ->
@@ -369,14 +397,14 @@ process(Handlers, Request, Socket, SockMod, Trail) ->
LocalPath = lists:nthtail(length(HandlerPathPrefix), Request#request.path),
R = try
HandlerModule:socket_handoff(
LocalPath, Request, Socket, SockMod, Trail, HandlerOpts)
LocalPath, Request, HandlerOpts)
catch error:undef ->
HandlerModule:process(LocalPath, Request)
end,
ejabberd_hooks:run(http_request_debug, [{LocalPath, Request}]),
R;
false ->
process(HandlersLeft, Request, Socket, SockMod, Trail)
process(HandlersLeft, Request)
end.
extract_path_query(#state{request_method = Method,
@@ -398,24 +426,29 @@ extract_path_query(#state{request_method = Method,
extract_path_query(#state{request_method = Method,
request_path = {abs_path, Path},
request_content_length = Len,
trail = Trail,
sockmod = _SockMod,
socket = _Socket} = State)
when (Method =:= 'POST' orelse Method =:= 'PUT') andalso
is_integer(Len) ->
case recv_data(State, Len) of
error -> {State, false};
{NewState, Data} ->
?DEBUG("client data: ~p~n", [Data]),
when (Method =:= 'POST' orelse Method =:= 'PUT') andalso Len>0 ->
case catch url_decode_q_split(Path) of
{'EXIT', _} -> {NewState, false};
{'EXIT', _} -> {State, false};
{NPath, _Query} ->
LPath = normalize_path([NPE
|| NPE <- str:tokens(path_decode(NPath), <<"/">>)]),
LQuery = case catch parse_urlencoded(Data) of
{'EXIT', _Reason} -> [];
LQ -> LQ
end,
{NewState, {LPath, LQuery, Data}}
LPath = normalize_path(
[NPE || NPE <- str:tokens(path_decode(NPath), <<"/">>)]),
case Method of
'PUT' ->
{State, {LPath, [], Trail}};
'POST' ->
case recv_data(State) of
{ok, Data} ->
LQuery = case catch parse_urlencoded(Data) of
{'EXIT', _Reason} -> [];
LQ -> LQ
end,
{State, {LPath, LQuery, Data}};
error ->
{State, false}
end
end
end;
extract_path_query(State) ->
@@ -428,16 +461,23 @@ process_request(#state{request_host = undefined,
process_request(#state{request_method = Method,
request_auth = Auth,
request_lang = Lang,
request_version = Version,
sockmod = SockMod,
socket = Socket,
options = Options,
request_host = Host,
request_port = Port,
request_tp = TP,
request_content_length = Length,
request_headers = RequestHeaders,
request_handlers = RequestHandlers,
custom_headers = CustomHeaders,
trail = Trail} = State) ->
custom_headers = CustomHeaders} = State) ->
case proplists:get_value(<<"Expect">>, RequestHeaders, <<>>) of
<<"100-", _/binary>> when Version == {1, 1} ->
send_text(State, <<"HTTP/1.1 100 Continue\r\n\r\n">>);
_ ->
ok
end,
case extract_path_query(State) of
{State2, false} ->
{State2, make_bad_request(State)};
@@ -459,7 +499,10 @@ process_request(#state{request_method = Method,
path = LPath,
q = LQuery,
auth = Auth,
data = Data,
length = Length,
sockmod = SockMod,
socket = Socket,
data = Data,
lang = Lang,
host = Host,
port = Port,
@@ -469,7 +512,7 @@ process_request(#state{request_method = Method,
ip = IP},
RequestHandlers1 = ejabberd_hooks:run_fold(
http_request_handlers, RequestHandlers, [Host, Request]),
Res = case process(RequestHandlers1, Request, Socket, SockMod, Trail) of
Res = case process(RequestHandlers1, Request) of
El when is_record(El, xmlel) ->
make_xhtml_output(State, 200, CustomHeaders, El);
{Status, Headers, El}
@@ -482,6 +525,8 @@ process_request(#state{request_method = Method,
when is_binary(Output) or is_list(Output) ->
make_text_output(State, Status,
Headers ++ CustomHeaders, Output);
{Status, Headers, {file, FileName}} ->
make_file_output(State, Status, Headers, FileName);
{Status, Reason, Headers, Output}
when is_binary(Output) or is_list(Output) ->
make_text_output(State, Status, Reason,
@@ -489,7 +534,7 @@ process_request(#state{request_method = Method,
_ ->
none
end,
{State2, Res}
{State2#state{trail = <<>>}, Res}
end.
make_bad_request(State) ->
@@ -519,118 +564,96 @@ analyze_ip_xff({IPLast, Port}, XFF, Host) ->
end,
{IPClient, Port}.
is_ipchain_trusted([], _) -> false;
is_ipchain_trusted(_UserIPs, all) -> true;
is_ipchain_trusted(UserIPs, TrustedIPs) ->
[] == UserIPs -- [<<"127.0.0.1">> | TrustedIPs].
is_ipchain_trusted(UserIPs, Masks) ->
lists:all(
fun(IP) ->
case inet:parse_address(binary_to_list(IP)) of
{ok, IP2} ->
lists:any(
fun({Mask, MaskLen}) ->
acl:ip_matches_mask(IP2, Mask, MaskLen)
end, [{{127,0,0,1}, 8} | Masks]);
_ ->
false
end
end, UserIPs).
recv_data(State, Len) -> recv_data(State, Len, <<>>).
recv_data(State, 0, Acc) -> {State, Acc};
recv_data(#state{trail = Trail} = State, Len, <<>>) when byte_size(Trail) > Len ->
<<Data:Len/binary, Rest/binary>> = Trail,
{State#state{trail = Rest}, Data};
recv_data(State, Len, Acc) ->
case State#state.trail of
<<>> ->
case (State#state.sockmod):recv(State#state.socket,
min(Len, 16#4000000), 300000)
of
{ok, Data} ->
recv_data(State, Len - byte_size(Data), <<Acc/binary, Data/binary>>);
Err ->
?DEBUG("Cannot receive HTTP data: ~p", [Err]),
error
recv_data(#state{request_content_length = Len}) when Len >= ?MAX_POST_SIZE ->
error;
recv_data(#state{request_content_length = Len, trail = Trail,
sockmod = SockMod, socket = Socket}) ->
NewLen = Len - byte_size(Trail),
if NewLen > 0 ->
case SockMod:recv(Socket, NewLen, 60000) of
{ok, Data} -> {ok, <<Trail/binary, Data/binary>>};
{error, _} -> error
end;
_ ->
Trail = (State#state.trail),
recv_data(State#state{trail = <<>>},
Len - byte_size(Trail), <<Acc/binary, Trail/binary>>)
true ->
{ok, Trail}
end.
make_xhtml_output(State, Status, Headers, XHTML) ->
Data = case lists:member(html, Headers) of
true ->
iolist_to_binary([?HTML_DOCTYPE,
fxml:element_to_binary(XHTML)]);
_ ->
iolist_to_binary([?XHTML_DOCTYPE,
fxml:element_to_binary(XHTML)])
end,
Headers1 = case lists:keysearch(<<"Content-Type">>, 1,
Headers)
of
{value, _} ->
[{<<"Content-Length">>,
integer_to_binary(byte_size(Data))}
| Headers];
_ ->
[{<<"Content-Type">>, <<"text/html; charset=utf-8">>},
{<<"Content-Length">>,
integer_to_binary(byte_size(Data))}
| Headers]
recv_file(#request{length = Len, data = Trail,
sockmod = SockMod, socket = Socket}, Path) ->
case file:open(Path, [write, exclusive, raw]) of
{ok, Fd} ->
case file:write(Fd, Trail) of
ok ->
NewLen = max(0, Len - byte_size(Trail)),
case do_recv_file(NewLen, SockMod, Socket, Fd) of
ok ->
ok;
{error, _} = Err ->
file:delete(Path),
Err
end;
{error, _} = Err ->
file:delete(Path),
Err
end;
{error, _} = Err ->
Err
end.
do_recv_file(0, _SockMod, _Socket, Fd) ->
file:close(Fd);
do_recv_file(Len, SockMod, Socket, Fd) ->
ChunkLen = min(Len, ?RECV_BUF),
try
{ok, Data} = SockMod:recv(Socket, ChunkLen, timer:seconds(30)),
ok = file:write(Fd, Data),
do_recv_file(Len-size(Data), SockMod, Socket, Fd)
catch _:{badmatch, {error, _} = Err} ->
file:close(Fd),
Err
end.
make_headers(State, Status, Reason, Headers, Data) ->
Len = if is_integer(Data) -> Data;
true -> iolist_size(Data)
end,
Headers1 = [{<<"Content-Length">>, integer_to_binary(Len)} | Headers],
Headers2 = case lists:keyfind(<<"Content-Type">>, 1, Headers) of
{_, _} ->
Headers1;
false ->
[{<<"Content-Type">>, <<"text/html; charset=utf-8">>}
| Headers1]
end,
HeadersOut = case {State#state.request_version,
State#state.request_keepalive}
of
{{1, 1}, true} -> Headers1;
{_, true} ->
[{<<"Connection">>, <<"keep-alive">>} | Headers1];
{_, false} ->
[{<<"Connection">>, <<"close">>} | Headers1]
State#state.request_keepalive} of
{{1, 1}, true} -> Headers2;
{_, true} ->
[{<<"Connection">>, <<"keep-alive">>} | Headers2];
{_, false} ->
[{<<"Connection">>, <<"close">>} | Headers2]
end,
Version = case State#state.request_version of
{1, 1} -> <<"HTTP/1.1 ">>;
_ -> <<"HTTP/1.0 ">>
{1, 1} -> <<"HTTP/1.1 ">>;
_ -> <<"HTTP/1.0 ">>
end,
H = lists:map(fun ({Attr, Val}) ->
[Attr, <<": ">>, Val, <<"\r\n">>];
(_) -> []
end,
HeadersOut),
SL = [Version,
integer_to_binary(Status), <<" ">>,
code_to_phrase(Status), <<"\r\n">>],
Data2 = case State#state.request_method of
'HEAD' -> <<"">>;
_ -> Data
end,
[SL, H, <<"\r\n">>, Data2].
make_text_output(State, Status, Headers, Text) ->
make_text_output(State, Status, <<"">>, Headers, Text).
make_text_output(State, Status, Reason, Headers, Text) ->
Data = iolist_to_binary(Text),
Headers1 = case lists:keysearch(<<"Content-Type">>, 1,
Headers)
of
{value, _} ->
[{<<"Content-Length">>,
integer_to_binary(byte_size(Data))}
| Headers];
_ ->
[{<<"Content-Type">>, <<"text/html; charset=utf-8">>},
{<<"Content-Length">>,
integer_to_binary(byte_size(Data))}
| Headers]
end,
HeadersOut = case {State#state.request_version,
State#state.request_keepalive}
of
{{1, 1}, true} -> Headers1;
{_, true} ->
[{<<"Connection">>, <<"keep-alive">>} | Headers1];
{_, false} ->
[{<<"Connection">>, <<"close">>} | Headers1]
end,
Version = case State#state.request_version of
{1, 1} -> <<"HTTP/1.1 ">>;
_ -> <<"HTTP/1.0 ">>
end,
H = lists:map(fun ({Attr, Val}) ->
[Attr, <<": ">>, Val, <<"\r\n">>]
end,
HeadersOut),
H = [[Attr, <<": ">>, Val, <<"\r\n">>] || {Attr, Val} <- HeadersOut],
NewReason = case Reason of
<<"">> -> code_to_phrase(Status);
_ -> Reason
@@ -638,11 +661,55 @@ make_text_output(State, Status, Reason, Headers, Text) ->
SL = [Version,
integer_to_binary(Status), <<" ">>,
NewReason, <<"\r\n">>],
[SL, H, <<"\r\n">>].
make_xhtml_output(State, Status, Headers, XHTML) ->
Data = case State#state.request_method of
'HEAD' -> <<"">>;
_ ->
DocType = case lists:member(html, Headers) of
true -> ?HTML_DOCTYPE;
false -> ?XHTML_DOCTYPE
end,
iolist_to_binary([DocType, fxml:element_to_binary(XHTML)])
end,
EncodedHdrs = make_headers(State, Status, <<"">>, Headers, Data),
[EncodedHdrs, Data].
make_text_output(State, Status, Headers, Text) ->
make_text_output(State, Status, <<"">>, Headers, Text).
make_text_output(State, Status, Reason, Headers, Text) ->
Data = iolist_to_binary(Text),
Data2 = case State#state.request_method of
'HEAD' -> <<"">>;
_ -> Data
'HEAD' -> <<"">>;
_ -> Data
end,
[SL, H, <<"\r\n">>, Data2].
EncodedHdrs = make_headers(State, Status, Reason, Headers, Data2),
[EncodedHdrs, Data2].
make_file_output(State, Status, Headers, FileName) ->
case file:read_file_info(FileName) of
{ok, #file_info{size = Size}} when State#state.request_method == 'HEAD' ->
make_headers(State, Status, <<"">>, Headers, Size);
{ok, #file_info{size = Size}} ->
case file:open(FileName, [raw, read]) of
{ok, Fd} ->
EncodedHdrs = make_headers(State, Status, <<"">>, Headers, Size),
send_text(State, EncodedHdrs),
send_file(State, Fd, Size, FileName),
file:close(Fd),
none;
{error, Why} ->
Reason = file_format_error(Why),
?ERROR_MSG("Failed to open ~s: ~s", [FileName, Reason]),
make_text_output(State, 404, Reason, [], <<>>)
end;
{error, Why} ->
Reason = file_format_error(Why),
?ERROR_MSG("Failed to read info of ~s: ~s", [FileName, Reason]),
make_text_output(State, 404, Reason, [], <<>>)
end.
parse_lang(Langs) ->
case str:tokens(Langs, <<",; ">>) of
@@ -650,6 +717,12 @@ parse_lang(Langs) ->
[] -> <<"en">>
end.
file_format_error(Reason) ->
case file:format_error(Reason) of
"unknown POSIX error" -> atom_to_list(Reason);
Text -> Text
end.
% Code below is taken (with some modifications) from the yaws webserver, which
% is distributed under the following license:
%
@@ -679,7 +752,7 @@ url_decode_q_split(<<>>, Ack) ->
path_decode(Path) -> path_decode(Path, <<>>).
path_decode(<<$%, Hi, Lo, Tail/binary>>, Acc) ->
Hex = hex_to_integer([Hi, Lo]),
Hex = list_to_integer([Hi, Lo], 16),
if Hex == 0 -> exit(badurl);
true -> ok
end,
@@ -713,25 +786,10 @@ rest_dir(N, Path, <<_H, T/binary>>) -> rest_dir(N, Path, T).
expand_custom_headers(Headers) ->
lists:map(fun({K, V}) ->
{K, misc:expand_keyword(<<"@VERSION@">>, V, ?VERSION)}
{K, misc:expand_keyword(<<"@VERSION@">>, V,
ejabberd_config:get_version())}
end, Headers).
%% hex_to_integer
hex_to_integer(Hex) ->
case catch list_to_integer(Hex, 16) of
{'EXIT', _} -> old_hex_to_integer(Hex);
X -> X
end.
old_hex_to_integer(Hex) ->
DEHEX = fun (H) when H >= $a, H =< $f -> H - $a + 10;
(H) when H >= $A, H =< $F -> H - $A + 10;
(H) when H >= $0, H =< $9 -> H - $0
end,
lists:foldl(fun (E, Acc) -> Acc * 16 + DEHEX(E) end, 0,
Hex).
code_to_phrase(100) -> <<"Continue">>;
code_to_phrase(101) -> <<"Switching Protocols ">>;
code_to_phrase(200) -> <<"OK">>;
@@ -802,7 +860,7 @@ parse_urlencoded(S) ->
parse_urlencoded(<<$%, Hi, Lo, Tail/binary>>, Last, Cur,
State) ->
Hex = hex_to_integer([Hi, Lo]),
Hex = list_to_integer([Hi, Lo], 16),
parse_urlencoded(Tail, Last, <<Cur/binary, Hex>>, State);
parse_urlencoded(<<$&, Tail/binary>>, _Last, Cur, key) ->
[{Cur, <<"">>} | parse_urlencoded(Tail,
@@ -822,41 +880,6 @@ parse_urlencoded(<<>>, Last, Cur, _State) ->
[{Last, Cur}];
parse_urlencoded(undefined, _, _, _) -> [].
url_encode(A) ->
url_encode(A, <<>>).
url_encode(<<H:8, T/binary>>, Acc) when
(H >= $a andalso H =< $z) orelse
(H >= $A andalso H =< $Z) orelse
(H >= $0 andalso H =< $9) orelse
H == $_ orelse
H == $. orelse
H == $- orelse
H == $/ orelse
H == $: ->
url_encode(T, <<Acc/binary, H>>);
url_encode(<<H:8, T/binary>>, Acc) ->
case integer_to_hex(H) of
[X, Y] -> url_encode(T, <<Acc/binary, $%, X, Y>>);
[X] -> url_encode(T, <<Acc/binary, $%, $0, X>>)
end;
url_encode(<<>>, Acc) ->
Acc.
integer_to_hex(I) ->
case catch erlang:integer_to_list(I, 16) of
{'EXIT', _} -> old_integer_to_hex(I);
Int -> Int
end.
old_integer_to_hex(I) when I < 10 -> integer_to_list(I);
old_integer_to_hex(I) when I < 16 -> [I - 10 + $A];
old_integer_to_hex(I) when I >= 16 ->
N = trunc(I / 16),
old_integer_to_hex(N) ++ old_integer_to_hex(I rem 16).
% The following code is mostly taken from yaws_ssl.erl
toupper(C) when C >= $a andalso C =< $z -> C - 32;
@@ -894,11 +917,11 @@ get_certfile(Opts) ->
{_, CertFile} ->
CertFile;
false ->
case ejabberd_pkix:get_certfile(?MYNAME) of
case ejabberd_pkix:get_certfile(ejabberd_config:get_myname()) of
{ok, CertFile} ->
CertFile;
error ->
ejabberd_config:get_option({domain_certfile, ?MYNAME})
ejabberd_config:get_option({domain_certfile, ejabberd_config:get_myname()})
end
end.
@@ -928,7 +951,14 @@ transform_listen_option(Opt, Opts) ->
(atom()) -> [atom()].
opt_type(trusted_proxies) ->
fun (all) -> all;
(TPs) -> [iolist_to_binary(TP) || TP <- TPs] end;
(TPs) -> lists:filtermap(
fun(TP) ->
case acl:parse_ip_netmask(iolist_to_binary(TP)) of
{ok, Ip, Mask} -> {true, {Ip, Mask}};
_ -> false
end
end, TPs)
end;
opt_type(_) -> [trusted_proxies].
-spec listen_opt_type(tls) -> fun((boolean()) -> boolean());
@@ -998,6 +1028,8 @@ listen_opt_type(inet) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(inet6) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(backlog) ->
fun(I) when is_integer(I), I>0 -> I end;
listen_opt_type(accept_interval) ->
fun(I) when is_integer(I), I>=0 -> I end;
listen_opt_type(_) ->
%% TODO
fun(A) -> A end.
+6 -7
View File
@@ -35,9 +35,8 @@
terminate/3, send_xml/2, setopts/2, sockname/1,
peername/1, controlling_process/2, become_controller/2,
monitor/1, reset_stream/1, close/1, change_shaper/2,
socket_handoff/6, opt_type/1]).
socket_handoff/3, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
@@ -121,9 +120,8 @@ change_shaper({http_ws, _FsmRef, _IP}, _Shaper) ->
%% TODO???
ok.
socket_handoff(LocalPath, Request, Socket, SockMod, Buf, Opts) ->
ejabberd_websocket:socket_handoff(LocalPath, Request, Socket, SockMod,
Buf, Opts, ?MODULE, fun get_human_html_xmlel/0).
socket_handoff(LocalPath, Request, Opts) ->
ejabberd_websocket:socket_handoff(LocalPath, Request, Opts, ?MODULE, fun get_human_html_xmlel/0).
%%% Internal
@@ -134,14 +132,15 @@ init([{#ws{ip = IP, http_opts = HOpts}, _} = WS]) ->
({resume_timeout, _}) -> true;
({max_resume_timeout, _}) -> true;
({resend_on_timeout, _}) -> true;
({access, _}) -> true;
(_) -> false
end, HOpts),
Opts = ejabberd_c2s_config:get_c2s_limits() ++ SOpts,
PingInterval = ejabberd_config:get_option(
{websocket_ping_interval, ?MYNAME},
{websocket_ping_interval, ejabberd_config:get_myname()},
?PING_INTERVAL) * 1000,
WSTimeout = ejabberd_config:get_option(
{websocket_timeout, ?MYNAME},
{websocket_timeout, ejabberd_config:get_myname()},
?WEBSOCKET_TIMEOUT) * 1000,
Socket = {http_ws, self(), IP},
?DEBUG("Client connected through websocket ~p",
+1 -31
View File
@@ -34,7 +34,6 @@
add_listener/3, delete_listener/2, transform_options/1,
validate_cfg/1, opt_type/1, config_reloaded/0]).
-include("ejabberd.hrl").
-include("logger.hrl").
%% We do not block on send anymore.
@@ -256,36 +255,7 @@ get_ip_tuple(IPOpt, _IPVOpt) ->
IPOpt.
accept(ListenSocket, Module, Opts) ->
IntervalOpt =
case proplists:get_value(accept_interval, Opts) of
[{linear, [I1_, T1_, T2_, I2_]}] ->
{linear, I1_, T1_, T2_, I2_};
I_ -> I_
end,
Interval =
case IntervalOpt of
undefined ->
0;
I when is_integer(I), I >= 0 ->
I;
{linear, I1, T1, T2, I2}
when is_integer(I1),
is_integer(T1),
is_integer(T2),
is_integer(I2),
I1 >= 0,
I2 >= 0,
T2 > 0 ->
{MSec, Sec, _USec} = os:timestamp(),
TS = MSec * 1000000 + Sec,
{linear, I1, TS + T1, T2, I2};
I ->
?WARNING_MSG("There is a problem in the configuration: "
"~p is a wrong accept_interval value. "
"Using 0 as fallback",
[I]),
0
end,
Interval = proplists:get_value(accept_interval, Opts, 0),
accept(ListenSocket, Module, Opts, Interval).
accept(ListenSocket, Module, Opts, Interval) ->
+6 -59
View File
@@ -32,10 +32,8 @@
%% API
-export([start/0, start_link/0]).
-export([route/1, process_iq/1,
-export([route/1,
get_features/1,
register_iq_handler/4,
unregister_iq_handler/2,
bounce_resource_packet/1,
host_up/1, host_down/1]).
@@ -47,15 +45,12 @@
-export([route_iq/2, route_iq/3]).
-deprecated([{route_iq, 2}, {route_iq, 3}]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-include("xmpp.hrl").
-record(state, {}).
-define(IQTABLE, local_iqtable).
%%====================================================================
%% API
%%====================================================================
@@ -72,30 +67,6 @@ start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
[]).
-spec process_iq(iq()) -> any().
process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
when T == get; T == set ->
XMLNS = xmpp:get_ns(El),
Host = To#jid.lserver,
case ets:lookup(?IQTABLE, {Host, XMLNS}) of
[{_, Module, Function}] ->
gen_iq_handler:handle(Host, Module, Function, Packet);
[] ->
Txt = <<"No module is handling this query">>,
Err = xmpp:err_service_unavailable(Txt, Lang),
ejabberd_router:route_error(Packet, Err)
end;
process_iq(#iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
when T == get; T == set ->
Txt = case SubEls of
[] -> <<"No child elements found">>;
_ -> <<"Too many child elements">>
end,
Err = xmpp:err_bad_request(Txt, Lang),
ejabberd_router:route_error(Packet, Err);
process_iq(#iq{type = T}) when T == result; T == error ->
ok.
-spec route(stanza()) -> any().
route(Packet) ->
try do_route(Packet)
@@ -112,15 +83,6 @@ route_iq(IQ, Fun) ->
route_iq(IQ, Fun, Timeout) ->
ejabberd_router:route_iq(IQ, Fun, undefined, Timeout).
-spec register_iq_handler(binary(), binary(), module(), function()) -> ok.
register_iq_handler(Host, XMLNS, Module, Fun) ->
gen_server:cast(?MODULE,
{register_iq_handler, Host, XMLNS, Module, Fun}).
-spec unregister_iq_handler(binary(), binary()) -> ok.
unregister_iq_handler(Host, XMLNS) ->
gen_server:cast(?MODULE, {unregister_iq_handler, Host, XMLNS}).
-spec bounce_resource_packet(stanza()) -> ok | stop.
bounce_resource_packet(#presence{to = #jid{lresource = <<"">>}}) ->
ok;
@@ -135,12 +97,7 @@ bounce_resource_packet(Packet) ->
-spec get_features(binary()) -> [binary()].
get_features(Host) ->
get_features(ets:next(?IQTABLE, {Host, <<"">>}), Host, []).
get_features({Host, XMLNS}, Host, XMLNSs) ->
get_features(ets:next(?IQTABLE, {Host, XMLNS}), Host, [XMLNS|XMLNSs]);
get_features(_, _, XMLNSs) ->
XMLNSs.
gen_iq_handler:get_features(?MODULE, Host).
%%====================================================================
%% gen_server callbacks
@@ -148,26 +105,16 @@ get_features(_, _, XMLNSs) ->
init([]) ->
process_flag(trap_exit, true),
lists:foreach(fun host_up/1, ?MYHOSTS),
lists:foreach(fun host_up/1, ejabberd_config:get_myhosts()),
ejabberd_hooks:add(host_up, ?MODULE, host_up, 10),
ejabberd_hooks:add(host_down, ?MODULE, host_down, 100),
catch ets:new(?IQTABLE, [named_table, public, ordered_set,
{read_concurrency, true}]),
gen_iq_handler:start(?MODULE),
update_table(),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
Reply = ok, {reply, Reply, State}.
handle_cast({register_iq_handler, Host, XMLNS, Module, Function},
State) ->
ets:insert(?IQTABLE,
{{Host, XMLNS}, Module, Function}),
{noreply, State};
handle_cast({unregister_iq_handler, Host, XMLNS},
State) ->
ets:delete(?IQTABLE, {Host, XMLNS}),
{noreply, State};
handle_cast(_Msg, State) -> {noreply, State}.
handle_info({route, Packet}, State) ->
@@ -178,7 +125,7 @@ handle_info(Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
lists:foreach(fun host_down/1, ?MYHOSTS),
lists:foreach(fun host_down/1, ejabberd_config:get_myhosts()),
ejabberd_hooks:delete(host_up, ?MODULE, host_up, 10),
ejabberd_hooks:delete(host_down, ?MODULE, host_down, 100),
ok.
@@ -197,7 +144,7 @@ do_route(Packet) ->
if To#jid.luser /= <<"">> ->
ejabberd_sm:route(Packet);
is_record(Packet, iq), To#jid.lresource == <<"">> ->
process_iq(Packet);
gen_iq_handler:handle(?MODULE, Packet);
Type == result; Type == error ->
ok;
true ->
+1 -2
View File
@@ -30,7 +30,6 @@
-export([start/0, restart/0, reopen_log/0, rotate_log/0, get/0, set/1,
get_log_path/0, opt_type/1]).
-include("ejabberd.hrl").
-type loglevel() :: 0 | 1 | 2 | 3 | 4 | 5.
@@ -59,7 +58,7 @@ get_log_path() ->
undefined ->
case os:getenv("EJABBERD_LOG_PATH") of
false ->
?LOG_PATH;
"ejabberd.log";
Path ->
Path
end
-1
View File
@@ -54,7 +54,6 @@
-include("xmpp.hrl").
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_http.hrl").
+3 -4
View File
@@ -34,13 +34,12 @@
clean/1,
opt_type/1]).
-include("ejabberd.hrl").
-include("ejabberd_oauth.hrl").
-include("logger.hrl").
-include("jid.hrl").
init() ->
rest:start(?MYNAME),
rest:start(ejabberd_config:get_myname()),
ok.
store(R) ->
@@ -50,7 +49,7 @@ store(R) ->
SJID = jid:encode({User, Server, <<"">>}),
case rest:with_retry(
post,
[?MYNAME, Path, [],
[ejabberd_config:get_myname(), Path, [],
{[{<<"token">>, R#oauth_token.token},
{<<"user">>, SJID},
{<<"scope">>, R#oauth_token.scope},
@@ -65,7 +64,7 @@ store(R) ->
lookup(Token) ->
Path = path(<<"lookup">>),
case rest:with_retry(post, [?MYNAME, Path, [],
case rest:with_retry(post, [ejabberd_config:get_myname(), Path, [],
{[{<<"token">>, Token}]}],
2, 500) of
{ok, 200, {Data}} ->
+3 -4
View File
@@ -34,7 +34,6 @@
clean/1]).
-include("ejabberd_oauth.hrl").
-include("ejabberd.hrl").
-include("ejabberd_sql_pt.hrl").
-include("jid.hrl").
-include("logger.hrl").
@@ -49,7 +48,7 @@ store(R) ->
Scope = str:join(R#oauth_token.scope, <<" ">>),
Expire = R#oauth_token.expire,
case ?SQL_UPSERT(
?MYNAME,
ejabberd_config:get_myname(),
"oauth_token",
["!token=%(Token)s",
"jid=%(SJID)s",
@@ -63,7 +62,7 @@ store(R) ->
lookup(Token) ->
case ejabberd_sql:sql_query(
?MYNAME,
ejabberd_config:get_myname(),
?SQL("select @(jid)s, @(scope)s, @(expire)d"
" from oauth_token where token=%(Token)s")) of
{selected, [{SJID, Scope, Expire}]} ->
@@ -79,6 +78,6 @@ lookup(Token) ->
clean(TS) ->
ejabberd_sql:sql_query(
?MYNAME,
ejabberd_config:get_myname(),
?SQL("delete from oauth_token where expire < %(TS)d")).
+4 -2
View File
@@ -40,7 +40,7 @@
-define(CHUNK_SIZE, 1024*20). %20k
-include("ejabberd.hrl").
-include("scram.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-include("mod_privacy.hrl").
@@ -92,7 +92,7 @@ import_file(FileName, State) ->
-spec export_server(binary()) -> any().
export_server(Dir) ->
export_hosts(?MYHOSTS, Dir).
export_hosts(ejabberd_config:get_myhosts(), Dir).
-spec export_host(binary(), binary()) -> any().
export_host(Dir, Host) ->
@@ -404,6 +404,8 @@ process_user(#xmlel{name = <<"user">>, attrs = Attrs, children = Els},
case ejabberd_auth:try_register(LUser, LServer, Pass) of
ok ->
process_user_els(Els, State#state{user = LUser});
{error, invalid_password} when (Password == <<>>) ->
process_user_els(Els, State#state{user = LUser});
{error, Err} ->
stop("Failed to create user '~s': ~p", [Name, Err])
end
+161 -86
View File
@@ -49,9 +49,10 @@
-type bad_cert_reason() :: cert_expired | invalid_issuer | invalid_signature |
name_not_permitted | missing_basic_constraint |
invalid_key_usage | selfsigned_peer | unknown_sig_algo |
unknown_ca | missing_priv_key.
-type bad_cert() :: {bad_cert, bad_cert_reason()}.
-type cert_error() :: not_cert | not_der | not_pem | encrypted.
unknown_ca | missing_priv_key | unknown_key_algo |
unknown_key_type | encrypted | not_der | not_cert |
not_pem.
-type cert_error() :: {bad_cert, bad_cert_reason()}.
-export_type([cert_error/0]).
-define(CA_CACHE, ca_cache).
@@ -76,13 +77,13 @@ route_registered(Route) ->
gen_server:call(?MODULE, {route_registered, Route}).
-spec format_error(cert_error() | file:posix()) -> string().
format_error(not_cert) ->
format_error({bad_cert, not_cert}) ->
"no PEM encoded certificates found";
format_error(not_pem) ->
format_error({bad_cert, not_pem}) ->
"failed to decode from PEM format";
format_error(not_der) ->
format_error({bad_cert, not_der}) ->
"failed to decode from DER format";
format_error(encrypted) ->
format_error({bad_cert, encrypted}) ->
"encrypted certificate";
format_error({bad_cert, cert_expired}) ->
"certificate is no longer valid as its expiration date has passed";
@@ -103,6 +104,10 @@ format_error({bad_cert, selfsigned_peer}) ->
"self-signed certificate";
format_error({bad_cert, unknown_sig_algo}) ->
"certificate is signed using unknown algorithm";
format_error({bad_cert, unknown_key_algo}) ->
"unknown private key algorithm";
format_error({bad_cert, unknown_key_type}) ->
"private key is of unknown type";
format_error({bad_cert, unknown_ca}) ->
"certificate is signed by unknown CA";
format_error({bad_cert, missing_priv_key}) ->
@@ -172,6 +177,7 @@ config_reloaded() ->
true -> init_cache();
false -> delete_cache()
end,
fast_tls:clear_cache(),
gen_server:call(?MODULE, config_reloaded, 60000).
opt_type(ca_path) ->
@@ -328,7 +334,8 @@ get_certfiles_from_config_options(_State) ->
Host <- ejabberd_config:get_myhosts()]),
[iolist_to_binary(P) || P <- lists:usort(Local ++ Global)].
-spec add_certfiles(state()) -> {ok, state()} | {error, bad_cert()}.
-spec add_certfiles(state()) -> {ok, state()} |
{error, cert_error() | file:posix()}.
add_certfiles(State) ->
?DEBUG("Reading certificates", []),
Paths = get_certfiles_from_config_options(State),
@@ -342,7 +349,8 @@ add_certfiles(State) ->
{error, _} = Err -> Err
end.
-spec add_certfiles(binary(), state()) -> {ok, state()} | {error, bad_cert()}.
-spec add_certfiles(binary(), state()) -> {ok, state()} |
{error, cert_error() | file:posix()}.
add_certfiles(Host, State) ->
State1 = lists:foldl(
fun(Opt, AccState) ->
@@ -362,8 +370,8 @@ add_certfiles(Host, State) ->
{ok, State}
end.
-spec add_certfile(file:filename_all(), state()) -> {ok, state()} |
{{error, cert_error()}, state()}.
-spec add_certfile(file:filename_all(), state()) ->
{ok, state()} | {{error, cert_error() | file:posix()}, state()}.
add_certfile(Path, State) ->
case lists:member(Path, State#state.paths) of
true ->
@@ -385,30 +393,14 @@ add_certfile(Path, State) ->
end
end.
-spec build_chain_and_check(state()) -> ok | {error, bad_cert()}.
-spec build_chain_and_check(state()) -> ok | {error, cert_error() | file:posix()}.
build_chain_and_check(State) ->
?DEBUG("Building certificates graph", []),
CertPaths = get_cert_paths(maps:keys(State#state.certs), State#state.graph),
?DEBUG("Finding matched certificate keys", []),
case match_cert_keys(CertPaths, State#state.keys) of
{ok, Chains} ->
?DEBUG("Storing certificate chains", []),
CertFilesWithDomains = store_certs(Chains, []),
ets:delete_all_objects(?MODULE),
lists:foreach(
fun({Path, Domain}) ->
fast_tls:add_certfile(Domain, Path),
ets:insert(?MODULE, {Domain, Path})
end, CertFilesWithDomains),
?DEBUG("Validating certificates", []),
Errors = validate(CertPaths, State#state.validate),
?DEBUG("Subscribing to file events", []),
lists:foreach(
fun({Cert, Why}) ->
Path = maps:get(Cert, State#state.certs),
?WARNING_MSG("Failed to validate certificate from ~s: ~s",
[Path, format_error(Why)])
end, Errors);
InvalidCerts = validate(CertPaths, State),
SortedChains = sort_chains(Chains, InvalidCerts),
store_certs(SortedChains, State);
{error, Cert, Why} ->
Path = maps:get(Cert, State#state.certs),
?ERROR_MSG("Failed to build certificate chain for ~s: ~s",
@@ -416,9 +408,35 @@ build_chain_and_check(State) ->
{error, Why}
end.
-spec store_certs([{[cert()], priv_key()}],
[{binary(), binary()}]) -> [{binary(), binary()}].
store_certs([{Certs, Key}|Chains], Acc) ->
-spec store_certs([{[cert()], priv_key()}], state()) -> ok | {error, file:posix()}.
store_certs(Chains, State) ->
?DEBUG("Storing certificate chains", []),
Res = lists:foldl(
fun(_, {error, _} = Err) ->
Err;
({Certs, Key}, Acc) ->
case store_cert(Certs, Key, State) of
{ok, FileDoms} ->
Acc ++ FileDoms;
{error, _} = Err ->
Err
end
end, [], Chains),
case Res of
{error, Why} ->
{error, Why};
FileDomains ->
ets:delete_all_objects(?MODULE),
lists:foreach(
fun({Path, Domain}) ->
fast_tls:add_certfile(Domain, Path),
ets:insert(?MODULE, {Domain, Path})
end, FileDomains)
end.
-spec store_cert([cert()], priv_key(), state()) -> {ok, [{binary(), binary()}]} |
{error, file:posix()}.
store_cert(Certs, Key, State) ->
CertPEMs = public_key:pem_encode(
lists:map(
fun(Cert) ->
@@ -432,20 +450,51 @@ store_certs([{Certs, Key}|Chains], Acc) ->
not_encrypted}]),
PEMs = <<CertPEMs/binary, KeyPEM/binary>>,
Cert = hd(Certs),
Domains = xmpp_stream_pkix:get_cert_domains(Cert),
FileName = filename:join(certs_dir(), str:sha(PEMs)),
case file:write_file(FileName, PEMs) of
ok ->
file:change_mode(FileName, 8#600),
NewAcc = [{FileName, Domain} || Domain <- Domains] ++ Acc,
store_certs(Chains, NewAcc);
{error, Why} ->
case xmpp_stream_pkix:get_cert_domains(Cert) of
[] ->
Path = maps:get(Cert, State#state.certs),
?WARNING_MSG("Certificate from ~s doesn't define "
"any domain names", [Path]),
{ok, [{FileName, <<"">>}]};
Domains ->
{ok, [{FileName, Domain} || Domain <- Domains]}
end;
{error, Why} = Err ->
?ERROR_MSG("Failed to write to ~s: ~s",
[FileName, file:format_error(Why)]),
store_certs(Chains, [])
end;
store_certs([], Acc) ->
Acc.
Err
end.
-spec sort_chains([{[cert()], priv_key()}], [cert()]) -> [{[cert()], priv_key()}].
sort_chains(Chains, InvalidCerts) ->
lists:sort(
fun({[Cert1|_], _}, {[Cert2|_], _}) ->
IsValid1 = not lists:member(Cert1, InvalidCerts),
IsValid2 = not lists:member(Cert2, InvalidCerts),
if IsValid1 and not IsValid2 ->
false;
IsValid2 and not IsValid1 ->
true;
true ->
compare_expiration_date(Cert1, Cert2)
end
end, Chains).
%% Returns true if the first certificate has sooner expiration date
-spec compare_expiration_date(cert(), cert()) -> boolean().
compare_expiration_date(#'OTPCertificate'{
tbsCertificate =
#'OTPTBSCertificate'{
validity = #'Validity'{notAfter = After1}}},
#'OTPCertificate'{
tbsCertificate =
#'OTPTBSCertificate'{
validity = #'Validity'{notAfter = After2}}}) ->
get_timestamp(After1) =< get_timestamp(After2).
-spec load_certfile(file:filename_all()) -> {ok, [cert()], [priv_key()]} |
{error, cert_error() | file:posix()}.
@@ -471,57 +520,69 @@ pem_decode(Data) ->
(_) -> false
end, Objects) of
{[], []} ->
{error, not_cert};
{error, {bad_cert, not_cert}};
{Certs, PrivKeys} ->
{ok, Certs, PrivKeys}
end
end
catch _:_ ->
{error, not_pem}
catch E:R ->
St = erlang:get_stacktrace(),
?DEBUG("PEM decoding stacktrace: ~p", [{E, {R, St}}]),
{error, {bad_cert, not_pem}}
end.
-spec decode_certs([public_key:pem_entry()]) -> {[cert()], [priv_key()]} |
{error, not_der | encrypted}.
-spec decode_certs([public_key:pem_entry()]) -> [cert() | priv_key()] |
{error, cert_error()}.
decode_certs(PemEntries) ->
try lists:foldr(
fun(_, {error, _} = Err) ->
Err;
({_, _, Flag}, _) when Flag /= not_encrypted ->
{error, encrypted};
({'Certificate', Der, _}, Acc) ->
[public_key:pkix_decode_cert(Der, otp)|Acc];
({'PrivateKeyInfo', Der, not_encrypted}, Acc) ->
#'PrivateKeyInfo'{privateKeyAlgorithm =
#'PrivateKeyInfo_privateKeyAlgorithm'{
algorithm = Algo},
privateKey = Key} =
public_key:der_decode('PrivateKeyInfo', Der),
case Algo of
?'rsaEncryption' ->
[public_key:der_decode(
'RSAPrivateKey', iolist_to_binary(Key))|Acc];
?'id-dsa' ->
[public_key:der_decode(
'DSAPrivateKey', iolist_to_binary(Key))|Acc];
?'id-ecPublicKey' ->
[public_key:der_decode(
'ECPrivateKey', iolist_to_binary(Key))|Acc];
_ ->
Acc
end;
({Tag, Der, _}, Acc) when Tag == 'RSAPrivateKey';
Tag == 'DSAPrivateKey';
Tag == 'ECPrivateKey' ->
[public_key:der_decode(Tag, Der)|Acc];
(_, Acc) ->
Acc
end, [], PemEntries)
catch _:_ ->
{error, not_der}
try lists:flatmap(
fun({Tag, Der, Flag}) ->
decode_cert(Tag, Der, Flag)
end, PemEntries)
catch _:{bad_cert, _} = Err ->
{error, Err};
E:R ->
St = erlang:get_stacktrace(),
?DEBUG("DER decoding stacktrace: ~p", [{E, {R, St}}]),
{error, {bad_cert, not_der}}
end.
-spec validate([{path, [cert()]}], boolean()) -> [{cert(), bad_cert()}].
validate(Paths, true) ->
-spec decode_cert(atom(), binary(), atom()) -> [cert() | priv_key()].
decode_cert(_, _, Flag) when Flag /= not_encrypted ->
erlang:error({bad_cert, encrypted});
decode_cert('Certificate', Der, _) ->
[public_key:pkix_decode_cert(Der, otp)];
decode_cert('PrivateKeyInfo', Der, not_encrypted) ->
case public_key:der_decode('PrivateKeyInfo', Der) of
#'PrivateKeyInfo'{privateKeyAlgorithm =
#'PrivateKeyInfo_privateKeyAlgorithm'{
algorithm = Algo},
privateKey = Key} ->
KeyBin = iolist_to_binary(Key),
case Algo of
?'rsaEncryption' ->
[public_key:der_decode('RSAPrivateKey', KeyBin)];
?'id-dsa' ->
[public_key:der_decode('DSAPrivateKey', KeyBin)];
?'id-ecPublicKey' ->
[public_key:der_decode('ECPrivateKey', KeyBin)];
_ ->
erlang:error({bad_cert, unknown_key_algo})
end;
#'RSAPrivateKey'{} = Key -> [Key];
#'DSAPrivateKey'{} = Key -> [Key];
#'ECPrivateKey'{} = Key -> [Key];
_ -> erlang:error({bad_cert, unknown_key_type})
end;
decode_cert(Tag, Der, _) when Tag == 'RSAPrivateKey';
Tag == 'DSAPrivateKey';
Tag == 'ECPrivateKey' ->
[public_key:der_decode(Tag, Der)];
decode_cert(_, _, _) ->
[].
-spec validate([{path, [cert()]}], state()) -> [cert()].
validate(Paths, #state{validate = true} = State) ->
?DEBUG("Validating certificates", []),
{ok, Re} = re:compile("^[a-f0-9]+\\.[0-9]+$", [unicode]),
Hashes = case file:list_dir(ca_dir()) of
{ok, Files} ->
@@ -550,13 +611,16 @@ validate(Paths, true) ->
ok ->
false;
{error, Cert, Reason} ->
{true, {Cert, Reason}}
File = maps:get(Cert, State#state.certs),
?WARNING_MSG("Failed to validate certificate from ~s: ~s",
[File, format_error(Reason)]),
{true, Cert}
end
end, Paths);
validate(_, _) ->
[].
-spec validate_path([cert()], dict:dict()) -> ok | {error, cert(), bad_cert()}.
-spec validate_path([cert()], dict:dict()) -> ok | {error, cert(), cert_error()}.
validate_path([Cert|_] = Certs, Cache) ->
case find_local_issuer(Cert, Cache) of
{ok, IssuerCert} ->
@@ -714,6 +778,7 @@ do_read_ca_file(Path) ->
-spec match_cert_keys([{path, [cert()]}], [priv_key()])
-> {ok, [{cert(), priv_key()}]} | {error, {bad_cert, missing_priv_key}}.
match_cert_keys(CertPaths, PrivKeys) ->
?DEBUG("Finding matched certificate keys", []),
KeyPairs = [{pubkey_from_privkey(PrivKey), PrivKey} || PrivKey <- PrivKeys],
match_cert_keys(CertPaths, KeyPairs, []).
@@ -762,6 +827,7 @@ pubkey_from_privkey(#'ECPrivateKey'{publicKey = Key}) ->
-spec get_cert_paths([cert()], digraph:graph()) -> [{path, [cert()]}].
get_cert_paths(Certs, G) ->
?DEBUG("Building certificates graph", []),
{NewCerts, OldCerts} =
lists:partition(
fun(Cert) ->
@@ -837,6 +903,15 @@ short_name_hash(_) ->
"".
-endif.
-spec get_timestamp({utcTime | generalTime, string()}) -> string().
get_timestamp({utcTime, [Y1,Y2|T]}) ->
case list_to_integer([Y1,Y2]) of
N when N >= 50 -> [$1,$9,Y1,Y2|T];
_ -> [$2,$0,Y1,Y2|T]
end;
get_timestamp({generalTime, TS}) ->
TS.
wildcard(Path) when is_binary(Path) ->
wildcard(binary_to_list(Path));
wildcard(Path) ->
+2 -3
View File
@@ -33,7 +33,6 @@
-export([start_link/0, init/1, opt_type/1,
config_reloaded/0, start_host/1, stop_host/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
start_link() ->
@@ -56,7 +55,7 @@ get_specs() ->
{ok, Spec} -> [Spec];
undefined -> []
end
end, ?MYHOSTS).
end, ejabberd_config:get_myhosts()).
-spec get_spec(binary()) -> {ok, supervisor:child_spec()} | undefined.
get_spec(Host) ->
@@ -72,7 +71,7 @@ get_spec(Host) ->
-spec config_reloaded() -> ok.
config_reloaded() ->
lists:foreach(fun start_host/1, ?MYHOSTS).
lists:foreach(fun start_host/1, ejabberd_config:get_myhosts()).
-spec start_host(binary()) -> ok.
start_host(Host) ->
-1
View File
@@ -50,7 +50,6 @@
-define(CALL_TIMEOUT, 60*1000). %% 60 seconds
-include("logger.hrl").
-include("ejabberd.hrl").
-record(state, {connection :: pid() | undefined,
num :: pos_integer(),
+1 -2
View File
@@ -32,7 +32,6 @@
%% Supervisor callbacks
-export([init/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-define(DEFAULT_POOL_SIZE, 10).
@@ -98,7 +97,7 @@ init([]) ->
%%% Internal functions
%%%===================================================================
is_redis_configured() ->
lists:any(fun is_redis_configured/1, ?MYHOSTS).
lists:any(fun is_redis_configured/1, ejabberd_config:get_myhosts()).
is_redis_configured(Host) ->
ServerConfigured = ejabberd_config:has_option({redis_server, Host}),
-1
View File
@@ -41,7 +41,6 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
-record(state, {pid = self() :: pid()}).
+1 -2
View File
@@ -33,7 +33,6 @@
transform_options/1, get_random_pid/0,
host_up/1, config_reloaded/0, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-define(DEFAULT_POOL_SIZE, 10).
@@ -74,7 +73,7 @@ config_reloaded() ->
end.
is_riak_configured() ->
lists:any(fun is_riak_configured/1, ?MYHOSTS).
lists:any(fun is_riak_configured/1, ejabberd_config:get_myhosts()).
is_riak_configured(Host) ->
ServerConfigured = ejabberd_config:has_option({riak_server, Host}),
+2 -7
View File
@@ -68,7 +68,6 @@
%% This value is used in SIP and Megaco for a transaction lifetime.
-define(IQ_TIMEOUT, 32000).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_router.hrl").
-include("xmpp.hrl").
@@ -306,12 +305,8 @@ is_my_host(Domain) ->
end.
-spec process_iq(iq()) -> any().
process_iq(#iq{to = To} = IQ) ->
if To#jid.luser == <<"">> ->
ejabberd_local:process_iq(IQ);
true ->
ejabberd_sm:process_iq(IQ)
end.
process_iq(IQ) ->
gen_iq_handler:handle(IQ).
-spec config_reloaded() -> ok.
config_reloaded() ->
-1
View File
@@ -30,7 +30,6 @@
-export([init/1, handle_cast/2, handle_call/3, handle_info/2,
terminate/2, code_change/3, start_link/0]).
-include("ejabberd.hrl").
-include("ejabberd_router.hrl").
-include("logger.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-1
View File
@@ -41,7 +41,6 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-1
View File
@@ -31,7 +31,6 @@
-export([init/1, handle_cast/2, handle_call/3, handle_info/2,
terminate/2, code_change/3, start_link/0]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_router.hrl").
+5 -6
View File
@@ -29,7 +29,6 @@
-export([init/0, register_route/5, unregister_route/3, find_routes/1,
get_all_routes/0]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_sql_pt.hrl").
-include("ejabberd_router.hrl").
@@ -41,7 +40,7 @@ init() ->
Node = erlang:atom_to_binary(node(), latin1),
?DEBUG("Cleaning SQL 'route' table...", []),
case ejabberd_sql:sql_query(
?MYNAME, ?SQL("delete from route where node=%(Node)s")) of
ejabberd_config:get_myname(), ?SQL("delete from route where node=%(Node)s")) of
{updated, _} ->
ok;
Err ->
@@ -53,7 +52,7 @@ register_route(Domain, ServerHost, LocalHint, _, Pid) ->
PidS = misc:encode_pid(Pid),
LocalHintS = enc_local_hint(LocalHint),
Node = erlang:atom_to_binary(node(Pid), latin1),
case ?SQL_UPSERT(?MYNAME, "route",
case ?SQL_UPSERT(ejabberd_config:get_myname(), "route",
["!domain=%(Domain)s",
"!server_host=%(ServerHost)s",
"!node=%(Node)s",
@@ -69,7 +68,7 @@ unregister_route(Domain, _, Pid) ->
PidS = misc:encode_pid(Pid),
Node = erlang:atom_to_binary(node(Pid), latin1),
case ejabberd_sql:sql_query(
?MYNAME,
ejabberd_config:get_myname(),
?SQL("delete from route where domain=%(Domain)s "
"and pid=%(PidS)s and node=%(Node)s")) of
{updated, _} ->
@@ -80,7 +79,7 @@ unregister_route(Domain, _, Pid) ->
find_routes(Domain) ->
case ejabberd_sql:sql_query(
?MYNAME,
ejabberd_config:get_myname(),
?SQL("select @(server_host)s, @(node)s, @(pid)s, @(local_hint)s "
"from route where domain=%(Domain)s")) of
{selected, Rows} ->
@@ -94,7 +93,7 @@ find_routes(Domain) ->
get_all_routes() ->
case ejabberd_sql:sql_query(
?MYNAME,
ejabberd_config:get_myname(),
?SQL("select @(domain)s from route where domain <> server_host")) of
{selected, Domains} ->
{ok, [Domain || {Domain} <- Domains]};
+3 -4
View File
@@ -54,7 +54,6 @@
-export([get_info_s2s_connections/1,
transform_options/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
@@ -303,7 +302,7 @@ init([]) ->
{attributes, record_info(fields, temporarily_blocked)}]),
ejabberd_hooks:add(host_up, ?MODULE, host_up, 50),
ejabberd_hooks:add(host_down, ?MODULE, host_down, 60),
lists:foreach(fun host_up/1, ?MYHOSTS),
lists:foreach(fun host_up/1, ejabberd_config:get_myhosts()),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
@@ -322,7 +321,7 @@ handle_info(_Info, State) -> {noreply, State}.
terminate(_Reason, _State) ->
ejabberd_commands:unregister_commands(get_commands_spec()),
lists:foreach(fun host_down/1, ?MYHOSTS),
lists:foreach(fun host_down/1, ejabberd_config:get_myhosts()),
ejabberd_hooks:delete(host_up, ?MODULE, host_up, 50),
ejabberd_hooks:delete(host_down, ?MODULE, host_down, 60),
ok.
@@ -544,7 +543,7 @@ is_service(From, To) ->
s2s -> % bypass RFC 3920 10.3
false;
local ->
Hosts = (?MYHOSTS),
Hosts = ejabberd_config:get_myhosts(),
P = fun (ParentDomain) ->
lists:member(ParentDomain, Hosts)
end,
+8 -6
View File
@@ -44,7 +44,6 @@
-export([stop/1, close/1, close/2, send/2, update_state/2, establish/1,
host_up/1, host_down/1]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
-include("logger.hrl").
@@ -263,10 +262,10 @@ init([State, Opts]) ->
State1 = State#{tls_options => TLSOpts2,
auth_domains => sets:new(),
xmlns => ?NS_SERVER,
lang => ?MYLANG,
server => ?MYNAME,
lserver => ?MYNAME,
server_host => ?MYNAME,
lang => ejabberd_config:get_mylang(),
server => ejabberd_config:get_myname(),
lserver => ejabberd_config:get_myname(),
server_host => ejabberd_config:get_myname(),
established => false,
shaper => Shaper},
State2 = xmpp_stream_in:set_timeout(State1, Timeout),
@@ -388,6 +387,9 @@ listen_opt_type(inet) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(inet6) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(backlog) ->
fun(I) when is_integer(I), I>0 -> I end;
listen_opt_type(accept_interval) ->
fun(I) when is_integer(I), I>=0 -> I end;
listen_opt_type(_) ->
[shaper, certfile, ciphers, dhfile, cafile, protocol_options,
tls_compression, tls, max_fsm_queue, backlog, inet, inet6].
tls_compression, tls, max_fsm_queue, backlog, inet, inet6,
accept_interval].
+3 -4
View File
@@ -42,7 +42,6 @@
-export([start/3, start_link/3, connect/1, close/1, close/2, stop/1, send/2,
route/2, establish/1, update_state/2, host_up/1, host_down/1]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
-include("logger.hrl").
@@ -61,12 +60,12 @@ start(From, To, Opts) ->
Res -> Res
end;
_ ->
xmpp_stream_out:start(?MODULE, [xmpp_socket, From, To, Opts],
xmpp_stream_out:start(?MODULE, [From, To, Opts],
ejabberd_config:fsm_limit_opts([]))
end.
start_link(From, To, Opts) ->
xmpp_stream_out:start_link(?MODULE, [xmpp_socket, From, To, Opts],
xmpp_stream_out:start_link(?MODULE, [From, To, Opts],
ejabberd_config:fsm_limit_opts([])).
-spec connect(pid()) -> ok.
@@ -274,7 +273,7 @@ init([#{server := LServer, remote_server := RServer} = State, Opts]) ->
State1 = State#{on_route => queue,
queue => p1_queue:new(QueueType, QueueLimit),
xmlns => ?NS_SERVER,
lang => ?MYLANG,
lang => ejabberd_config:get_mylang(),
server_host => ServerHost,
shaper => none},
State2 = xmpp_stream_out:set_timeout(State1, Timeout),
+14 -7
View File
@@ -36,7 +36,6 @@
%% API
-export([send/2]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
-include("logger.hrl").
@@ -106,8 +105,8 @@ init([State, Opts]) ->
State2 = xmpp_stream_in:set_timeout(State1, Timeout),
State3 = State2#{access => Access,
xmlns => ?NS_COMPONENT,
lang => ?MYLANG,
server => ?MYNAME,
lang => ejabberd_config:get_mylang(),
server => ejabberd_config:get_myname(),
host_opts => dict:from_list(HostOpts1),
stream_version => undefined,
tls_options => TLSOpts,
@@ -170,7 +169,7 @@ handle_auth_success(_, Mech, _,
end,
lists:foreach(
fun(H) ->
ejabberd_router:register_route(H, ?MYNAME),
ejabberd_router:register_route(H, ejabberd_config:get_myname()),
ejabberd_hooks:run(component_connected, [H])
end, Routes),
State.
@@ -191,8 +190,14 @@ handle_authenticated_packet(Pkt0, #{ip := {IP, _}, lang := Lang} = State)
From = xmpp:get_from(Pkt),
case check_from(From, State) of
true ->
ejabberd_router:route(Pkt),
State;
{Pkt2, State2} = ejabberd_hooks:run_fold(component_send_packet, {Pkt, State}, []),
case Pkt2 of
drop ->
ok;
_ ->
ejabberd_router:route(Pkt2)
end,
State2;
false ->
Txt = <<"Improper domain part of 'from' attribute">>,
Err = xmpp:serr_invalid_from(Txt, Lang),
@@ -335,7 +340,9 @@ listen_opt_type(inet) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(inet6) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(backlog) ->
fun(I) when is_integer(I), I>0 -> I end;
listen_opt_type(accept_interval) ->
fun(I) when is_integer(I), I>=0 -> I end;
listen_opt_type(_) ->
[access, shaper_rule, certfile, ciphers, dhfile, cafile, tls,
protocol_options, tls_compression, password, hosts, check_from,
max_fsm_queue, global_routes, backlog, inet, inet6].
max_fsm_queue, global_routes, backlog, inet, inet6, accept_interval].
+5 -4
View File
@@ -44,7 +44,6 @@ start(_, _) ->
-export([tcp_init/2, udp_init/2, udp_recv/5, start/2,
socket_type/0, listen_opt_type/1]).
-include("ejabberd.hrl").
%%%===================================================================
%%% API
@@ -71,11 +70,11 @@ set_certfile(Opts) ->
true ->
Opts;
false ->
case ejabberd_pkix:get_certfile(?MYNAME) of
case ejabberd_pkix:get_certfile(ejabberd_config:get_myname()) of
{ok, CertFile} ->
[{certfile, CertFile}|Opts];
error ->
case ejabberd_config:get_option({domain_certfile, ?MYNAME}) of
case ejabberd_config:get_option({domain_certfile, ejabberd_config:get_myname()}) of
undefined ->
Opts;
CertFile ->
@@ -93,8 +92,10 @@ listen_opt_type(certfile) ->
end;
listen_opt_type(tls) ->
fun(B) when is_boolean(B) -> B end;
listen_opt_type(accept_interval) ->
fun(I) when is_integer(I), I>=0 -> I end;
listen_opt_type(_) ->
[tls, certfile].
[tls, certfile, accept_interval].
%%%===================================================================
%%% Internal functions
+32 -66
View File
@@ -39,7 +39,6 @@
stop/0,
route/1,
route/2,
process_iq/1,
open_session/5,
open_session/6,
close_session/4,
@@ -58,13 +57,12 @@
get_vh_session_list/1,
get_vh_session_number/1,
get_vh_by_backend/1,
register_iq_handler/4,
unregister_iq_handler/2,
force_update_presence/1,
connected_users/0,
connected_users_number/0,
user_resources/2,
kick_user/2,
kick_user/3,
get_session_pid/3,
get_session_sid/3,
get_session_sids/2,
@@ -87,7 +85,6 @@
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
@@ -245,10 +242,12 @@ get_user_info(User, Server) ->
LServer = jid:nameprep(Server),
Mod = get_sm_backend(LServer),
Ss = online(get_sessions(Mod, LUser, LServer)),
[{LResource, [{node, node(Pid)}|Info]}
[{LResource, [{node, node(Pid)}, {ts, Ts}, {pid, Pid},
{priority, Priority} | Info]}
|| #session{usr = {_, _, LResource},
priority = Priority,
info = Info,
sid = {_, Pid}} <- clean_session_list(Ss)].
sid = {Ts, Pid}} <- clean_session_list(Ss)].
-spec get_user_info(binary(), binary(), binary()) -> info() | offline.
@@ -262,8 +261,11 @@ get_user_info(User, Server, Resource) ->
offline;
Ss ->
Session = lists:max(Ss),
Node = node(element(2, Session#session.sid)),
[{node, Node}|Session#session.info]
{Ts, Pid} = Session#session.sid,
Node = node(Pid),
Priority = Session#session.priority,
[{node, Node}, {ts, Ts}, {pid, Pid}, {priority, Priority}
|Session#session.info]
end.
-spec set_presence(sid(), binary(), binary(), binary(),
@@ -397,17 +399,6 @@ get_vh_session_number(Server) ->
Mod = get_sm_backend(LServer),
length(online(get_sessions(Mod, LServer))).
-spec register_iq_handler(binary(), binary(), atom(), atom()) -> ok.
register_iq_handler(Host, XMLNS, Module, Fun) ->
?GEN_SERVER:cast(?MODULE,
{register_iq_handler, Host, XMLNS, Module, Fun}).
-spec unregister_iq_handler(binary(), binary()) -> ok.
unregister_iq_handler(Host, XMLNS) ->
?GEN_SERVER:cast(?MODULE, {unregister_iq_handler, Host, XMLNS}).
%% Why the hell do we have so many similar kicks?
c2s_handle_info(#{lang := Lang} = State, replaced) ->
State1 = State#{replaced => true},
@@ -437,26 +428,17 @@ init([]) ->
init_cache(),
lists:foreach(fun(Mod) -> Mod:init() end, get_sm_backends()),
clean_cache(),
ets:new(sm_iqtable, [named_table, public, {read_concurrency, true}]),
gen_iq_handler:start(?MODULE),
ejabberd_hooks:add(host_up, ?MODULE, host_up, 50),
ejabberd_hooks:add(host_down, ?MODULE, host_down, 60),
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 50),
lists:foreach(fun host_up/1, ?MYHOSTS),
lists:foreach(fun host_up/1, ejabberd_config:get_myhosts()),
ejabberd_commands:register_commands(get_commands_spec()),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
Reply = ok, {reply, Reply, State}.
handle_cast({register_iq_handler, Host, XMLNS, Module, Function},
State) ->
ets:insert(sm_iqtable,
{{Host, XMLNS}, Module, Function}),
{noreply, State};
handle_cast({unregister_iq_handler, Host, XMLNS},
State) ->
ets:delete(sm_iqtable, {Host, XMLNS}),
{noreply, State};
handle_cast(_Msg, State) -> {noreply, State}.
handle_info({route, Packet}, State) ->
@@ -467,7 +449,7 @@ handle_info(Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
lists:foreach(fun host_down/1, ?MYHOSTS),
lists:foreach(fun host_down/1, ejabberd_config:get_myhosts()),
ejabberd_hooks:delete(host_up, ?MODULE, host_up, 50),
ejabberd_hooks:delete(host_down, ?MODULE, host_down, 60),
ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 50),
@@ -664,7 +646,7 @@ do_route(#message{to = #jid{lresource = <<"">>}, type = T} = Packet) ->
end;
do_route(#iq{to = #jid{lresource = <<"">>}} = Packet) ->
?DEBUG("processing IQ to bare JID:~n~s", [xmpp:pp(Packet)]),
process_iq(Packet);
gen_iq_handler:handle(?MODULE, Packet);
do_route(Packet) ->
?DEBUG("processing packet to full JID:~n~s", [xmpp:pp(Packet)]),
To = xmpp:get_to(Packet),
@@ -849,31 +831,6 @@ get_max_user_sessions(LUser, Host) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec process_iq(iq()) -> any().
process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
when T == get; T == set ->
XMLNS = xmpp:get_ns(El),
Host = To#jid.lserver,
case ets:lookup(sm_iqtable, {Host, XMLNS}) of
[{_, Module, Function}] ->
gen_iq_handler:handle(Host, Module, Function, Packet);
[] ->
Txt = <<"No module is handling this query">>,
Err = xmpp:err_service_unavailable(Txt, Lang),
ejabberd_router:route_error(Packet, Err)
end;
process_iq(#iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
when T == get; T == set ->
Txt = case SubEls of
[] -> <<"No child elements found">>;
_ -> <<"Too many child elements">>
end,
Err = xmpp:err_bad_request(Txt, Lang),
ejabberd_router:route_error(Packet, Err);
process_iq(#iq{}) ->
ok.
-spec force_update_presence({binary(), binary()}) -> ok.
force_update_presence({LUser, LServer}) ->
@@ -895,7 +852,7 @@ get_sm_backend(Host) ->
-spec get_sm_backends() -> [module()].
get_sm_backends() ->
lists:usort([get_sm_backend(Host) || Host <- ?MYHOSTS]).
lists:usort([get_sm_backend(Host) || Host <- ejabberd_config:get_myhosts()]).
-spec get_vh_by_backend(module()) -> [binary()].
@@ -903,7 +860,7 @@ get_vh_by_backend(Mod) ->
lists:filter(
fun(Host) ->
get_sm_backend(Host) == Mod
end, ?MYHOSTS).
end, ejabberd_config:get_myhosts()).
%%--------------------------------------------------------------------
%%% Cache stuff
@@ -966,7 +923,7 @@ use_cache() ->
fun(Host) ->
Mod = get_sm_backend(Host),
use_cache(Mod, Host)
end, ?MYHOSTS).
end, ejabberd_config:get_myhosts()).
-spec cache_nodes(module(), binary()) -> [node()].
cache_nodes(Mod, LServer) ->
@@ -1026,14 +983,23 @@ user_resources(User, Server) ->
Resources = get_user_resources(User, Server),
lists:sort(Resources).
-spec kick_user(binary(), binary()) -> non_neg_integer().
kick_user(User, Server) ->
Resources = get_user_resources(User, Server),
lists:foreach(
fun(Resource) ->
PID = get_session_pid(User, Server, Resource),
ejabberd_c2s:route(PID, kick)
end, Resources),
length(Resources).
lists:foldl(
fun(Resource, Acc) ->
case kick_user(User, Server, Resource) of
false -> Acc;
true -> Acc + 1
end
end, 0, Resources).
-spec kick_user(binary(), binary(), binary()) -> boolean().
kick_user(User, Server, Resource) ->
case get_session_pid(User, Server, Resource) of
none -> false;
Pid -> ejabberd_c2s:route(Pid, kick)
end.
make_sid() ->
{p1_time_compat:unique_timestamp(), self()}.
-1
View File
@@ -40,7 +40,6 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3, start_link/0]).
-include("ejabberd.hrl").
-include("ejabberd_sm.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-1
View File
@@ -37,7 +37,6 @@
-export([init/1, handle_cast/2, handle_call/3, handle_info/2,
terminate/2, code_change/3, start_link/0]).
-include("ejabberd.hrl").
-include("ejabberd_sm.hrl").
-include("logger.hrl").
-1
View File
@@ -36,7 +36,6 @@
get_sessions/1,
get_sessions/2]).
-include("ejabberd.hrl").
-include("ejabberd_sm.hrl").
-include("logger.hrl").
-include("ejabberd_sql_pt.hrl").
-1
View File
@@ -66,7 +66,6 @@
session_established/2, session_established/3,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_sql_pt.hrl").
+1 -7
View File
@@ -33,7 +33,6 @@
get_pids/1, get_random_pid/1, transform_options/1,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-define(PGSQL_PORT, 5432).
@@ -172,12 +171,7 @@ check_sqlite_db(Host) ->
end.
create_sqlite_tables(DB) ->
SqlDir = case code:priv_dir(ejabberd) of
{error, _} ->
?SQL_DIR;
PrivDir ->
filename:join(PrivDir, "sql")
end,
SqlDir = misc:sql_dir(),
File = filename:join(SqlDir, "lite.sql"),
case file:open(File, [read, binary]) of
{ok, Fd} ->
+7 -6
View File
@@ -46,7 +46,6 @@ start(_, _) ->
-export([tcp_init/2, udp_init/2, udp_recv/5, start/2,
socket_type/0, listen_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
%%%===================================================================
@@ -79,7 +78,7 @@ prepare_turn_opts(Opts) ->
prepare_turn_opts(Opts, _UseTurn = false) ->
set_certfile(Opts);
prepare_turn_opts(Opts, _UseTurn = true) ->
NumberOfMyHosts = length(?MYHOSTS),
NumberOfMyHosts = length(ejabberd_config:get_myhosts()),
case proplists:get_value(turn_ip, Opts) of
undefined ->
?WARNING_MSG("option 'turn_ip' is undefined, "
@@ -100,11 +99,11 @@ prepare_turn_opts(Opts, _UseTurn = true) ->
"'auth_type' is set to 'user', "
"more likely the TURN relay won't "
"be working properly. Using ~s as "
"a fallback", [?MYNAME]);
"a fallback", [ejabberd_config:get_myname()]);
true ->
ok
end,
[{auth_realm, ?MYNAME}];
[{auth_realm, ejabberd_config:get_myname()}];
_ ->
[]
end,
@@ -118,7 +117,7 @@ set_certfile(Opts) ->
true ->
Opts;
false ->
Realm = proplists:get_value(auth_realm, Opts, ?MYNAME),
Realm = proplists:get_value(auth_realm, Opts, ejabberd_config:get_myname()),
case ejabberd_pkix:get_certfile(Realm) of
{ok, CertFile} ->
[{certfile, CertFile}|Opts];
@@ -174,8 +173,10 @@ listen_opt_type(server_name) ->
fun iolist_to_binary/1;
listen_opt_type(backlog) ->
fun(I) when is_integer(I), I>0 -> I end;
listen_opt_type(accept_interval) ->
fun(I) when is_integer(I), I>=0 -> I end;
listen_opt_type(_) ->
[shaper, auth_type, auth_realm, tls, certfile, turn_min_port,
turn_max_port, turn_max_allocations, turn_max_permissions,
server_name, backlog].
server_name, backlog, accept_interval].
-endif.
+22 -22
View File
@@ -31,7 +31,7 @@
-author('ekhramtsov@process-one.net').
%% API
-export([start/0, opt_type/1]).
-export([start/0, opt_type/1, config_reloaded/0]).
%% gen_event callbacks
-export([init/1, handle_event/2, handle_call/2,
@@ -42,7 +42,6 @@
%%-include("logger.hrl").
-define(CHECK_INTERVAL, timer:seconds(30)).
-define(DISK_FULL_THRES, 0.99).
-record(state, {tref :: reference(),
mref :: reference()}).
@@ -67,30 +66,29 @@ start() ->
application:set_env(os_mon, start_cpu_sup, false),
application:set_env(os_mon, start_os_sup, false),
application:set_env(os_mon, start_memsup, true),
application:set_env(os_mon, start_disksup, true),
application:set_env(os_mon, disk_almost_full_threshold, ?DISK_FULL_THRES),
ejabberd:start_app(os_mon).
application:set_env(os_mon, start_disksup, false),
ejabberd:start_app(os_mon),
set_oom_watermark().
excluded_apps() ->
[os_mon, mnesia, sasl, stdlib, kernel].
-spec config_reloaded() -> ok.
config_reloaded() ->
set_oom_watermark().
%%%===================================================================
%%% gen_event callbacks
%%%===================================================================
init([]) ->
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 50),
{ok, #state{}}.
handle_event({set_alarm, {system_memory_high_watermark, _}}, State) ->
error_logger:warning_msg(
"More than 80% of OS memory is allocated, "
"starting OOM watchdog", []),
handle_overload(State),
{ok, restart_timer(State)};
handle_event({clear_alarm, system_memory_high_watermark}, State) ->
cancel_timer(State#state.tref),
error_logger:info_msg(
"Memory consumption is back to normal, "
"stopping OOM watchdog", []),
{ok, State#state{tref = undefined}};
handle_event({set_alarm, {process_memory_high_watermark, Pid}}, State) ->
case proc_stat(Pid, get_app_pids()) of
@@ -105,12 +103,6 @@ handle_event({set_alarm, {process_memory_high_watermark, Pid}}, State) ->
end;
handle_event({clear_alarm, process_memory_high_watermark}, State) ->
{ok, State};
handle_event({set_alarm, {{disk_almost_full, MountPoint}, _}}, State) ->
error_logger:warning_msg("Disk is almost full on ~p", [MountPoint]),
{ok, State};
handle_event({clear_alarm, {disk_almost_full, MountPoint}}, State) ->
error_logger:info_msg("Disk usage is back to normal on ~p", [MountPoint]),
{ok, State};
handle_event(Event, State) ->
error_logger:warning_msg("unexpected event: ~p", [Event]),
{ok, State}.
@@ -126,7 +118,7 @@ handle_info(Info, State) ->
{ok, State}.
terminate(_Reason, _State) ->
ok.
ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 50).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
@@ -142,7 +134,8 @@ handle_overload(State) ->
handle_overload(_State, Procs) ->
AppPids = get_app_pids(),
{TotalMsgs, ProcsNum, Apps, Stats} = overloaded_procs(AppPids, Procs),
if TotalMsgs >= 10000 ->
MaxMsgs = ejabberd_config:get_option(oom_queue, 10000),
if TotalMsgs >= MaxMsgs ->
SortedStats = lists:reverse(lists:keysort(#proc_stat.qlen, Stats)),
error_logger:warning_msg(
"The system is overloaded with ~b messages "
@@ -326,14 +319,21 @@ kill_proc(Pid) ->
exit(Pid, kill),
Pid.
-spec set_oom_watermark() -> ok.
set_oom_watermark() ->
WaterMark = ejabberd_config:get_option(oom_watermark, 80),
memsup:set_sysmem_high_watermark(WaterMark/100).
-spec maybe_restart_app(atom()) -> any().
maybe_restart_app(lager) ->
ejabberd_logger:restart();
maybe_restart_app(_) ->
ok.
-spec opt_type(oom_killer) -> fun((boolean()) -> boolean());
(atom()) -> [atom()].
opt_type(oom_killer) ->
fun(B) when is_boolean(B) -> B end;
opt_type(_) -> [oom_killer].
opt_type(oom_watermark) ->
fun(I) when is_integer(I), I>0, I<100 -> I end;
opt_type(oom_queue) ->
fun(I) when is_integer(I), I>0 -> I end;
opt_type(_) -> [oom_killer, oom_watermark, oom_queue].
-1
View File
@@ -29,7 +29,6 @@
%% API
-export([update/0, update/1, update_info/0]).
-include("ejabberd.hrl").
-include("logger.hrl").
%%====================================================================
-1
View File
@@ -31,7 +31,6 @@
%% External exports
-export([make_xhtml/1, make_xhtml/2, error/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
+6 -7
View File
@@ -35,7 +35,6 @@
list_users_in_diapason/4, pretty_print_xml/1,
term_to_id/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
@@ -1062,7 +1061,7 @@ parse_access_rule(Text) ->
%%%% list_vhosts
list_vhosts(Lang, JID) ->
Hosts = (?MYHOSTS),
Hosts = ejabberd_config:get_myhosts(),
HostsAllowed = lists:filter(fun (Host) ->
acl:any_rules_allowed(Host,
[configure, webadmin_view],
@@ -1240,7 +1239,7 @@ list_given_users(Host, Users, Prefix, Lang, URLFunc) ->
?XE(<<"tr">>,
[?XE(<<"td">>,
[?AC((URLFunc({user, Prefix,
ejabberd_http:url_encode(User),
misc:url_encode(User),
Server})),
(us_to_list(US)))]),
?XE(<<"td">>, FQueueLen),
@@ -1282,7 +1281,7 @@ get_stats(global, Lang) ->
ejabberd_auth:count_users(Host)
+ Total
end,
0, ?MYHOSTS),
0, ejabberd_config:get_myhosts()),
OutS2SNumber = ejabberd_s2s:outgoing_s2s_number(),
InS2SNumber = ejabberd_s2s:incoming_s2s_number(),
[?XAE(<<"table">>, [],
@@ -1319,7 +1318,7 @@ list_online_users(Host, _Lang) ->
SUsers = lists:usort(Users),
lists:flatmap(fun ({_S, U} = SU) ->
[?AC(<<"../user/",
(ejabberd_http:url_encode(U))/binary, "/">>,
(misc:url_encode(U))/binary, "/">>,
(su_to_list(SU))),
?BR]
end,
@@ -1784,7 +1783,7 @@ get_node(global, Node, [<<"backup">>], Query, Lang) ->
?C(<<" ">>),
?INPUT(<<"text">>,
<<"export_piefxis_host_dirhost">>,
(?MYNAME))]),
(ejabberd_config:get_myname()))]),
?XE(<<"td">>,
[?INPUT(<<"text">>,
<<"export_piefxis_host_dirpath">>,
@@ -1800,7 +1799,7 @@ get_node(global, Node, [<<"backup">>], Query, Lang) ->
?C(<<" ">>),
?INPUT(<<"text">>,
<<"export_sql_filehost">>,
(?MYNAME))]),
(ejabberd_config:get_myname()))]),
?XE(<<"td">>,
[?INPUT(<<"text">>,
<<"export_sql_filepath">>,
+7 -7
View File
@@ -42,9 +42,8 @@
-author('ecestari@process-one.net').
-export([check/2, socket_handoff/8]).
-export([check/2, socket_handoff/5]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
@@ -89,8 +88,9 @@ check(_Path, Headers) ->
socket_handoff(LocalPath, #request{method = 'GET', ip = IP, q = Q, path = Path,
headers = Headers, host = Host, port = Port,
opts = HOpts},
Socket, SockMod, Buf, _Opts, HandlerModule, InfoMsgFun) ->
socket = Socket, sockmod = SockMod,
data = Buf, opts = HOpts},
_Opts, HandlerModule, InfoMsgFun) ->
case check(LocalPath, Headers) of
true ->
WS = #ws{socket = Socket,
@@ -109,11 +109,11 @@ socket_handoff(LocalPath, #request{method = 'GET', ip = IP, q = Q, path = Path,
_ ->
{200, ?HEADER, InfoMsgFun()}
end;
socket_handoff(_, #request{method = 'OPTIONS'}, _, _, _, _, _, _) ->
socket_handoff(_, #request{method = 'OPTIONS'}, _, _, _) ->
{200, ?OPTIONS_HEADER, []};
socket_handoff(_, #request{method = 'HEAD'}, _, _, _, _, _, _) ->
socket_handoff(_, #request{method = 'HEAD'}, _, _, _) ->
{200, ?HEADER, []};
socket_handoff(_, _, _, _, _, _, _, _) ->
socket_handoff(_, _, _, _, _) ->
{400, ?HEADER, #xmlel{name = <<"h1">>,
children = [{xmlcdata, <<"400 Bad Request">>}]}}.
+4 -2
View File
@@ -37,7 +37,6 @@
-export([start/2, handler/2, process/2, socket_type/0,
transform_listen_option/2, listen_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_http.hrl").
-include("mod_roster.hrl").
@@ -585,5 +584,8 @@ listen_opt_type(inet) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(inet6) -> fun(B) when is_boolean(B) -> B end;
listen_opt_type(backlog) ->
fun(I) when is_integer(I), I>0 -> I end;
listen_opt_type(accept_interval) ->
fun(I) when is_integer(I), I>=0 -> I end;
listen_opt_type(_) ->
[access_commands, maxsessions, timeout, backlog, inet, inet6].
[access_commands, maxsessions, timeout, backlog, inet, inet6,
accept_interval].
-1
View File
@@ -51,7 +51,6 @@ modules() ->
[ejabberd_auth,
mod_announce,
mod_caps,
mod_irc,
mod_last,
mod_mam,
mod_muc,
+71 -13
View File
@@ -65,7 +65,6 @@
-behaviour(p1_fsm).
-include("ejabberd.hrl").
-include("logger.hrl").
%% External exports
@@ -88,7 +87,7 @@
-export_type([filter/0]).
-include("ELDAPv3.hrl").
-include_lib("kernel/include/inet.hrl").
-include("eldap.hrl").
-define(LDAP_VERSION, 3).
@@ -139,8 +138,8 @@
passwd = <<"">> :: binary(),
id = 0 :: non_neg_integer(),
bind_timer = make_ref() :: reference(),
dict = dict:new() :: ?TDICT,
req_q = queue:new() :: ?TQUEUE}).
dict = dict:new() :: dict:dict(),
req_q = queue:new() :: queue:queue()}).
%%%----------------------------------------------------------------------
%%% API
@@ -1057,15 +1056,11 @@ connect_bind(S) ->
?DEBUG("Connecting to LDAP server at ~s:~p with options ~p",
[Host, S#eldap.port, Opts]),
HostS = binary_to_list(Host),
SocketData = case S#eldap.tls of
tls ->
SockMod = ssl, ssl:connect(HostS, S#eldap.port, Opts);
%% starttls -> %% TODO: Implement STARTTLS;
_ ->
SockMod = gen_tcp,
gen_tcp:connect(HostS, S#eldap.port, Opts)
end,
case SocketData of
SockMod = case S#eldap.tls of
tls -> ssl;
_ -> gen_tcp
end,
case connect(HostS, S#eldap.port, SockMod, Opts) of
{ok, Socket} ->
case bind_request(Socket, S#eldap{sockmod = SockMod}) of
{ok, NewS} ->
@@ -1132,3 +1127,66 @@ format_error(SockMod, Reason) ->
_ ->
Txt
end.
%%--------------------------------------------------------------------
%% Connecting stuff
%%--------------------------------------------------------------------
-define(CONNECT_TIMEOUT, timer:seconds(15)).
-define(DNS_TIMEOUT, timer:seconds(5)).
connect(Host, Port, Mod, Opts) ->
case lookup(Host) of
{ok, AddrsFamilies} ->
do_connect(AddrsFamilies, Port, Mod, Opts, {error, nxdomain});
{error, _} = Err ->
Err
end.
do_connect([{IP, Family}|AddrsFamilies], Port, Mod, Opts, _Err) ->
case Mod:connect(IP, Port, [Family|Opts], ?CONNECT_TIMEOUT) of
{ok, Sock} ->
{ok, Sock};
{error, _} = Err ->
do_connect(AddrsFamilies, Port, Mod, Opts, Err)
end;
do_connect([], _Port, _Mod, _Opts, Err) ->
Err.
lookup(Host) ->
case inet:parse_address(Host) of
{ok, IP} ->
{ok, [{IP, get_addr_type(IP)}]};
{error, _} ->
do_lookup([{Host, Family} || Family <- [inet6, inet]],
[], {error, nxdomain})
end.
do_lookup([{Host, Family}|HostFamilies], AddrFamilies, Err) ->
case inet:gethostbyname(Host, Family, ?DNS_TIMEOUT) of
{ok, HostEntry} ->
Addrs = host_entry_to_addrs(HostEntry),
AddrFamilies1 = [{Addr, Family} || Addr <- Addrs],
do_lookup(HostFamilies,
AddrFamilies ++ AddrFamilies1,
Err);
{error, _} = Err1 ->
do_lookup(HostFamilies, AddrFamilies, Err1)
end;
do_lookup([], [], Err) ->
Err;
do_lookup([], AddrFamilies, _Err) ->
{ok, AddrFamilies}.
host_entry_to_addrs(#hostent{h_addr_list = AddrList}) ->
lists:filter(
fun(Addr) ->
try get_addr_type(Addr) of
_ -> true
catch _:badarg ->
false
end
end, AddrList).
get_addr_type({_, _, _, _}) -> inet;
get_addr_type({_, _, _, _, _, _, _, _}) -> inet6;
get_addr_type(_) -> erlang:error(badarg).
-1
View File
@@ -31,7 +31,6 @@
-export([start_link/7, bind/3, search/2,
modify_passwd/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
%%====================================================================
-1
View File
@@ -34,7 +34,6 @@
decode_octet_string/3, uids_domain_subst/2, opt_type/1,
options/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("eldap.hrl").
+14 -14
View File
@@ -33,7 +33,7 @@
available_command/0, available/0, available/1,
installed_command/0, installed/0, installed/1,
install/1, uninstall/1, upgrade/0, upgrade/1,
add_sources/2, del_sources/1, modules_dir/0,
add_sources/1, add_sources/2, del_sources/1, modules_dir/0,
config_dir/0, opt_type/1, get_commands_spec/0]).
-export([compile_erlang_file/2, compile_elixir_file/2]).
@@ -56,7 +56,8 @@ init([]) ->
process_flag(trap_exit, true),
[code:add_patha(module_ebin_dir(Module))
|| {Module, _} <- installed()],
p1_http:start(),
application:start(inets),
inets:start(httpc, [{profile, ext_mod}]),
ejabberd_commands:register_commands(get_commands_spec()),
{ok, #state{}}.
@@ -313,23 +314,22 @@ check(Package) when is_binary(Package) ->
%% -- archives and variables functions
geturl(Url) ->
geturl(Url, []).
geturl(Url, UsrOpts) ->
geturl(Url, [], UsrOpts).
geturl(Url, Hdrs, UsrOpts) ->
Host = case getenv("PROXY_SERVER", "", ":") of
[H, Port] -> [{proxy_host, H}, {proxy_port, list_to_integer(Port)}];
[H] -> [{proxy_host, H}, {proxy_port, 8080}];
_ -> []
case getenv("PROXY_SERVER", "", ":") of
[H, Port] ->
httpc:set_options([{proxy, {{H, list_to_integer(Port)}, []}}], ext_mod);
[H] ->
httpc:set_options([{proxy, {{H, 8080}, []}}], ext_mod);
_ ->
ok
end,
User = case getenv("PROXY_USER", "", [4]) of
[U, Pass] -> [{proxy_user, U}, {proxy_password, Pass}];
[U, Pass] -> [{proxy_auth, {U, Pass}}];
_ -> []
end,
case p1_http:request(get, Url, Hdrs, [], Host++User++UsrOpts++[{version, "HTTP/1.0"}]) of
{ok, 200, Headers, Response} ->
case httpc:request(get, {Url, []}, User, [{body_format, binary}], ext_mod) of
{ok, {{_, 200, _}, Headers, Response}} ->
{ok, Headers, Response};
{ok, Code, _Headers, Response} ->
{ok, {{_, Code, _}, _Headers, Response}} ->
{error, {Code, Response}};
{error, Reason} ->
{error, Reason}
+155 -105
View File
@@ -1,8 +1,5 @@
%%%----------------------------------------------------------------------
%%% File : extauth.erl
%%% Author : Leif Johansson <leifj@it.su.se>
%%% Purpose : External authentication using a simple port-driver
%%% Created : 30 Jul 2004 by Leif Johansson <leifj@it.su.se>
%%%-------------------------------------------------------------------
%%% Created : 7 May 2018 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2018 ProcessOne
@@ -21,54 +18,45 @@
%%% with this program; if not, write to the Free Software Foundation, Inc.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%----------------------------------------------------------------------
%%%-------------------------------------------------------------------
-module(extauth).
-behaviour(ejabberd_config).
-ifndef(GEN_SERVER).
-define(GEN_SERVER, gen_server).
-endif.
-behaviour(?GEN_SERVER).
-author('leifj@it.su.se').
-define(CALL_TIMEOUT, timer:seconds(30)).
-export([start/2, stop/1, init/2, check_password/3,
set_password/3, try_register/3, remove_user/2,
remove_user/3, user_exists/2, opt_type/1]).
%% API
-export([start/1, stop/1, reload/1, start_link/2]).
-export([check_password/3, set_password/3, try_register/3, remove_user/2,
remove_user/3, user_exists/2]).
-export([prog_name/1, pool_name/1, worker_name/2, pool_size/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
-define(INIT_TIMEOUT, 60000).
-record(state, {port :: port(),
prog :: string(),
start_time :: integer(),
os_pid :: integer() | undefined}).
-define(CALL_TIMEOUT, 10000).
start(Host, ExtPrg) ->
lists:foreach(fun (This) ->
start_instance(get_process_name(Host, This), ExtPrg)
end,
lists:seq(0, get_instances(Host) - 1)).
start_instance(ProcessName, ExtPrg) ->
spawn(?MODULE, init, [ProcessName, ExtPrg]).
restart_instance(ProcessName, ExtPrg) ->
unregister(ProcessName),
start_instance(ProcessName, ExtPrg).
init(ProcessName, ExtPrg) ->
register(ProcessName, self()),
process_flag(trap_exit, true),
Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
loop(Port, ?INIT_TIMEOUT, ProcessName, ExtPrg).
%%%===================================================================
%%% API
%%%===================================================================
start(Host) ->
extauth_sup:start(Host).
stop(Host) ->
lists:foreach(fun (This) ->
get_process_name(Host, This) ! stop
end,
lists:seq(0, get_instances(Host) - 1)).
extauth_sup:stop(Host).
get_process_name(Host, Integer) ->
gen_mod:get_module_proc(iolist_to_binary([Host,
integer_to_list(Integer)]),
eauth).
reload(Host) ->
extauth_sup:reload(Host).
start_link(Name, Prog) ->
?GEN_SERVER:start_link({local, Name}, ?MODULE, [Prog], []).
check_password(User, Server, Password) ->
call_port(Server, [<<"auth">>, User, Server, Password]).
@@ -80,82 +68,144 @@ set_password(User, Server, Password) ->
call_port(Server, [<<"setpass">>, User, Server, Password]).
try_register(User, Server, Password) ->
case call_port(Server,
[<<"tryregister">>, User, Server, Password])
of
true -> ok;
false -> {error, not_allowed}
end.
call_port(Server, [<<"tryregister">>, User, Server, Password]).
remove_user(User, Server) ->
call_port(Server, [<<"removeuser">>, User, Server]).
remove_user(User, Server, Password) ->
call_port(Server,
[<<"removeuser3">>, User, Server, Password]).
call_port(Server, [<<"removeuser3">>, User, Server, Password]).
call_port(Server, Msg) ->
LServer = jid:nameprep(Server),
ProcessName = get_process_name(LServer,
random_instance(get_instances(LServer))),
ProcessName ! {call, self(), Msg},
receive {eauth, Result} -> Result end.
-spec prog_name(binary()) -> string() | undefined.
prog_name(Host) ->
ejabberd_config:get_option({extauth_program, Host}).
random_instance(MaxNum) ->
randoms:uniform(MaxNum) - 1.
-spec pool_name(binary()) -> atom().
pool_name(Host) ->
list_to_atom("extauth_pool_" ++ binary_to_list(Host)).
get_instances(Server) ->
ejabberd_config:get_option({extauth_instances, Server}, 1).
-spec worker_name(atom(), integer()) -> atom().
worker_name(Pool, N) ->
list_to_atom(atom_to_list(Pool) ++ "_" ++ integer_to_list(N)).
loop(Port, Timeout, ProcessName, ExtPrg) ->
receive
{call, Caller, Msg} ->
port_command(Port, encode(Msg)),
receive
{Port, {data, Data}} ->
?DEBUG("extauth call '~p' received data response:~n~p",
[Msg, Data]),
Caller ! {eauth, decode(Data)},
loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg);
{Port, Other} ->
?ERROR_MSG("extauth call '~p' received strange response:~n~p",
[Msg, Other]),
Caller ! {eauth, false},
loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg)
-spec pool_size(binary()) -> pos_integer().
pool_size(Host) ->
case ejabberd_config:get_option({extauth_pool_size, Host}) of
undefined ->
try erlang:system_info(logical_processors)
catch _:_ -> 1
end;
Size ->
Size
end.
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([Prog]) ->
process_flag(trap_exit, true),
{Port, OSPid} = start_port(Prog),
Time = curr_time(),
{ok, #state{port = Port, start_time = Time,
prog = Prog, os_pid = OSPid}}.
handle_call({cmd, Cmd, EndTime}, _From, State) ->
Timeout = EndTime - curr_time(),
if Timeout > 0 ->
Port = State#state.port,
port_command(Port, Cmd),
receive
{Port, {data, [0, N] = Data}} when N == 0; N == 1 ->
?DEBUG("Received response from external authentication "
"program: ~p", [Data]),
{reply, decode_bool(N), State};
{Port, Data} ->
?ERROR_MSG("Received unexpected response from external "
"authentication program '~s': ~p "
"(port = ~p, pid = ~w)",
[State#state.prog, Data, Port, State#state.os_pid]),
{reply, {error, unexpected_response}, State};
{'EXIT', Port, Reason} ->
handle_info({'EXIT', Port, Reason}, State)
after Timeout ->
?ERROR_MSG("extauth call '~p' didn't receive response",
[Msg]),
Caller ! {eauth, false},
Pid = restart_instance(ProcessName, ExtPrg),
flush_buffer_and_forward_messages(Pid),
exit(port_terminated)
end;
stop ->
Port ! {self(), close},
receive {Port, closed} -> exit(normal) end;
{'EXIT', Port, Reason} ->
?CRITICAL_MSG("extauth script has exitted abruptly "
"with reason '~p'",
[Reason]),
Pid = restart_instance(ProcessName, ExtPrg),
flush_buffer_and_forward_messages(Pid),
exit(port_terminated)
{stop, normal, State}
end;
true ->
{noreply, State}
end.
flush_buffer_and_forward_messages(Pid) ->
receive
Message ->
Pid ! Message, flush_buffer_and_forward_messages(Pid)
after 0 -> true
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info({'EXIT', Port, _Reason}, #state{port = Port,
start_time = Time} = State) ->
case curr_time() - Time of
Diff when Diff < 1000 ->
?ERROR_MSG("Failed to start external authentication program '~s'",
[State#state.prog]),
{stop, normal, State};
_ ->
?ERROR_MSG("External authentication program '~s' has terminated "
"unexpectedly (pid=~w), restarting via supervisor...",
[State#state.prog, State#state.os_pid]),
{stop, normal, State}
end;
handle_info(Info, State) ->
?WARNING_MSG("Unexpected info: ~p", [Info]),
{noreply, State}.
terminate(_Reason, State) ->
catch port_close(State#state.port),
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
-spec curr_time() -> non_neg_integer().
curr_time() ->
p1_time_compat:monotonic_time(milli_seconds).
-spec start_port(string()) -> {port(), integer() | undefined}.
start_port(Path) ->
Port = open_port({spawn, Path}, [{packet, 2}]),
link(Port),
case erlang:port_info(Port, os_pid) of
{os_pid, OSPid} ->
{Port, OSPid};
undefined ->
{Port, undefined}
end.
encode(L) -> str:join(L, <<":">>).
call_port(Server, Args) ->
call_port(Server, Args, ?CALL_TIMEOUT).
decode([0, 0]) -> false;
decode([0, 1]) -> true.
call_port(Server, Args, Timeout) ->
StartTime = p1_time_compat:monotonic_time(milli_seconds),
Pool = pool_name(Server),
PoolSize = pool_size(Server),
I = randoms:round_robin(PoolSize),
Cmd = str:join(Args, <<":">>),
do_call(Cmd, I, I + PoolSize, Pool, PoolSize,
StartTime + Timeout, StartTime).
-spec opt_type(extauth_instances) -> fun((pos_integer()) -> pos_integer());
(atom()) -> [atom()].
opt_type(extauth_instances) ->
fun (V) when is_integer(V), V > 0 -> V end;
opt_type(_) -> [extauth_instances].
do_call(_, Max, Max, _, _, _, _) ->
{error, disconnected};
do_call(Cmd, I, Max, Pool, PoolSize, EndTime, CurrTime) ->
Timeout = EndTime - CurrTime,
if Timeout > 0 ->
Proc = worker_name(Pool, (I rem PoolSize) + 1),
try ?GEN_SERVER:call(Proc, {cmd, Cmd, EndTime}, Timeout)
catch exit:{timeout, {?GEN_SERVER, call, _}} ->
{error, timeout};
exit:{_, {?GEN_SERVER, call, _}} ->
do_call(Cmd, I+1, Max, Pool, PoolSize, EndTime, curr_time())
end;
true ->
{error, timeout}
end.
decode_bool(0) -> false;
decode_bool(1) -> true.
+110
View File
@@ -0,0 +1,110 @@
%%%-------------------------------------------------------------------
%%% Created : 7 May 2018 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2018 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License along
%%% with this program; if not, write to the Free Software Foundation, Inc.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%-------------------------------------------------------------------
-module(extauth_sup).
-behaviour(supervisor).
%% API
-export([start/1, stop/1, reload/1, start_link/3]).
%% Supervisor callbacks
-export([init/1]).
-include("logger.hrl").
%%%===================================================================
%%% API functions
%%%===================================================================
start(Host) ->
case extauth:prog_name(Host) of
undefined ->
?ERROR_MSG("Option 'extauth_program' is not set for '~s'",
[Host]),
ignore;
Prog ->
Pool = extauth:pool_name(Host),
ChildSpec = {Pool, {?MODULE, start_link, [Host, Prog, Pool]},
permanent, infinity, supervisor, [?MODULE]},
supervisor:start_child(ejabberd_backend_sup, ChildSpec)
end.
stop(Host) ->
Pool = extauth:pool_name(Host),
supervisor:terminate_child(ejabberd_backend_sup, Pool),
supervisor:delete_child(ejabberd_backend_sup, Pool).
reload(Host) ->
Pool = extauth:pool_name(Host),
Prog = extauth:prog_name(Host),
PoolSize = extauth:pool_size(Host),
try process_info(whereis(Pool), dictionary) of
{dictionary, Dict} ->
case proplists:get_value(extauth_program, Dict) of
Prog ->
OldPoolSize = try supervisor:which_children(Pool) of
Children -> length(Children)
catch _:_ -> PoolSize
end,
if OldPoolSize > PoolSize ->
lists:foreach(
fun(I) ->
Worker = extauth:worker_name(Pool, I),
supervisor:terminate_child(Pool, Worker),
supervisor:delete_child(Pool, Worker)
end, lists:seq(PoolSize+1, OldPoolSize));
OldPoolSize < PoolSize ->
lists:foreach(
fun(I) ->
Spec = worker_spec(Pool, Prog, I),
supervisor:start_child(Pool, Spec)
end, lists:seq(OldPoolSize+1, PoolSize));
OldPoolSize == PoolSize ->
ok
end;
_ ->
stop(Host),
start(Host)
end
catch _:badarg ->
ok
end.
start_link(Host, Prog, Pool) ->
supervisor:start_link({local, Pool}, ?MODULE, [Host, Prog, Pool]).
%%%===================================================================
%%% Supervisor callbacks
%%%===================================================================
init([Host, Prog, Pool]) ->
PoolSize = extauth:pool_size(Host),
Children = lists:map(
fun(I) ->
worker_spec(Pool, Prog, I)
end, lists:seq(1, PoolSize)),
put(extauth_program, Prog),
{ok, {{one_for_one, PoolSize, 1}, Children}}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
worker_spec(Pool, Prog, I) ->
Worker = extauth:worker_name(Pool, I),
{Worker, {extauth, start_link, [Worker, Prog]},
permanent, 5000, worker, [extauth]}.

Some files were not shown because too many files have changed in this diff Show More