Skip to content

Commit

Permalink
updated testing script to use alert class
Browse files Browse the repository at this point in the history
  • Loading branch information
sqall01 committed Dec 24, 2018
1 parent c90a8c9 commit 105f431
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 161 deletions.
2 changes: 1 addition & 1 deletion alertClientPushNotification/instanceInfo.json
@@ -1 +1 @@
{"files": {"config/example_template.msg": "038ff581a15ea7c7c8dc595cccc126bacff10342a2857ff46a012bb0f5efa4c6", "init.d_example/alertRalertClientPushNotification.service": "048607ff5620d2c4d7390a6260e31827d0dff2d90e7e842a7296bbd1dead4ca5", "config/config.xml.template": "0b66ab1b8c955481e4b8d36dab5f46e7e0e528fed75ad3a53182b380ab10f515", "alertRupdate.py": "9fb518ca9ecc74ea0293a05e205f7ff0ff21273607d3cfcd2a2123aaba9a5090", "lib/update.py": "f6ee389e7ad53240c6b9300295da3acfbc242fdffe91b194831c0d48df383680", "init.d_example/alertRalertClientPushNotification.sh": "edb962bf1e71dd484ec194145dc9cf0bac9930232ea57632440512a1cf2068a2", "lib/__init__.py": "c147c6410d93492f369f0f70b479b4c31ebbc91ea9d24e43f1fb83c09d039fad", "CHANGELOG.md": "1f3e12bc510aeb5df0db834f7f275e082785f187266b4bdf89df055d9e166070", "testPushConfiguration.py": "f7a50e94789fb6bcef0bd1999bb81224734311c75d3d68d7b201b5dbad5ab52d", "lib/globalData.py": "53f841e8805f7ce0852de4e8357b7aad169ad766295a6c5adfe61d292c6ab3dc", "alertRclient.py": "8947fe25645663e2001e4d40b88b2e643a108fe7c5b5790dd6529f0ec7bc34a0", "README.md": "2f49700938a7615c3e81aa5ec12952bd18f3acdfe7f1ad36d7750a065707757e", "lib/alert.py": "c9dd3791eeb6ac62c6e153030f431617edb7ebe28a72f2af959df7e098c6da59", "lib/smtp.py": "0f322776d7626d85b4041c66534d8742d1294b67cbdbba753f6092a749aaf51c", "lib/client.py": "7e03081559339bf7369622873c6c6ed31c7d3c5d5edd31c7dfd710b4089bda86", "config/push.alertr.de.crt": "99847be5f6a28107af1ef6a590dbdcc5b9cf792658bef2a9f2faa5d806642c7a", "lib/localObjects.py": "c6749540445e4307674b5acb50601ffd14707015e8dbc36a67ce59f9969a834d"}, "version": 0.501, "rev": 2, "dependencies": {"pip": [{"import": "lightweightpush", "version": "0.0.5", "packet": "lightweightpush"}]}}
{"files": {"config/example_template.msg": "038ff581a15ea7c7c8dc595cccc126bacff10342a2857ff46a012bb0f5efa4c6", "init.d_example/alertRalertClientPushNotification.service": "048607ff5620d2c4d7390a6260e31827d0dff2d90e7e842a7296bbd1dead4ca5", "config/config.xml.template": "0b66ab1b8c955481e4b8d36dab5f46e7e0e528fed75ad3a53182b380ab10f515", "alertRupdate.py": "9fb518ca9ecc74ea0293a05e205f7ff0ff21273607d3cfcd2a2123aaba9a5090", "lib/update.py": "f6ee389e7ad53240c6b9300295da3acfbc242fdffe91b194831c0d48df383680", "init.d_example/alertRalertClientPushNotification.sh": "edb962bf1e71dd484ec194145dc9cf0bac9930232ea57632440512a1cf2068a2", "lib/__init__.py": "74a51cc4060f13a0adbc9fb353134915ecfed2924daf5786c690c131610e85c9", "CHANGELOG.md": "1f3e12bc510aeb5df0db834f7f275e082785f187266b4bdf89df055d9e166070", "testPushConfiguration.py": "f428c9bc876ca57c49560a7bc13c61645535eed0913f61432d7e853376694af8", "lib/globalData.py": "53f841e8805f7ce0852de4e8357b7aad169ad766295a6c5adfe61d292c6ab3dc", "alertRclient.py": "8947fe25645663e2001e4d40b88b2e643a108fe7c5b5790dd6529f0ec7bc34a0", "README.md": "2f49700938a7615c3e81aa5ec12952bd18f3acdfe7f1ad36d7750a065707757e", "lib/alert.py": "dc89a3c48d758fcd378d80e37635fe703df351bfe53d01b5b8a469e9210b8f79", "lib/smtp.py": "0f322776d7626d85b4041c66534d8742d1294b67cbdbba753f6092a749aaf51c", "lib/client.py": "7e03081559339bf7369622873c6c6ed31c7d3c5d5edd31c7dfd710b4089bda86", "config/push.alertr.de.crt": "99847be5f6a28107af1ef6a590dbdcc5b9cf792658bef2a9f2faa5d806642c7a", "lib/localObjects.py": "c6749540445e4307674b5acb50601ffd14707015e8dbc36a67ce59f9969a834d"}, "version": 0.501, "rev": 2, "dependencies": {"pip": [{"import": "lightweightpush", "version": "0.0.5", "packet": "lightweightpush"}]}}
3 changes: 2 additions & 1 deletion alertClientPushNotification/lib/__init__.py
Expand Up @@ -11,4 +11,5 @@
from smtp import SMTPAlert
from alert import PushAlert, ErrorCodes
from update import Updater
from globalData import GlobalData
from globalData import GlobalData
from localObjects import SensorAlert
5 changes: 5 additions & 0 deletions alertClientPushNotification/lib/alert.py
Expand Up @@ -54,6 +54,7 @@ def __init__(self, globalData):

