From 868f0e4d9cb7690bcccef71dca234103214cfb4d Mon Sep 17 00:00:00 2001 From: LDA Date: Sun, 16 Jun 2024 11:08:18 +0200 Subject: [PATCH] [ADD/WIP] Begin XMPPwerk The fuck is a stanza? Presence? Why did Prosody not tell me I'm an idiot when I clearly made a MALFORMED XML document? This and much more, in the next commit! --- .gitignore | 2 + src/Main.c | 14 ++++++ src/XML/Parser.c | 72 ++++++++++++++++++++++++++++++- src/XML/SAX.c | 26 +++++++++-- src/XMPP/Component.c | 100 ++++++++++++++++++++++++++++++++++++++++--- src/include/XML.h | 2 +- src/include/XMPP.h | 2 +- 7 files changed, 207 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 56d1883..a8b1c25 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ build/* build parsee* parsee +*.swp +.* diff --git a/src/Main.c b/src/Main.c index b7367db..839fa38 100644 --- a/src/Main.c +++ b/src/Main.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -15,6 +16,19 @@ Main(void) ParseeData *data; const ParseeConfig *parsee_conf; Stream *yaml; + { + char *as = "TODO"; + char *shared = "TODO"; + Stream *jabber = XMPPInitialiseCompStream(as, 0); + XMPPAuthenticateCompStream(jabber, as, shared); + while (!StreamEof(jabber)) + { + StreamPutc(StreamStderr(), StreamGetc(jabber)); + StreamFlush(StreamStderr()); + } + XMPPEndCompStream(jabber); + return 0; + } Log(LOG_INFO, "%s - v%s", NAME, VERSION); ParseeConfigLoad("parsee.json"); diff --git a/src/XML/Parser.c b/src/XML/Parser.c index 9e7e79e..988c2bd 100644 --- a/src/XML/Parser.c +++ b/src/XML/Parser.c @@ -1,12 +1,82 @@ #include +#include + /* TODO: The rest of all that. */ XMLElement * XMLDecode(Stream *stream, bool autofree) { /* TODO: Use the existing SAX parser to decode everything */ - return NULL; +#define push(x) ArrayAdd(stack, x) +#define pop(x) ArrayDelete(stack, ArraySize(stack) - 1) +#define peek(x) ArrayGet(stack, ArraySize(stack) - 1) + XMLexer *lexer; + XMLEvent *event; + XMLElement *ret = NULL; + XMLElement *top; + char *key, *val; + + Array *stack; + + if (!stream) + { + return NULL; + } + lexer = XMLCreateLexer(stream, autofree); + stack = ArrayCreate(); + while ((event = XMLCrank(lexer)) && (!ret || ArraySize(stack))) + { + switch (event->type) + { + case XML_LEXER_STARTELEM: + /* Create a new element that will populated. */ + top = XMLCreateTag(event->element); + Log(LOG_INFO, "<%s>", top->name); + XMLAddChild(peek(), top); + while (HashMapIterate(event->attrs, &key, (void **) &val)) + { + XMLAddAttr(top, key, val); + } + if (!ret) + { + /* If we didn't have any element before, this one is + * going to be our top of the stack */ + ret = top; + } + push(top); + break; + case XML_LEXER_ELEM: + /* Create a new element that will populated. */ + top = XMLCreateTag(event->element); + XMLAddChild(peek(), top); + Log(LOG_INFO, "<%s />", top->name); + while (HashMapIterate(event->attrs, &key, (void **) &val)) + { + XMLAddAttr(top, key, val); + } + if (!ret) + { + /* If we didn't have any element before, this one is + * going to be our top of the stack */ + ret = top; + } + push(top); + /* Fallthrough */ + case XML_LEXER_ENDELEM: + /* Pop out an element out of the DOM. */ + Log(LOG_INFO, ""); + pop(); + break; + default: break; + } + XMLFreeEvent(event); + event = NULL; + } + XMLFreeEvent(event); + ArrayFree(stack); + XMLFreeLexer(lexer); + return ret; } void diff --git a/src/XML/SAX.c b/src/XML/SAX.c index 82c101c..56d6b94 100644 --- a/src/XML/SAX.c +++ b/src/XML/SAX.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -24,7 +23,8 @@ struct XMLexer { XML_STATE_ATTR, XML_STATE_ATTRHEAD_PROP, - XML_STATE_ATTRTAIL + XML_STATE_ATTRTAIL, + XML_STATE_PI } state; struct { @@ -161,6 +161,17 @@ XMLCrank(XMLexer *lexer) lexer->state = XML_STATE_ATTRTAIL; break; } + else if (XMLookahead(lexer, "data.str) + { + XMLFreeEvent(event); + event = XMLCreateData(lexer); + } + + lexer->state = XML_STATE_PI; + break; + } else if (XMLookahead(lexer, "<", true)) { if (lexer->data.str) @@ -189,6 +200,14 @@ XMLCrank(XMLexer *lexer) return NULL; } break; + case XML_STATE_PI: + if (XMLookahead(lexer, "?>", true)) + { + lexer->state = XML_STATE_NONE; + break; + } + XMLGetc(lexer); + break; case XML_STATE_ATTR: attrname = XMLParseName(lexer); if (!attrname) @@ -250,7 +269,6 @@ XMLFreeEvent(XMLEvent *event) void *val; while (HashMapIterate(event->attrs, &key, &val)) { - Log(LOG_INFO, "Trying to free %s", val); Free(val); } HashMapFree(event->attrs); @@ -640,6 +658,8 @@ XMLParseAttQuote(XMLexer *lexer) point = XMLInitialiseBuffer(lexer); + /* TODO: My Prosody is actually trolling me. + * GIVE ME A FUCKING STREAM ID YOU RETARD. */ while ((c = XMLGetc(lexer))) { if (!IsNormalQ(c)) diff --git a/src/XMPP/Component.c b/src/XMPP/Component.c index eda6270..af9a0ee 100644 --- a/src/XMPP/Component.c +++ b/src/XMPP/Component.c @@ -1,5 +1,9 @@ #include +#include +#include +#include + #include #include #include @@ -28,7 +32,7 @@ XMPPInitialiseCompStream(char *host, int port) char serv[8]; Stream *stream; - snprintf(serv, sizeof(serv), "%hu", port); + snprintf(serv, sizeof(serv), "%hu", port ? port : DEFAULT_PROSODY_PORT); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -51,6 +55,7 @@ XMPPInitialiseCompStream(char *host, int port) sd = -1; continue; } + Log(LOG_INFO, "Connected to port %s", serv); break; } @@ -62,6 +67,7 @@ XMPPInitialiseCompStream(char *host, int port) freeaddrinfo(res0); stream = StreamFd(sd); + Log(LOG_INFO, "Got %d via %p", sd, stream); if (!stream) { close(sd); @@ -71,13 +77,97 @@ XMPPInitialiseCompStream(char *host, int port) return stream; } +#include +static char * +ComputeHandshake(char *shared, char *stream) +{ + char *source; + unsigned char *raw_sha; + char *sha; + + source = StrConcat(2, stream, shared); + raw_sha = Sha1(source); + sha = ShaToHex(raw_sha); + + Free(raw_sha); + Free(source); + + return sha; +} bool -XMPPAuthenticateCompStream(Stream *stream, char *shared) +XMPPAuthenticateCompStream(Stream *stream, char *as, char *shared) { /* TODO */ - (void) stream; - (void) shared; - return false; + XMLexer *sax; + XMLEvent *ev; + char *stream_id, *handshake; + bool ret = false; + if (!stream || !as || !shared) + { + return false; + } + StreamPrintf(stream, + "", as + ); + StreamFlush(stream); + sax = XMLCreateLexer(stream, false); + while ((ev = XMLCrank(sax))) + { + if (ev->type == XML_RELAX) + { + XMLFreeEvent(ev); + continue; + } + break; + } + if (ev->type != XML_LEXER_STARTELEM || + !StrEquals(ev->element, "stream:stream")) + { + Log(LOG_ERR, "Excepted strea:stream element."); + XMLFreeEvent(ev); + goto end; + } + + stream_id = StrDuplicate(HashMapGet(ev->attrs, "id")); + handshake = ComputeHandshake(shared, stream_id); + /* y no stream id */ + Log(LOG_NOTICE, "- sID='%s'", stream_id); + StreamPrintf(stream, "%s", handshake); + StreamFlush(stream); + XMLFreeEvent(ev); + + while ((ev = XMLCrank(sax))) + { + if (ev->type == XML_RELAX) + { + XMLFreeEvent(ev); + continue; + } + break; + } + if (ev->type != XML_LEXER_ELEM || + !StrEquals(ev->element, "handshake")) + { + Log(LOG_ERR, "Excepted empty handshake reply, got nonsense."); + Free(stream_id); + Free(handshake); + XMLFreeEvent(ev); + goto end; + } + + ret = true; + /* We can uhh, send stanzas, and receive them! */ + Log(LOG_INFO, "Communications to '%s' established.", as); + + XMLFreeEvent(ev); + Free(stream_id); + Free(handshake); +end: + XMLFreeLexer(sax); + return ret; } void diff --git a/src/include/XML.h b/src/include/XML.h index 1218768..72c4555 100644 --- a/src/include/XML.h +++ b/src/include/XML.h @@ -10,8 +10,8 @@ typedef struct XMLEvent { enum { XML_LEXER_UNKNOWN = 0, XML_LEXER_STARTELEM, - XML_LEXER_ELEM, /* Empty attr */ XML_LEXER_DATA, + XML_LEXER_ELEM, /* Empty attr */ XML_LEXER_ENDELEM, XML_RELAX diff --git a/src/include/XMPP.h b/src/include/XMPP.h index c5988bb..665be8a 100644 --- a/src/include/XMPP.h +++ b/src/include/XMPP.h @@ -10,7 +10,7 @@ extern Stream * XMPPInitialiseCompStream(char *host, int port); /* Authenticates a component stream with a given shared secret, * with a stream ID from the server. This should be called right * after XMPPInitialiseCompStream. */ -extern bool XMPPAuthenticateCompStream(Stream *stream, char *shared); +extern bool XMPPAuthenticateCompStream(Stream *stream, char *as, char *shared); /* TODO: XMPP stuff, I don't fucking know, I'm not a Jabbernerd. */