You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
asterisk-voicemail/debian/patches/sipwise_vm_add_pcre_support...

270 lines
8.1 KiB

From: Sipwise Development Team <support@sipwise.com>
Date: Mon, 21 Feb 2022 14:17:23 +0100
Subject: sipwise_vm_add_pcre_support
---
Makefile | 4 +-
apps/app_voicemail.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 178 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 9ee80e1..69eccd0 100644
--- a/Makefile
+++ b/Makefile
@@ -12,10 +12,11 @@ MODULES_DIR=$(INSTALL_PREFIX)$(ASTLIBDIR)
ASTETCDIR=$(INSTALL_PREFIX)/etc/asterisk
CC?=gcc
+PKG_CONFIG?=pkg-config
OPTIMIZE=-O2
DEBUG=-g
-LIBS+=
+LIBS+=$(shell $(PKG_CONFIG) --libs libpcre2-8)
CFLAGS+=-pipe -fPIC
CFLAGS+=-Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
CFLAGS+=-Wno-format-truncation
@@ -24,6 +25,7 @@ CFLAGS+=-Wno-sign-compare
CFLAGS+=-Wno-unused-parameter
CFLAGS+=-Wno-unused-variable
CFLAGS+=-D_REENTRANT -D_GNU_SOURCE -DODBC_STORAGE
+CFLAGS+=$(shell $(PKG_CONFIG) --cflags libpcre2-8) -DPCRE2_CODE_UNIT_WIDTH=8
all: _all
@echo " +-------- app_voicemail Build Complete --------+"
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 7667ae1..e9d5ec3 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -112,6 +112,9 @@
#include "asterisk/threadstorage.h"
#endif
+#include <ctype.h>
+#include <pcre2.h>
+
/*** DOCUMENTATION
<application name="VoiceMail" language="en_US">
<synopsis>
@@ -1081,6 +1084,8 @@ static int maxlogins = 3;
static int minpassword = MINPASSWORD;
static int passwordlocation;
static char aliasescontext[MAX_VM_CONTEXT_LEN];
+static char sw_normalize_user_match[256];
+static char sw_normalize_user_replace[256];
/*! Poll mailboxes for changes since there is something external to
* app_voicemail that may change them. */
@@ -1317,6 +1322,134 @@ static int inprocess_count(const char *context, const char *mailbox, int delta)
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit);
#endif
+/* Sipwise PCRE2 helper functions adapted from contrib of pcre:
+
+ Written by: Bert Driehuis <driehuis@playbeing.org>
+ Copyright (c) 2000 Bert Driehuis
+
+ Permission is granted to anyone to use this software for any purpose on any
+ computer system, and to redistribute it freely, subject to the following
+ restrictions:
+
+ 1. This software 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.
+
+ 2. The origin of this software must not be misrepresented, either by
+ explicit claim or by omission.
+
+ 3. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 4. If PCRE is embedded in any software that is released under the GNU
+ General Purpose Licence (GPL), then the terms of that licence shall
+ supersede any condition above with which it is incompatible.
+*/
+#define MAXCAPTURE 50
+
+static int findreplen(const char *rep, int nmat, const int *replen)
+{
+ int len = 0;
+ int val;
+ char *cp = (char *)rep;
+
+ while (*cp) {
+ if (*cp == '$' && isdigit(cp[1])) {
+ val = strtoul(&cp[1], &cp, 10);
+ if (val && val <= nmat)
+ len += replen[val -1];
+ else
+ fprintf(stderr, "repl %d out of range\n", val);
+ } else {
+ cp++;
+ len++;
+ }
+ }
+
+ return len;
+}
+
+static void doreplace(char *out, const char *rep,
+ int nmat, int *replen, const char **repstr)
+{
+ int val;
+ char *cp = (char *)rep;
+
+ while (*cp) {
+ if (*cp == '$' && isdigit(cp[1])) {
+ val = strtoul(&cp[1], &cp, 10);
+ if (val && val <= nmat) {
+ strncpy(out, repstr[val - 1], replen[val - 1]);
+ out += replen[val -1];
+ }
+ } else {
+ *out++ = *cp++;
+ }
+ }
+}
+
+static char *edit(const char *str, int len, const char *rep,
+ int nmat, const size_t *ovec)
+{
+ int i, slen, rlen;
+ const size_t *mvec = ovec;
+ char *res, *cp;
+ int replen[MAXCAPTURE];
+ const char *repstr[MAXCAPTURE];
+
+ nmat--;
+ ovec += 2;
+ for (i = 0; i < nmat; i++) {
+ replen[i] = ovec[i * 2 + 1] - ovec[i * 2];
+ repstr[i] = &str[ovec[i * 2]];
+ }
+ slen = len;
+ len -= mvec[1] - mvec[0];
+ len += rlen = findreplen(rep, nmat, replen);
+ cp = res = ast_malloc(len + 1);
+ if (mvec[0] > 0) {
+ strncpy(cp, str, mvec[0]);
+ cp += mvec[0];
+ }
+ doreplace(cp, rep, nmat, replen, repstr);
+ cp += rlen;
+ if (mvec[1] < slen)
+ strcpy(cp, &str[mvec[1]]);
+ res[len] = 0;
+
+ return res;
+}
+
+static char *pcre_subst(const pcre2_code *ppat,
+ const char *str, int len,
+ int offset, int options, const char *rep)
+{
+ int nmat;
+ pcre2_match_data *md;
+ size_t *ovec;
+
+ md = pcre2_match_data_create(MAXCAPTURE, NULL);
+ if (!md)
+ return NULL;
+
+ nmat = pcre2_match(ppat, (PCRE2_SPTR8)str, len, offset, options,
+ md, NULL);
+ if (nmat <= 0) {
+ pcre2_match_data_free(md);
+ return NULL;
+ }
+
+ ovec = pcre2_get_ovector_pointer(md);
+ pcre2_match_data_free(md);
+
+ if (!ovec)
+ return NULL;
+
+ return edit(str, len, rep, nmat, ovec);
+}
+
+/* end of pcre helper functions */
+
/*!
* \brief Strips control and non 7-bit clean characters from input string.
*
@@ -11317,6 +11450,10 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
int useadsi = 0, valid = 0, logretries = 0;
char password[AST_MAX_EXTENSION], *passptr = NULL;
struct ast_vm_user vmus, *vmu = NULL;
+ int errcode;
+ size_t erroffset;
+ pcre2_code *ppat = NULL;
+ char *normalized_mailbox;
/* If ADSI is supported, setup login screen */
adsi_begin(chan, &useadsi);
@@ -11327,6 +11464,17 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
return -1;
}
+ if (sw_normalize_user_match[0] != '\0' &&
+ sw_normalize_user_replace[0] != '\0') {
+ // TODO: could be done once on start
+ ppat = pcre2_compile((PCRE2_SPTR8)sw_normalize_user_match, PCRE2_ZERO_TERMINATED, 0, &errcode, &erroffset, NULL);
+ if (ppat == NULL) {
+ ast_log(LOG_WARNING, "Couldn't compile user match regex '%s': %d at offset %zd\n",
+ sw_normalize_user_match, errcode, erroffset);
+ return -1;
+ }
+ }
+
/* Authenticate them and get their mailbox/password */
while (!valid && (logretries < max_logins)) {
@@ -11356,6 +11504,18 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
if (useadsi)
adsi_password(chan);
+ if (ppat) {
+ ast_log(LOG_NOTICE, "Trying to rewrite user input '%s' using s/%s/%s/\n",
+ mailbox, sw_normalize_user_match, sw_normalize_user_replace);
+ normalized_mailbox = pcre_subst(ppat, mailbox, strlen(mailbox), 0, 0, sw_normalize_user_replace);
+ if(normalized_mailbox) {
+ ast_log(LOG_NOTICE, "Rewrote mailbox user input '%s' to %s\n",
+ mailbox, normalized_mailbox);
+ ast_copy_string(mailbox, normalized_mailbox, mailbox_size);
+ ast_free(normalized_mailbox);
+ }
+ }
+
if (!ast_strlen_zero(prefix)) {
char fullusername[80];
@@ -14349,6 +14509,8 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
char secretfn[PATH_MAX] = "";
long tps_queue_low;
long tps_queue_high;
+ const char *ast_sw_normalize_user_match = NULL;
+ const char *ast_sw_normalize_user_replace = NULL;
#ifdef IMAP_STORAGE
ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
@@ -14421,6 +14583,19 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
ast_set2_flag((&globalflags), ast_true(val), VM_ODBC_AUDIO_ON_DISK);
#endif
+
+ /* sipwise sw_normalize_user_match/replace */
+ if ((ast_sw_normalize_user_match = ast_variable_retrieve(cfg, "general", "sw_normalize_user_match"))) {
+ ast_copy_string(sw_normalize_user_match, ast_sw_normalize_user_match, sizeof(sw_normalize_user_match));
+ } else {
+ sw_normalize_user_match[0] = '\0';
+ }
+ if ((ast_sw_normalize_user_replace = ast_variable_retrieve(cfg, "general", "sw_normalize_user_replace"))) {
+ ast_copy_string(sw_normalize_user_replace, ast_sw_normalize_user_replace, sizeof(sw_normalize_user_replace));
+ } else {
+ sw_normalize_user_replace[0] = '\0';
+ }
+
/* Mail command */
strcpy(mailcmd, SENDMAIL);
if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))