self.globalData = globalData
self.pushRetryTimeout = self.globalData.pushRetryTimeout
self.pushRetries = self.globalData.pushRetries

# These are the message settings.
self._channel = None
Expand Down Expand Up @@ -136,6 +137,7 @@ def _sendMessage(self, subject, msg, sensorAlert):

# Send message to push server.
ctr = 0
errorCode = ErrorCodes.NO_ERROR
while True:

ctr += 1
Expand Down Expand Up @@ -194,6 +196,9 @@ def _sendMessage(self, subject, msg, sensorAlert):

time.sleep(self.pushRetryTimeout)

# Return last error code (used by the testPushConfiguration.py script).
return errorCode


# this function is called once when the alert client has connected itself
# to the server (should be use to initialize everything that is needed
Expand Down
198 changes: 39 additions & 159 deletions alertClientPushNotification/testPushConfiguration.py
Expand Up @@ -8,60 +8,14 @@
# Licensed under the GNU Affero General Public License, version 3.

import time
import socket
import ssl
import threading
import logging
import os
import base64
import xml.etree.cElementTree
import random
import json
import hashlib
import sys
import re
from Crypto.Cipher import AES
from lib import GlobalData
from lib import ErrorCodes
BUFSIZE = 4096


# simple class of an ssl tcp client
class Client:

def __init__(self, host, port, serverCAFile):
self.host = host
self.port = port
self.serverCAFile = serverCAFile
self.socket = None
self.sslSocket = None


