Support chat marker (XEP-0333) stanzas when the "--chat-marker" switch
is provided on the command line. A chat marker is prefixed by 'M':
~~~
M:groupchat:test@conference.example.com/msantos:me@example.com/162315501161646113068402:
~~~
The idea is to allow scripts to react based on whether a message has
been read, for example, escalating via other channels.
strcmp(3) segfaulted when comparing the from address to NULL.
Checking messages originated from the output account only makes sense
with groupchat. Remove the check for type of "chat".
An empty string in the type, to and from uses a default value. For
example to send a message to the groupchat specified on the command
line:
~~~
m::::this is a test message
~~~
Rough implementation to allow input to be formatted as colon separated
values in the same way as output:
* percent decoding of the input is not supported yet
* only message stanzas supported
Using formatted input lets the script respond to other users aside from
the default channel assigned to stdout:
~~~
m:chat:to@example.com:from@example.com:message-body
~~~
TODO:
* does the default stdout channel always need to be formatted?
~~~
m:chat:to@example.com:from@example.com:message-body
m:groupchat:default@conference.example.com:from@example.com:message-body
~~~
Otherwise it could be ambiguous.
* support presence and iq stanzas
For example, a bot could respond to groupchat invitations.
* percent decoding: require the input to be percent encoded
Support binary and multiline data.
* format naming: choose better names for the format types
Instead of supplying the output JID as an optional argument:
xmppipe --output foo@conference.example.com
Use the first argument:
xmppipe foo@conference.example.com
The -o/--output switches are still accepted.
Running xmppipe in chat mode without a full jid:
xmppipe --chat --output foo
Caused a segfault when a NULL domain was passed to
xmpp_stanza_set_attribute(). The libstrophe functions do not check for
NULL and so crash calling strlen(NULL).
Set the jid's domain from the user's username. If the user's jid is
user@example.com:
# expanded to foo@example.com
xmppipe --chat --output foo
Document usage of one to one chat:
xmppipe --chat --output me@example.com
Only provide the long option until a few quirks have been worked out:
* if only a username is provided, it will be expanded to a conference
name
# expands to me@conference.example.com
xmppipe --chat --output me
* should "normal" and "headline" message types also be supported?
* tests
* always add id in iq stanzas.
* presence: response from muc may contain more than one 'x' element,
match stanza by namespace
* debug: print out current state
Add preliminary support to one to one chats. No XEPs were read in the
preparation of this change:
xmppipe -C example@example.com
TODO
* clean up
* state change is hardcoded
* if (GROUPCHAT) branches
* autodetect MUC
* in chat mode, ctrl-D can cause a loop
Terminate long option list so xmppipe doesn't segfault when passed an
unknown option.
Correct the usage. Revert to using --ouput for the MUC name instead of
--stdout to avoid confusion.
Add a sandbox enforced before options are parsed and the connection is
established to the XMPP server. This sandbox will allow network
operations.
The post-connect sandbox is unchanged and restricts operations to stdio.
The commit just adds the infrastructure for the pre-connect sandbox.
When base64 encoding is enabled, ignore any messages that fail base64
decoding.
Previously signed-unsigned integer conversion would cause the return
value of b64_pton() on error (a negative integer) to be converted to a
large value. The attempt to allocate this value would force xmppipe to
exit.
The rlimit sandbox disables forking processes and opening files.
The rlimit sandbox is not used by default yet. To compile it:
XMPPIPE_SANDBOX=XMPPIPE_SANDBOX_RLIMIT make
The rlimit sandbox should work on any platform. However the interaction
of RLIMIT_NOFILE with poll(2) (and select(2)?) on some platforms (FreeBSD
but really any OS besides Linux) is problematic:
* opening a number of fd's, setting RLIMIT_NOFILE to 0, calling
poll(2) on the fdset
Linux: works
FreeBSD: fails
* opening a number of fd's, setting RLIMIT_NOFILE to maxfd+1, calling
poll(2) on the fdset
Linux: works
FreeBSD: works
The issue with the second option is that a library may have opened a
sequence of file descriptors then closed the lower numbered fd's:
open() => 3
open() => 4
open() => 5
close(3)
close(4)
maxfd = 5
RLIMIT_NOFILE would be set to 6 (stdin, stdout, stderr, 3, 4, 5) and the
sandbox would allow re-opening fd's 3 and 4.
One possible fix would be to run through the sequence of fd's before
entering the rlimit sandbox:
* test if the fd is closed
* if the fd is closed, dup2(STDIN_FILENO, fd)
Since the closed fd's are not part of the pollset, they will not be
polled and should be ignored.
Note we can't simply move maxfd to the lowest unused fd because
libstrophe maintains the fd number as internal, opaque state.
Empirically, the xmpp fd is always 3. Another option would be to abort
the process if the fd does not equal 3.
Prepare for sandboxing the xmppipe process by adding a function called
after all file descriptors are allocated.
The intent of the sandbox is to limit the xmppipe process to the role
of a component in a shell pipeline: reading from stdin, reading/writing
to the XMPP socket and writing to stdout. Any activity not involved with
using stdio should force the process to exit.
The sandbox function will vary based on the capabilities of the
platform. The default sandbox function does nothing.
Limitations of the sandbox:
Probably the biggest risk is in session establishment:
* the TLS handshake
* the XML parsing
The sandbox is enforced after the TLS connection is established, i.e.,
after the file descriptor for the XMPP session is allocated and so has no
effect on the TLS handshake or the initial XMPP handshake.
Possibly an initial sandbox could be setup for the connection phase
followed by a stricter sandbox for the stdio phase.