Merge branch 'master' of github.com:Atheros1/PyBitmessage

This commit is contained in:
Jonathan Warren 2013-07-15 19:28:31 -04:00
commit c6291f55ef
7 changed files with 151 additions and 59 deletions

View File

@ -720,7 +720,6 @@ if __name__ == "__main__":
helper_bootstrap.knownNodes()
helper_bootstrap.dns()
# Start the address generation thread
addressGeneratorThread = addressGenerator()
addressGeneratorThread.daemon = True # close the main program even if there are threads left

View File

@ -29,6 +29,8 @@ import os
from pyelliptic.openssl import OpenSSL
import pickle
import platform
import debug
from debug import logger
try:
from PyQt4 import QtCore, QtGui
@ -1876,7 +1878,14 @@ class MyForm(QtGui.QMainWindow):
shared.knownNodesLock.release()
os.remove(shared.appdata + 'keys.dat')
os.remove(shared.appdata + 'knownnodes.dat')
previousAppdataLocation = shared.appdata
shared.appdata = ''
debug.restartLoggingInUpdatedAppdataLocation()
try:
os.remove(previousAppdataLocation + 'debug.log')
os.remove(previousAppdataLocation + 'debug.log.1')
except:
pass
if shared.appdata == '' and not self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): # If we ARE using portable mode now but the user selected that we shouldn't...
shared.appdata = shared.lookupAppdataFolder()
@ -1896,6 +1905,12 @@ class MyForm(QtGui.QMainWindow):
shared.knownNodesLock.release()
os.remove('keys.dat')
os.remove('knownnodes.dat')
debug.restartLoggingInUpdatedAppdataLocation()
try:
os.remove('debug.log')
os.remove('debug.log.1')
except:
pass
def click_radioButtonBlacklist(self):
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white':

View File

@ -5,6 +5,7 @@ import time
import shutil # used for moving the messages.dat file
import sys
import os
from debug import logger
# This thread exists because SQLITE3 is so un-threadsafe that we must
# submit queries to it and it puts results back in a different queue. They

View File

@ -23,6 +23,7 @@ import shared
# TODO(xj9): Get from a config file.
log_level = 'DEBUG'
def configureLogging():
logging.config.dictConfig({
'version': 1,
'formatters': {
@ -67,4 +68,14 @@ logging.config.dictConfig({
})
# TODO (xj9): Get from a config file.
#logger = logging.getLogger('console_only')
configureLogging()
logger = logging.getLogger('both')
def restartLoggingInUpdatedAppdataLocation():
global logger
for i in list(logger.handlers):
logger.removeHandler(i)
i.flush()
i.close()
configureLogging()
logger = logging.getLogger('both')

View File

@ -33,7 +33,7 @@ def dns():
print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method'
shared.knownNodes[1][item[4][0]] = (8080, int(time.time()))
except:
print 'bootstrap8080.bitmessage.org DNS bootstraping failed.'
print 'bootstrap8080.bitmessage.org DNS bootstrapping failed.'
try:
for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80):
print 'Adding', item[4][0], 'to knownNodes based on DNS boostrap method'

View File

@ -76,6 +76,8 @@ def loadConfig():
print 'Creating new config files in', shared.appdata
if not os.path.exists(shared.appdata):
os.makedirs(shared.appdata)
if not sys.platform.startswith('win'):
os.umask(0o077)
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)

View File

@ -8,22 +8,26 @@ 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 *
import highlevelcrypto
import shared
import helper_startup
config = ConfigParser.SafeConfigParser()
myECCryptorObjects = {}
MyECSubscriptionCryptorObjects = {}
@ -118,8 +122,11 @@ def lookupAppdataFolder():
if "HOME" in environ:
dataFolder = path.join(os.environ["HOME"], "Library/Application Support/", APPNAME) + '/'
else:
logger.critical('Could not find home folder, please report this message and your '
'OS X version to the BitMessage Github.')
stringToLog = 'Could not find home folder, please report this message and your OS X version to the BitMessage Github.'
if 'logger' in globals():
logger.critical(stringToLog)
else:
print stringToLog
sys.exit()
elif 'win32' in sys.platform or 'win64' in sys.platform:
@ -133,9 +140,14 @@ def lookupAppdataFolder():
# Migrate existing data to the proper location if this is an existing install
try:
logger.info("Moving data folder to %s" % (dataFolder))
move(path.join(environ["HOME"], ".%s" % APPNAME), dataFolder)
stringToLog = "Moving data folder to %s" % (dataFolder)
if 'logger' in globals():
logger.info(stringToLog)
else:
print stringToLog
except IOError:
# Old directory may not exist.
pass
dataFolder = dataFolder + '/'
return dataFolder
@ -190,14 +202,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 +221,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 +297,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 +335,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