changeset 51:36a30349b490

sip-in: parse INVITE From header
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 07 Sep 2022 17:53:10 -0800
parents daf1c26d7ae2
children ffb563a17f23
files libsip/Makefile libsip/grok_from.c libsip/grok_from.h sip-in/invite.c
diffstat 4 files changed, 124 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libsip/Makefile	Tue Sep 06 23:50:16 2022 -0800
+++ b/libsip/Makefile	Wed Sep 07 17:53:10 2022 -0800
@@ -1,7 +1,7 @@
 CC=	gcc
 CFLAGS=	-O2
-OBJS=	get_header.o out_msg.o primary_parse.o req_supp.o uas_basic.o \
-	uri_utils.o
+OBJS=	get_header.o grok_from.o out_msg.o primary_parse.o req_supp.o \
+	uas_basic.o uri_utils.o
 LIB=	libsip.a
 
 all:	${LIB}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libsip/grok_from.c	Wed Sep 07 17:53:10 2022 -0800
@@ -0,0 +1,100 @@
+/*
+ * Here we implement further parsing of the From header,
+ * beyond the preliminary step of uas_get_basic_headers().
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include "grok_from.h"
+
+grok_from_header(from_hdr, gfr)
+	char *from_hdr;
+	struct grok_from *gfr;
+{
+	char *cp = from_hdr, *bp;
+	int bracketed;
+
+	if (*cp == '<' || !strncasecmp(cp, "sip:", 4)) {
+		gfr->cnam = 0;
+		gfr->cnam_len = 0;
+		gfr->cnam_quoted = 0;
+	} else {
+		if (*cp == '"') {
+			cp++;
+			gfr->cnam = cp;
+			for (;;) {
+				if (!*cp)
+					return(-1);
+				if (*cp == '"')
+					break;
+				if (*cp++ == '\\') {
+					if (!*cp)
+						return(-1);
+					cp++;
+				}
+			}
+			gfr->cnam_len = cp - gfr->cnam;
+			gfr->cnam_quoted = 1;
+			cp++;
+			while (isspace(*cp))
+				cp++;
+			if (*cp != '<')
+				return(-1);
+		} else {
+			gfr->cnam = cp;
+			for (;;) {
+				if (!*cp)
+					return(-1);
+				if (*cp == '<')
+					break;
+				cp++;
+			}
+			for (bp = cp; bp > gfr->cnam && isspace(bp[-1]); bp--)
+				;
+			gfr->cnam_len = bp - gfr->cnam;
+			gfr->cnam_quoted = 0;
+		}
+	}
+	if (*cp == '<') {
+		cp++;
+		bracketed = 1;
+	} else
+		bracketed = 0;
+	gfr->uri = cp;
+	if (strncasecmp(cp, "sip:", 4))
+		return(-1);
+	cp += 4;
+	gfr->user = cp;
+	for (;;) {
+		if (!*cp || *cp == '<' || *cp == '>')
+			return(-1);
+		if (*cp == '@')
+			break;
+		cp++;
+	}
+	if (cp == gfr->user)
+		return(-1);
+	gfr->user_len = cp - gfr->user;
+	cp++;
+	for (;;) {
+		switch (*cp) {
+		case '\0':
+		case ';':
+			if (bracketed)
+				return(-1);
+			else
+				break;
+		case '>':
+			if (bracketed)
+				break;
+			else
+				return(-1);
+		case '<':
+			return(-1);
+		}
+		cp++;
+	}
+	gfr->uri_len = cp - gfr->uri;
+	return(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libsip/grok_from.h	Wed Sep 07 17:53:10 2022 -0800
@@ -0,0 +1,14 @@
+/*
+ * Here we define the structure used to capture the result
+ * of From header field parsing.
+ */
+
+struct grok_from {
+	char		*uri;
+	unsigned	uri_len;
+	char		*user;
+	unsigned	user_len;
+	char		*cnam;
+	unsigned	cnam_len;
+	int		cnam_quoted;
+};
--- a/sip-in/invite.c	Tue Sep 06 23:50:16 2022 -0800
+++ b/sip-in/invite.c	Wed Sep 07 17:53:10 2022 -0800
@@ -13,6 +13,7 @@
 #include <unistd.h>
 #include "../libsip/parse.h"
 #include "../libsip/uas_basic.h"
+#include "../libsip/grok_from.h"
 #include "../libsip/req_supp.h"
 #include "../libsip/out_msg.h"
 
@@ -28,6 +29,7 @@
 {
 	char uri_user[13], *called_nanp;
 	struct sip_msg_out resp;
+	struct grok_from gfrom;
 	struct supported_ext supp_ext;
 	char *hval, *unsup_ext;
 	int ext_100rel_req, ext_100rel_sup, use_100rel;
@@ -75,6 +77,12 @@
 			"404 Called number does not belong here");
 		goto error_resp;
 	}
+	/* parse and validate From header */
+	rc = grok_from_header(ess->from, &gfrom);
+	if (rc < 0) {
+		start_response_out_msg(&resp, "400 Malformed From header");
+		goto error_resp;
+	}
 	/* check 100rel and catch any unsupported requirements */
 	supp_ext.name = "100rel";
 	supp_ext.req_flag = &ext_100rel_req;