2017-10-24 19:16:36 +05:00
|
|
|
import CyberCPLogFileWriter as logging
|
|
|
|
|
import shutil
|
|
|
|
|
import os
|
|
|
|
|
import shlex
|
|
|
|
|
import subprocess
|
2017-12-09 22:30:10 +05:00
|
|
|
import socket
|
2017-10-24 19:16:36 +05:00
|
|
|
|
|
|
|
|
class sslUtilities:
|
|
|
|
|
|
2017-12-09 22:30:10 +05:00
|
|
|
Server_root = "/usr/local/lsws"
|
|
|
|
|
|
2018-05-08 21:25:37 +05:00
|
|
|
@staticmethod
|
|
|
|
|
def checkIfSSLMap(virtualHostName):
|
|
|
|
|
try:
|
|
|
|
|
data = open("/usr/local/lsws/conf/httpd_config.conf").readlines()
|
|
|
|
|
|
|
|
|
|
sslCheck = 0
|
|
|
|
|
|
|
|
|
|
for items in data:
|
2018-05-12 02:21:42 +05:00
|
|
|
if items.find("listener") >-1 and items.find("SSL") > -1:
|
2018-05-08 21:25:37 +05:00
|
|
|
sslCheck = 1
|
|
|
|
|
continue
|
|
|
|
|
if sslCheck == 1:
|
|
|
|
|
if items.find("}") > -1:
|
|
|
|
|
return 0
|
|
|
|
|
if items.find(virtualHostName) > -1 and sslCheck == 1:
|
|
|
|
|
data = filter(None, items.split(" "))
|
|
|
|
|
if data[1] == virtualHostName:
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
except BaseException,msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [IO Error with main config file [checkIfSSLMap]]")
|
|
|
|
|
return 0
|
|
|
|
|
|
2018-08-23 15:39:28 +05:00
|
|
|
@staticmethod
|
|
|
|
|
def checkSSLListener():
|
|
|
|
|
try:
|
|
|
|
|
data = open("/usr/local/lsws/conf/httpd_config.conf").readlines()
|
|
|
|
|
for items in data:
|
|
|
|
|
if items.find("listener SSL") > -1:
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
except BaseException,msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [IO Error with main config file [checkSSLListener]]")
|
|
|
|
|
return str(msg)
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def getDNSRecords(virtualHostName):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
withoutWWW = socket.gethostbyname(virtualHostName)
|
|
|
|
|
withWWW = socket.gethostbyname('www.' + virtualHostName)
|
|
|
|
|
|
|
|
|
|
return [1, withWWW, withoutWWW]
|
|
|
|
|
|
|
|
|
|
except BaseException, msg:
|
|
|
|
|
return [0, "347 " + str(msg) + " [issueSSLForDomain]"]
|
|
|
|
|
|
2017-10-24 19:16:36 +05:00
|
|
|
@staticmethod
|
|
|
|
|
def installSSLForDomain(virtualHostName):
|
|
|
|
|
|
2017-12-09 22:30:10 +05:00
|
|
|
confPath = sslUtilities.Server_root + "/conf/vhosts/" + virtualHostName
|
2017-10-24 19:16:36 +05:00
|
|
|
completePathToConfigFile = confPath + "/vhost.conf"
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
map = " map " + virtualHostName + " " + virtualHostName + "\n"
|
|
|
|
|
|
2018-08-23 15:39:28 +05:00
|
|
|
if sslUtilities.checkSSLListener() != 1:
|
2018-05-12 02:21:42 +05:00
|
|
|
|
2017-10-24 19:16:36 +05:00
|
|
|
writeDataToFile = open("/usr/local/lsws/conf/httpd_config.conf", 'a')
|
|
|
|
|
|
|
|
|
|
listener = "listener SSL {" + "\n"
|
|
|
|
|
address = " address *:443" + "\n"
|
|
|
|
|
secure = " secure 1" + "\n"
|
2018-08-23 15:39:28 +05:00
|
|
|
keyFile = " keyFile /etc/letsencrypt/live/" + virtualHostName + "/privkey.pem\n"
|
|
|
|
|
certFile = " certFile /etc/letsencrypt/live/" + virtualHostName + "/fullchain.pem\n"
|
2017-10-24 19:16:36 +05:00
|
|
|
certChain = " certChain 1" + "\n"
|
2018-03-19 22:15:02 +05:00
|
|
|
sslProtocol = " sslProtocol 30" + "\n"
|
2017-10-24 19:16:36 +05:00
|
|
|
map = " map " + virtualHostName + " " + virtualHostName + "\n"
|
|
|
|
|
final = "}" + "\n" + "\n"
|
|
|
|
|
|
|
|
|
|
writeDataToFile.writelines("\n")
|
|
|
|
|
writeDataToFile.writelines(listener)
|
|
|
|
|
writeDataToFile.writelines(address)
|
|
|
|
|
writeDataToFile.writelines(secure)
|
|
|
|
|
writeDataToFile.writelines(keyFile)
|
|
|
|
|
writeDataToFile.writelines(certFile)
|
|
|
|
|
writeDataToFile.writelines(certChain)
|
|
|
|
|
writeDataToFile.writelines(sslProtocol)
|
|
|
|
|
writeDataToFile.writelines(map)
|
|
|
|
|
writeDataToFile.writelines(final)
|
|
|
|
|
writeDataToFile.writelines("\n")
|
|
|
|
|
writeDataToFile.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
2017-10-26 23:50:59 +05:00
|
|
|
|
2018-05-08 21:25:37 +05:00
|
|
|
if sslUtilities.checkIfSSLMap(virtualHostName) == 0:
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-08 21:25:37 +05:00
|
|
|
data = open("/usr/local/lsws/conf/httpd_config.conf").readlines()
|
|
|
|
|
writeDataToFile = open("/usr/local/lsws/conf/httpd_config.conf", 'w')
|
|
|
|
|
sslCheck = 0
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-08 21:25:37 +05:00
|
|
|
for items in data:
|
2018-08-23 15:39:28 +05:00
|
|
|
if items.find("listener") > -1 and items.find("SSL") > -1:
|
2018-05-08 21:25:37 +05:00
|
|
|
sslCheck = 1
|
|
|
|
|
|
|
|
|
|
if (sslCheck == 1):
|
2018-05-12 02:21:42 +05:00
|
|
|
writeDataToFile.writelines(items)
|
2018-05-08 21:25:37 +05:00
|
|
|
writeDataToFile.writelines(map)
|
|
|
|
|
sslCheck = 0
|
2018-05-14 22:26:25 +05:00
|
|
|
else:
|
|
|
|
|
writeDataToFile.writelines(items)
|
2018-05-08 21:25:37 +05:00
|
|
|
writeDataToFile.close()
|
2017-10-24 19:16:36 +05:00
|
|
|
|
|
|
|
|
###################### Write per host Configs for SSL ###################
|
|
|
|
|
|
2018-08-23 15:39:28 +05:00
|
|
|
data = open(completePathToConfigFile, "r").readlines()
|
2017-10-24 19:16:36 +05:00
|
|
|
|
|
|
|
|
## check if vhssl is already in vhconf file
|
|
|
|
|
|
|
|
|
|
vhsslPresense = 0
|
|
|
|
|
|
|
|
|
|
for items in data:
|
2018-08-23 15:39:28 +05:00
|
|
|
if items.find("vhssl") > -1:
|
2017-10-24 19:16:36 +05:00
|
|
|
vhsslPresense = 1
|
|
|
|
|
|
|
|
|
|
if vhsslPresense == 0:
|
2018-08-23 15:39:28 +05:00
|
|
|
writeSSLConfig = open(completePathToConfigFile, "a")
|
2017-10-24 19:16:36 +05:00
|
|
|
|
|
|
|
|
vhssl = "vhssl {" + "\n"
|
2018-08-22 00:37:43 +05:00
|
|
|
keyFile = " keyFile /etc/letsencrypt/live/" + virtualHostName + "/privkey.pem\n"
|
|
|
|
|
certFile = " certFile /etc/letsencrypt/live/" + virtualHostName + "/fullchain.pem\n"
|
2017-10-24 19:16:36 +05:00
|
|
|
certChain = " certChain 1" + "\n"
|
2018-03-19 22:15:02 +05:00
|
|
|
sslProtocol = " sslProtocol 30" + "\n"
|
2017-10-24 19:16:36 +05:00
|
|
|
final = "}"
|
|
|
|
|
|
|
|
|
|
writeSSLConfig.writelines("\n")
|
|
|
|
|
|
|
|
|
|
writeSSLConfig.writelines(vhssl)
|
|
|
|
|
writeSSLConfig.writelines(keyFile)
|
|
|
|
|
writeSSLConfig.writelines(certFile)
|
|
|
|
|
writeSSLConfig.writelines(certChain)
|
|
|
|
|
writeSSLConfig.writelines(sslProtocol)
|
|
|
|
|
writeSSLConfig.writelines(final)
|
|
|
|
|
|
|
|
|
|
writeSSLConfig.writelines("\n")
|
|
|
|
|
|
|
|
|
|
writeSSLConfig.close()
|
|
|
|
|
|
2017-12-09 22:30:10 +05:00
|
|
|
return 1
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-08-23 15:39:28 +05:00
|
|
|
except BaseException, msg:
|
2017-12-09 22:30:10 +05:00
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [installSSLForDomain]]")
|
2017-10-24 19:16:36 +05:00
|
|
|
return 0
|
|
|
|
|
|
2018-05-06 14:18:41 +05:00
|
|
|
@staticmethod
|
2018-05-08 21:25:37 +05:00
|
|
|
def obtainSSLForADomain(virtualHostName,adminEmail,sslpath, aliasDomain = None):
|
2018-05-06 14:18:41 +05:00
|
|
|
try:
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-06 14:18:41 +05:00
|
|
|
## Obtaining Server IP
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-08 21:25:37 +05:00
|
|
|
if aliasDomain == None:
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-08-22 00:37:43 +05:00
|
|
|
existingCertPath = '/etc/letsencrypt/live/' + virtualHostName + '/README'
|
|
|
|
|
if os.path.exists(existingCertPath):
|
|
|
|
|
return 1
|
|
|
|
|
|
2018-05-21 16:51:28 +05:00
|
|
|
try:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile("Trying to obtain SSL for: " + virtualHostName + " and: www." + virtualHostName)
|
2018-08-23 15:39:28 +05:00
|
|
|
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d www." + virtualHostName
|
2018-05-21 16:51:28 +05:00
|
|
|
output = subprocess.check_output(shlex.split(command))
|
2018-08-23 15:39:28 +05:00
|
|
|
logging.CyberCPLogFileWriter.writeToFile("Successfully obtained SSL for: " + virtualHostName + " and: www." + virtualHostName)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except subprocess.CalledProcessError:
|
2018-05-21 16:51:28 +05:00
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
"Failed to obtain SSL for: " + virtualHostName + " and: www." + virtualHostName)
|
2018-08-23 15:39:28 +05:00
|
|
|
|
2018-05-21 16:51:28 +05:00
|
|
|
try:
|
2018-08-23 15:39:28 +05:00
|
|
|
logging.CyberCPLogFileWriter.writeToFile("Trying to obtain SSL for: " + virtualHostName)
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName
|
2018-05-21 16:51:28 +05:00
|
|
|
output = subprocess.check_output(shlex.split(command))
|
2018-08-23 15:39:28 +05:00
|
|
|
logging.CyberCPLogFileWriter.writeToFile("Successfully obtained SSL for: " + virtualHostName)
|
|
|
|
|
except subprocess.CalledProcessError:
|
2018-05-21 16:51:28 +05:00
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Failed to obtain SSL, issuing self-signed SSL for: ' + virtualHostName)
|
|
|
|
|
return 0
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-21 16:51:28 +05:00
|
|
|
##
|
|
|
|
|
|
|
|
|
|
if output.find('Congratulations!') > -1:
|
|
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
elif output.find('no action taken.') > -1:
|
2018-05-21 21:52:35 +05:00
|
|
|
|
2018-05-21 16:51:28 +05:00
|
|
|
return 1
|
|
|
|
|
elif output.find('Failed authorization procedure') > -1:
|
2018-05-08 21:25:37 +05:00
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
2018-05-21 16:51:28 +05:00
|
|
|
'Failed authorization procedure for ' + virtualHostName + " while issuing Let's Encrypt SSL.")
|
|
|
|
|
return 0
|
|
|
|
|
elif output.find('Too many SSL requests for this domain, please try to get SSL at later time.') > -1:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
'Too many SSL requests for ' + virtualHostName + " please try to get SSL at later time.")
|
2018-05-08 21:25:37 +05:00
|
|
|
return 0
|
|
|
|
|
|
2018-05-06 14:18:41 +05:00
|
|
|
else:
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-08-23 15:39:28 +05:00
|
|
|
ipFile = "/etc/cyberpanel/machineIP"
|
|
|
|
|
f = open(ipFile)
|
|
|
|
|
ipData = f.read()
|
|
|
|
|
serverIPAddress = ipData.split('\n', 1)[0]
|
|
|
|
|
|
2018-05-08 21:25:37 +05:00
|
|
|
ipRecords = sslUtilities.getDNSRecords(virtualHostName)
|
|
|
|
|
|
|
|
|
|
if ipRecords[0] == 1:
|
|
|
|
|
|
|
|
|
|
if serverIPAddress == ipRecords[1] and serverIPAddress == ipRecords[2]:
|
|
|
|
|
|
|
|
|
|
ipRecordsAlias = sslUtilities.getDNSRecords(aliasDomain)
|
|
|
|
|
|
|
|
|
|
if serverIPAddress == ipRecordsAlias[1] and serverIPAddress == ipRecordsAlias[2]:
|
|
|
|
|
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d www." + virtualHostName + " -d " + aliasDomain + " -d www." + aliasDomain
|
2018-05-08 21:25:37 +05:00
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
if serverIPAddress == ipRecordsAlias[2]:
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d www." + virtualHostName + " -d " + aliasDomain
|
2018-05-08 21:25:37 +05:00
|
|
|
else:
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d www." + virtualHostName
|
2018-05-08 21:25:37 +05:00
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
if serverIPAddress == ipRecords[2]:
|
|
|
|
|
|
|
|
|
|
ipRecordsAlias = sslUtilities.getDNSRecords(aliasDomain)
|
|
|
|
|
|
|
|
|
|
if serverIPAddress == ipRecordsAlias[1] and serverIPAddress == ipRecordsAlias[2]:
|
|
|
|
|
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d " + aliasDomain + " -d www." + aliasDomain
|
2018-05-08 21:25:37 +05:00
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
if serverIPAddress == ipRecordsAlias[2]:
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName + " -d " + aliasDomain
|
2018-05-08 21:25:37 +05:00
|
|
|
else:
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + virtualHostName
|
2018-05-08 21:25:37 +05:00
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
"SSL is issued without 'www' due to DNS error for domain : " + virtualHostName)
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
ipRecordsAlias = sslUtilities.getDNSRecords(aliasDomain)
|
|
|
|
|
|
|
|
|
|
if serverIPAddress == ipRecordsAlias[1] and serverIPAddress == ipRecordsAlias[2]:
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + aliasDomain + " -d www." + aliasDomain
|
2018-05-08 21:25:37 +05:00
|
|
|
else:
|
|
|
|
|
if serverIPAddress == ipRecordsAlias[2]:
|
2018-07-23 02:09:33 +05:00
|
|
|
command = "/usr/local/CyberCP/bin/certbot certonly -n --expand --agree-tos --email " + adminEmail + " --webroot -w " + sslpath + " -d " + aliasDomain
|
2018-05-08 21:25:37 +05:00
|
|
|
else:
|
|
|
|
|
return 0
|
|
|
|
|
else:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
"Failed to obtain DNS records for " + virtualHostName + ", issuing self signed certificate.")
|
|
|
|
|
return 0
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-08-23 15:39:28 +05:00
|
|
|
output = subprocess.check_output(shlex.split(command))
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-08-23 15:39:28 +05:00
|
|
|
if output.find('Congratulations!') > -1:
|
|
|
|
|
return 1
|
|
|
|
|
elif output.find('no action taken.') > -1:
|
|
|
|
|
return 1
|
|
|
|
|
elif output.find('Failed authorization procedure') > -1:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
'Failed authorization procedure for ' + virtualHostName + " while issuing Let's Encrypt SSL.")
|
|
|
|
|
return 0
|
|
|
|
|
elif output.find('Too many SSL requests for this domain, please try to get SSL at later time.') > -1:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
'Too many SSL requests for ' + virtualHostName + " please try to get SSL at later time.")
|
|
|
|
|
return 0
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-06 14:18:41 +05:00
|
|
|
except BaseException,msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [Failed to obtain SSL. [obtainSSLForADomain]]")
|
|
|
|
|
return 0
|
2017-10-24 19:16:36 +05:00
|
|
|
|
|
|
|
|
|
2018-05-21 16:51:28 +05:00
|
|
|
def issueSSLForDomain(domain, adminEmail, sslpath, aliasDomain = None):
|
2018-05-06 14:18:41 +05:00
|
|
|
try:
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-08 21:25:37 +05:00
|
|
|
if sslUtilities.obtainSSLForADomain(domain, adminEmail, sslpath, aliasDomain) == 1:
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-06 14:18:41 +05:00
|
|
|
if sslUtilities.installSSLForDomain(domain) == 1:
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
else:
|
|
|
|
|
return [0, "210 Failed to install SSL for domain. [issueSSLForDomain]"]
|
|
|
|
|
else:
|
2018-10-03 18:46:44 +05:00
|
|
|
pathToStoreSSL = "/etc/letsencrypt/live/" + domain
|
|
|
|
|
command = 'mkdir -p ' + pathToStoreSSL
|
|
|
|
|
subprocess.call(shlex.split(command))
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-08-22 00:37:43 +05:00
|
|
|
pathToStoreSSLPrivKey = "/etc/letsencrypt/live/" + domain + "/privkey.pem"
|
|
|
|
|
pathToStoreSSLFullChain = "/etc/letsencrypt/live/" + domain + "/fullchain.pem"
|
2017-10-24 19:16:36 +05:00
|
|
|
|
2018-05-06 14:18:41 +05:00
|
|
|
command = 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -keyout ' + pathToStoreSSLPrivKey + ' -out ' + pathToStoreSSLFullChain
|
|
|
|
|
cmd = shlex.split(command)
|
|
|
|
|
subprocess.call(cmd)
|
2017-12-09 22:30:10 +05:00
|
|
|
|
|
|
|
|
if sslUtilities.installSSLForDomain(domain) == 1:
|
2018-05-06 14:18:41 +05:00
|
|
|
logging.CyberCPLogFileWriter.writeToFile("Self signed SSL issued for " + domain + ".")
|
2017-12-09 22:30:10 +05:00
|
|
|
return [1, "None"]
|
|
|
|
|
else:
|
2018-05-06 14:18:41 +05:00
|
|
|
return [0, "220 Failed to install SSL for domain. [issueSSLForDomain]"]
|
|
|
|
|
|
2017-12-09 22:30:10 +05:00
|
|
|
except BaseException,msg:
|
2018-07-19 22:38:37 +05:00
|
|
|
return [0, "347 "+ str(msg)+ " [issueSSLForDomain]"]
|