def connect(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

self.sslSocket = ssl.wrap_socket(self.socket,
ca_certs=self.serverCAFile, cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1)

self.sslSocket.connect((self.host, self.port))


def send(self, data):
count = self.sslSocket.send(data)


def recv(self, buffsize, timeout=3.0):
data = None
self.sslSocket.settimeout(timeout)
data = self.sslSocket.recv(buffsize)
self.sslSocket.settimeout(None)
return data


def close(self):
# closing SSLSocket will also close the underlying socket
self.sslSocket.close()
from lib import PushAlert
from lib import SensorAlert
from lightweightpush import ErrorCodes


# Function creates a path location for the given user input.
Expand All @@ -76,46 +30,6 @@ def makePath(inputLocation):
return os.path.dirname(os.path.abspath(__file__)) + "/" + inputLocation


# Create the channel name linked to the username.
# NOTE: This function is not collision free but will improve collision
# resistance if multiple parties choose the same channel.
def generatePrefixedChannel(username, channel):
# Create a encryption key from the secret.
sha256 = hashlib.sha256()
sha256.update(username)
prefix = sha256.hexdigest()[0:8]
return prefix.lower() + "_" + channel


def checkChannel(channel):
return bool(re.match(r'^[a-zA-Z0-9-_.~%]+$', channel))


# Truncates the message and subject to fit in a notification message.
def truncToSize(subject, message, sbjMsgSize=1400):
len_json_sbj = len(json.dumps(subject))
len_sbj = len(subject)
len_json_msg = len(json.dumps(message))
len_msg = len(message)

# Consider json encoding (characters like \n need two characters).
if (len_json_sbj + len_json_msg) > sbjMsgSize:
number_to_remove = (len_json_sbj + len_json_msg + 7) - sbjMsgSize
if len_msg > number_to_remove:
message = message[0:(len_msg-number_to_remove)]
message += "*TRUNC*"
elif len_sbj > number_to_remove:
subject = subject[0:(len_sbj-number_to_remove)]
subject += "*TRUNC*"
else:
message = "*TRUNC*"
number_to_remove = number_to_remove - len_msg + 7
subject = subject[0:(len_sbj-number_to_remove)]
subject += "*TRUNC*"

return subject, message


if __name__ == '__main__':

fileName = os.path.basename(__file__)
Expand Down Expand Up @@ -178,11 +92,6 @@ def truncToSize(subject, message, sbjMsgSize=1400):
alert["templateFile"] = makePath(
str(item.find("push").attrib["templateFile"]))

# Check if channel is allowed.
if not checkChannel(alert["channel"]):
raise ValueError("Channel '%s' contains illegal characters."
% alert["channel"])

# check if the template file exists
if not os.path.isfile(alert["templateFile"]):
raise ValueError("Message template file '%s' does not exist."
Expand All @@ -208,108 +117,79 @@ def truncToSize(subject, message, sbjMsgSize=1400):
logging.info("[%s]: Sending message for alert id %d (%s)."
% (fileName, alert["id"], alert["description"]))

client = Client(globalData.pushServerAddress,
globalData.pushServerPort,
globalData.pushServerCert)

client.connect()

globalData.pushRetryTimeout = 5
globalData.pushRetries = 1

subject = "Test message for alert with id %d" % alert["id"]
message = "This is a test message for the alert:\n\n" \
+ "Id: %d\nDescription: %s\n\nCheers,\nalertR" \
% (alert["id"], alert["description"])

subject, message = truncToSize(subject, message,
globalData.pushSbjMsgSize)
utc_timestamp = int(time.time())
payload = json.dumps( {
"sbj": subject,
"msg": message,
"tt": utc_timestamp,
"ts": utc_timestamp,
"is_sa": True,
"st": 1
} )

enc_secret = alert["encSecret"]

# Create a encryption key from the secret.
sha256 = hashlib.sha256()
sha256.update(enc_secret)
key = sha256.digest()

# Add random bytes in the beginning of
# the message to increase randomness.
iv = os.urandom(16)
internal_iv = os.urandom(4)
padded_payload = internal_iv + payload

padding = len(padded_payload) % 16
if padding != 0:
for i in range(16 - padding):
# Use whitespaces as padding since they are ignored by json.
padded_payload += " "

cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted_payload = cipher.encrypt(padded_payload)

temp = iv + encrypted_payload
data_send = base64.b64encode(temp)
prefixed_channel = generatePrefixedChannel(alert["username"],
alert["channel"])

data = {"username": alert["username"],
"password": alert["password"],
"channel": prefixed_channel,
"data": data_send,
"version": 0.1}

client.send(json.dumps(data))

response_str = client.recv(BUFSIZE)

response = json.loads(response_str)
# Initialize alert object.
alertObj = PushAlert(globalData)
alertObj.id = alert["id"]
alertObj.description = alert["description"]
alertObj.username = alert["username"]
alertObj.password = alert["password"]
alertObj.channel = alert["channel"]
alertObj.encSecret = alert["encSecret"]
alertObj.templateFile = alert["templateFile"]
alertObj.alertLevels = list()
alertObj.subject = subject
alertObj.initializeAlert()

sensorAlert = SensorAlert()
sensorAlert.state = 1
sensorAlert.timeReceived = int(time.time())

errorCode = alertObj._sendMessage(subject, message, sensorAlert)

# Process response.
if response["Code"] == ErrorCodes.NO_ERROR:
if errorCode == ErrorCodes.NO_ERROR:
logging.info("[%s]: Message successfully transmitted." % fileName)
elif response["Code"] == ErrorCodes.DATABASE_ERROR:
elif errorCode == ErrorCodes.DATABASE_ERROR:
logging.error("[%s]: Database error on server side. "
% fileName
+ "Please try again later.")
elif response["Code"] == ErrorCodes.AUTH_ERROR:
elif errorCode == ErrorCodes.AUTH_ERROR:
logging.error("[%s]: Authentication failed. "
% fileName
+ "Check your credentials.")
elif response["Code"] == ErrorCodes.ILLEGAL_MSG_ERROR:
elif errorCode == ErrorCodes.ILLEGAL_MSG_ERROR:
logging.error("[%s]: Illegal message was sent. "
% fileName
+ "Please make sure to use the newest version. "
+ "If you do, please open an issue on "
+ "https://github.com/sqall01/alertR.")
elif response["Code"] == ErrorCodes.GOOGLE_MSG_TOO_LARGE:
elif errorCode == ErrorCodes.GOOGLE_MSG_TOO_LARGE:
logging.error("[%s]: Transmitted message too large. "
% fileName
+ "Please shorten it.")
elif response["Code"] == ErrorCodes.GOOGLE_CONNECTION:
elif errorCode == ErrorCodes.GOOGLE_CONNECTION:
logging.error("[%s]: Connection error on server side. "
% fileName
+ "Please try again later.")
elif response["Code"] == ErrorCodes.GOOGLE_AUTH:
elif errorCode == ErrorCodes.GOOGLE_AUTH:
logging.error("[%s]: Authentication error on server side. "
% fileName
+ "Please try again later.")
elif response["Code"] == ErrorCodes.VERSION_MISSMATCH:
elif errorCode == ErrorCodes.VERSION_MISSMATCH:
logging.error("[%s]: Version mismatch. "
% fileName
+ "Please update your client.")
elif response["Code"] == ErrorCodes.NO_NOTIFICATION_PERMISSION:
elif errorCode == ErrorCodes.NO_NOTIFICATION_PERMISSION:
logging.error("[%s]: No permission to use notification channel. "
% fileName
+ "Please update channel configuration.")
elif errorCode == ErrorCodes.CLIENT_CONNECTION_ERROR:
logging.error("[%s]: Client has problems connecting to service. "
% fileName
+ "Do you have an Internet connection?.")
else:
logging.error("[%s]: The following error code occurred: %d."
% (fileName, response["Code"])
% (fileName, errorCode)
+ "Please make sure to use the newest version. "
+ "If you do, please open an issue on "
+ "https://github.com/sqall01/alertR.")
+ "https://github.com/sqall01/alertR.")

0 comments on commit 105f431

Please sign in to comment.