|
|
|
@ -8,22 +8,27 @@ maximumAgeOfNodesThatIAdvertiseToOthers = 10800 # Equals three hours
|
|
|
|
|
useVeryEasyProofOfWorkForTesting = False # If you set this to True while on the normal network, you won't be able to send or sometimes receive messages.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import threading
|
|
|
|
|
import sys
|
|
|
|
|
from addresses import *
|
|
|
|
|
import highlevelcrypto
|
|
|
|
|
import Queue
|
|
|
|
|
import pickle
|
|
|
|
|
import os
|
|
|
|
|
import time
|
|
|
|
|
# Libraries.
|
|
|
|
|
import ConfigParser
|
|
|
|
|
import socket
|
|
|
|
|
import os
|
|
|
|
|
import pickle
|
|
|
|
|
import Queue
|
|
|
|
|
import random
|
|
|
|
|
import socket
|
|
|
|
|
import sys
|
|
|
|
|
import stat
|
|
|
|
|
import threading
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
# Project imports.
|
|
|
|
|
from addresses import *
|
|
|
|
|
from debug import logger
|
|
|
|
|
import highlevelcrypto
|
|
|
|
|
import shared
|
|
|
|
|
import helper_startup
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
config = ConfigParser.SafeConfigParser()
|
|
|
|
|
myECCryptorObjects = {}
|
|
|
|
|
MyECSubscriptionCryptorObjects = {}
|
|
|
|
@ -136,6 +141,7 @@ def lookupAppdataFolder():
|
|
|
|
|
logger.info("Moving data folder to %s" % (dataFolder))
|
|
|
|
|
move(path.join(environ["HOME"], ".%s" % APPNAME), dataFolder)
|
|
|
|
|
except IOError:
|
|
|
|
|
# Old directory may not exist.
|
|
|
|
|
pass
|
|
|
|
|
dataFolder = dataFolder + '/'
|
|
|
|
|
return dataFolder
|
|
|
|
@ -190,14 +196,17 @@ def decodeWalletImportFormat(WIFstring):
|
|
|
|
|
fullString = arithmetic.changebase(WIFstring,58,256)
|
|
|
|
|
privkey = fullString[:-4]
|
|
|
|
|
if fullString[-4:] != hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]:
|
|
|
|
|
sys.stderr.write('Major problem! When trying to decode one of your private keys, the checksum failed. Here is the PRIVATE key: %s\n' % str(WIFstring))
|
|
|
|
|
logger.error('Major problem! When trying to decode one of your private keys, the checksum '
|
|
|
|
|
'failed. Here is the PRIVATE key: %s\n' % str(WIFstring))
|
|
|
|
|
return ""
|
|
|
|
|
else:
|
|
|
|
|
#checksum passed
|
|
|
|
|
if privkey[0] == '\x80':
|
|
|
|
|
return privkey[1:]
|
|
|
|
|
else:
|
|
|
|
|
sys.stderr.write('Major problem! When trying to decode one of your private keys, the checksum passed but the key doesn\'t begin with hex 80. Here is the PRIVATE key: %s\n' % str(WIFstring))
|
|
|
|
|
logger.error('Major problem! When trying to decode one of your private keys, the '
|
|
|
|
|
'checksum passed but the key doesn\'t begin with hex 80. Here is the '
|
|
|
|
|
'PRIVATE key: %s\n' % str(WIFstring))
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -206,19 +215,32 @@ def reloadMyAddressHashes():
|
|
|
|
|
myECCryptorObjects.clear()
|
|
|
|
|
myAddressesByHash.clear()
|
|
|
|
|
#myPrivateKeys.clear()
|
|
|
|
|
|
|
|
|
|
keyfileSecure = checkSensitiveFilePermissions(appdata + 'keys.dat')
|
|
|
|
|
configSections = config.sections()
|
|
|
|
|
hasEnabledKeys = False
|
|
|
|
|
for addressInKeysFile in configSections:
|
|
|
|
|
if addressInKeysFile <> 'bitmessagesettings':
|
|
|
|
|
isEnabled = config.getboolean(addressInKeysFile, 'enabled')
|
|
|
|
|
if isEnabled:
|
|
|
|
|
hasEnabledKeys = True
|
|
|
|
|
status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile)
|
|
|
|
|
if addressVersionNumber == 2 or addressVersionNumber == 3:
|
|
|
|
|
privEncryptionKey = decodeWalletImportFormat(config.get(addressInKeysFile, 'privencryptionkey')).encode('hex') #returns a simple 32 bytes of information encoded in 64 Hex characters, or null if there was an error
|
|
|
|
|
# Returns a simple 32 bytes of information encoded in 64 Hex characters,
|
|
|
|
|
# or null if there was an error.
|
|
|
|
|
privEncryptionKey = decodeWalletImportFormat(
|
|
|
|
|
config.get(addressInKeysFile, 'privencryptionkey')).encode('hex')
|
|
|
|
|
|
|
|
|
|
if len(privEncryptionKey) == 64:#It is 32 bytes encoded as 64 hex characters
|
|
|
|
|
myECCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey)
|
|
|
|
|
myAddressesByHash[hash] = addressInKeysFile
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
sys.stderr.write('Error in reloadMyAddressHashes: Can\'t handle address versions other than 2 or 3.\n')
|
|
|
|
|
logger.error('Error in reloadMyAddressHashes: Can\'t handle address '
|
|
|
|
|
'versions other than 2 or 3.\n')
|
|
|
|
|
|
|
|
|
|
if not keyfileSecure:
|
|
|
|
|
fixSensitiveFilePermissions(appdata + 'keys.dat', hasEnabledKeys)
|
|
|
|
|
|
|
|
|
|
def reloadBroadcastSendersForWhichImWatching():
|
|
|
|
|
logger.debug('reloading subscriptions...')
|
|
|
|
@ -269,6 +291,7 @@ def doCleanShutdown():
|
|
|
|
|
sqlSubmitQueue.put('exit')
|
|
|
|
|
sqlLock.release()
|
|
|
|
|
logger.info('Finished flushing inventory.')
|
|
|
|
|
|
|
|
|
|
# Wait long enough to guarantee that any running proof of work worker threads will check the
|
|
|
|
|
# shutdown variable and exit. If the main thread closes before they do then they won't stop.
|
|
|
|
|
time.sleep(.25)
|
|
|
|
@ -306,5 +329,40 @@ def fixPotentiallyInvalidUTF8Data(text):
|
|
|
|
|
output = 'Part of the message is corrupt. The message cannot be displayed the normal way.\n\n' + repr(text)
|
|
|
|
|
return output
|
|
|
|
|
|
|
|
|
|
# Checks sensitive file permissions for inappropriate umask during keys.dat creation.
|
|
|
|
|
# (Or unwise subsequent chmod.)
|
|
|
|
|
#
|
|
|
|
|
# Returns true iff file appears to have appropriate permissions.
|
|
|
|
|
def checkSensitiveFilePermissions(filename):
|
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
|
# TODO: This might deserve extra checks by someone familiar with
|
|
|
|
|
# Windows systems.
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
present_permissions = os.stat(filename)[0]
|
|
|
|
|
disallowed_permissions = stat.S_IRWXG | stat.S_IRWXO
|
|
|
|
|
return present_permissions & disallowed_permissions == 0
|
|
|
|
|
|
|
|
|
|
# Fixes permissions on a sensitive file.
|
|
|
|
|
def fixSensitiveFilePermissions(filename, hasEnabledKeys):
|
|
|
|
|
if hasEnabledKeys:
|
|
|
|
|
logger.warning('Keyfile had insecure permissions, and there were enabled keys. '
|
|
|
|
|
'The truly paranoid should stop using them immediately.')
|
|
|
|
|
else:
|
|
|
|
|
logger.warning('Keyfile had insecure permissions, but there were no enabled keys.')
|
|
|
|
|
try:
|
|
|
|
|
present_permissions = os.stat(filename)[0]
|
|
|
|
|
disallowed_permissions = stat.S_IRWXG | stat.S_IRWXO
|
|
|
|
|
allowed_permissions = ((1<<32)-1) ^ disallowed_permissions
|
|
|
|
|
new_permissions = (
|
|
|
|
|
allowed_permissions & present_permissions)
|
|
|
|
|
os.chmod(filename, new_permissions)
|
|
|
|
|
|
|
|
|
|
logger.info('Keyfile permissions automatically fixed.')
|
|
|
|
|
|
|
|
|
|
except Exception, e:
|
|
|
|
|
logger.exception('Keyfile permissions could not be fixed.')
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
helper_startup.loadConfig()
|
|
|
|
|
from debug import logger
|