This is an automated email from the ASF dual-hosted git repository.
solomax pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openmeetings.git
The following commit(s) were added to refs/heads/master by this push:
new f9a95c9ef [OPENMEETINGS-2832] SIP extension number is sanitized
f9a95c9ef is described below
commit f9a95c9efd1f5cecb99f26b33da1655a124e8793
Author: Maxim Solodovnik <[email protected]>
AuthorDate: Mon Sep 7 20:51:50 2026 +0700
[OPENMEETINGS-2832] SIP extension number is sanitized
---
openmeetings-core/pom.xml | 4 +
.../apache/openmeetings/core/sip/SipManager.java | 10 +-
.../openmeetings/core/sip/TestSipMocked.java | 101 +++++++++++++++++++++
3 files changed, 113 insertions(+), 2 deletions(-)
diff --git a/openmeetings-core/pom.xml b/openmeetings-core/pom.xml
index 2849dd33e..69c4b93eb 100644
--- a/openmeetings-core/pom.xml
+++ b/openmeetings-core/pom.xml
@@ -78,5 +78,9 @@
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.openmeetings</groupId>
+ <artifactId>openmeetings-tests</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java
index 7c3881916..b3aef555b 100644
---
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java
+++
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/sip/SipManager.java
@@ -134,7 +134,8 @@ public class SipManager implements ISipManager {
}
}
- private ManagerResponse exec(ManagerAction action) {
+ // package private for tests
+ ManagerResponse exec(ManagerAction action) {
if (factory == null) {
log.warn("There is no Asterisk configured");
return null;
@@ -236,11 +237,16 @@ public class SipManager implements ISipManager {
log.warn("Failed to get SIP number for room: {}", r);
return;
}
+ String ext =
Optional.ofNullable(number).orElse("").lines().findFirst().orElse(null);
+ if (Strings.isEmpty(ext)) {
+ log.warn("Got empty extention number out of '{}'",
number);
+ return;
+ }
OriginateAction oa = new OriginateAction();
oa.setChannel(String.format("Local/%s@rooms-originate",
sipNumber));
oa.setContext("rooms-out");
- oa.setExten(number);
+ oa.setExten(ext);
oa.setPriority(1);
oa.setTimeout(managerTimeout);
diff --git
a/openmeetings-core/src/test/java/org/apache/openmeetings/core/sip/TestSipMocked.java
b/openmeetings-core/src/test/java/org/apache/openmeetings/core/sip/TestSipMocked.java
new file mode 100644
index 000000000..4c05ea50d
--- /dev/null
+++
b/openmeetings-core/src/test/java/org/apache/openmeetings/core/sip/TestSipMocked.java
@@ -0,0 +1,101 @@
+/*
+
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") + you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.core.sip;
+
+import static org.apache.openmeetings.test.Utils.getTestCoordinates;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.openmeetings.db.entity.room.Room;
+import org.asteriskjava.manager.ManagerConnection;
+import org.asteriskjava.manager.ManagerConnectionFactory;
+import org.asteriskjava.manager.ManagerConnectionState;
+import org.asteriskjava.manager.action.ManagerAction;
+import org.asteriskjava.manager.internal.ManagerWriterImpl;
+import org.asteriskjava.util.SocketConnectionFacade;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestSipMocked {
+ private static final Logger log =
LoggerFactory.getLogger(TestSipMocked.class);
+ @Mock
+ private ManagerConnection con;
+ @Mock
+ private ManagerConnectionFactory factory;
+ @Mock
+ private SocketConnectionFacade sock;
+ @InjectMocks
+ private ManagerWriterImpl writerImpl;
+
+ @BeforeEach
+ void setup(TestInfo testInfo) {
+ log.info("Test started: {} ---", getTestCoordinates(testInfo));
+ MockitoAnnotations.openMocks(this);
+ Mockito.reset();
+ doReturn(ManagerConnectionState.CONNECTED).when(con).getState();
+ }
+
+ @AfterEach
+ void tearDown(TestInfo testInfo) {
+ log.info(" --- test finished: {}",
getTestCoordinates(testInfo));
+ }
+
+ @Test
+ void testCallExternalNumber() throws Exception {
+ Room r = new Room();
+ r.setConfno("test-conf-no");
+
+ SipManager sip = spy(new SipManager());
+
+ ArgumentCaptor<ManagerAction> actionCaptor =
ArgumentCaptor.forClass(ManagerAction.class);
+ when(sip.exec(actionCaptor.capture())).thenReturn(null); // we
need argument
+
+ sip.callExternalNumber("12345\r\nAction: Command\r\nActionID:
injected\r\nCommand: sip show peers", r);
+ List<String> actionStrings = new ArrayList<>();
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws
Throwable {
+ actionStrings.add(invocation.getArgument(0));
+ return null;
+ }}).when(sock).write(anyString());
+ writerImpl.sendAction(actionCaptor.getValue(), "some-id");
+ assertEquals(1, actionStrings.size(), "Exctly one message
should be written");
+ assertFalse(actionStrings.get(0).contains("injected"),
"External number should be sanitized");
+ }
+}