[ADD] No-fly, forms

This commit is contained in:
LDA 2024-07-14 11:42:30 +02:00
commit df394172ec
11 changed files with 338 additions and 52 deletions

View file

@ -66,6 +66,8 @@ NewSession(XMPPCommandManager *m, char *node)
int period = (UtilTsMillis() / (10 SECONDS));
char *rand = StrRandom(16);
char *pstr = StrInt(period);
Free(session_id);
session_id = StrConcat(5, node, "_", pstr, "_", rand);
Free(rand);
@ -85,17 +87,24 @@ XMPPRegisterSession(XMPPCommandManager *m, char *p_jid, char *s_jid, char *node)
{
return NULL;
}
s_jid = ParseeTrimJID(s_jid);
p_jid = ParseeTrimJID(p_jid);
session = Malloc(sizeof(*session));
session->node = StrDuplicate(node);
session->issuer = StrDuplicate(s_jid);
session->receiver = StrDuplicate(p_jid);
session->creation = UtilTsMillis();
session_ident = NewSession(m, node);
session->identifier = session_ident;
HashMapSet(m->sessions, session_ident, session);
Free(s_jid);
Free(p_jid);
return session_ident;
}
@ -173,6 +182,30 @@ XMPPShoveCommandList(XMPPCommandManager *m, char *jid, XMLElement *p)
}
pthread_mutex_unlock(&m->lock);
}
static bool
XMPPVerifySession(XMPPCommandManager *mgr, char *s_id, char *from, char *to)
{
XMPPSession *session = mgr ? HashMapGet(mgr->sessions, s_id) : NULL;
bool ret = false;
if (!session)
{
return false;
}
from = ParseeTrimJID(from);
to = ParseeTrimJID(to);
ret = StrEquals(from, session->issuer) &&
StrEquals(to, session->receiver);
/* TODO: Expirations */
Free(from);
Free(to);
return ret;
}
bool
XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
{
@ -201,6 +234,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
{
char *action = HashMapGet(command->attrs, "action");
char *node = HashMapGet(command->attrs, "node");
char *session_given = HashMapGet(command->attrs, "sessionid");
if (!action || StrEquals(action, "execute"))
{
@ -210,19 +244,44 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
if (!cmd)
{
Log(LOG_WARNING,
"User %s asked to execute '%s', but it doesn't exist.",
from, node
);
/* TODO: Set an error note */
goto end;
}
if (XMPPCommandRequiresForm(cmd))
if (XMPPCommandRequiresForm(cmd) && !session_given)
{
Log(LOG_WARNING,
"User %s asked to execute '%s', but it requires a form, "
"which is currently UNIMPLEMENTED", from, node
);
XMLElement *actions = XMLCreateTag("actions");
XMLElement *completed = XMLCreateTag("complete");
XMLElement *x = XMLCreateTag("x");
XMLAddChild(actions, completed);
session_id = XMPPRegisterSession(m, to, from, node);
/* No forms, we good. */
iq = XMLCreateTag("iq");
XMLAddAttr(iq, "type", "result");
XMLAddAttr(iq, "from", to);
XMLAddAttr(iq, "to", from);
XMLAddAttr(iq, "id", id);
command_xml = XMLCreateTag("command");
XMLAddAttr(command_xml, "xmlns", CMD_NS);
XMLAddAttr(command_xml, "node", node);
XMLAddAttr(command_xml, "status", "executing");
XMLAddAttr(command_xml, "sessionid", session_id);
XMLAddChild(command_xml, actions);
XMLAddChild(iq, command_xml);
XMLAddAttr(x, "xmlns", "jabber:x:data");
XMLAddAttr(x, "type", "form");
XMPPShoveOptions(cmd, x);
XMLAddChild(command_xml, x);
pthread_mutex_lock(&jabber->write_lock);
XMLEncode(jabber->stream, iq);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq);
goto end;
}
@ -254,6 +313,48 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
good = true;
goto end;
}
else if (StrEquals(action, "complete") &&
XMPPVerifySession(m, session_given, from, to))
{
XMLElement *x_form = XMLookForTKV(command,
"x", "xmlns", "jabber:x:data"
);
XMLElement *command_xml, *iq;
if (!x_form ||
!StrEquals(HashMapGet(x_form->attrs, "type"), "submit"))
{
goto end;
}
cmd = HashMapGet(m->commands, node);
if (!XMPPVerifyForm(cmd, x_form))
{
goto end;
}
iq = XMLCreateTag("iq");
XMLAddAttr(iq, "type", "result");
XMLAddAttr(iq, "from", to);
XMLAddAttr(iq, "to", from);
XMLAddAttr(iq, "id", id);
command_xml = XMLCreateTag("command");
XMLAddAttr(command_xml, "xmlns", CMD_NS);
XMLAddAttr(command_xml, "node", node);
XMLAddAttr(command_xml, "status", "completed");
XMLAddAttr(command_xml, "sessionid", session_given);
XMPPExecuteCommand(m, cmd, from, command_xml, x_form);
XMLAddChild(iq, command_xml);
pthread_mutex_lock(&jabber->write_lock);
XMLEncode(jabber->stream, iq);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq);
InvalidateSession(m, session_given);
good = true;
goto end;
}
}
#undef CMD_NS