Make writing keys.dat safer by creating a backup file #715

Merged
yurivict merged 3 commits from some_small_changes into master 2014-12-26 03:09:17 +01:00
8 changed files with 50 additions and 69 deletions

View File

@ -429,8 +429,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
if not shared.safeConfigGetBoolean(address, 'chan'):
raise APIError(25, 'Specified address is not a chan address. Use deleteAddress API call instead.')
shared.config.remove_section(address)
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
return 'success'
elif method == 'deleteAddress':
@ -443,8 +442,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
if not shared.config.has_section(address):
raise APIError(13, 'Could not find this address in your keys.dat file.')
shared.config.remove_section(address)
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
shared.UISignalQueue.put(('rerenderInboxFromLabels',''))
shared.UISignalQueue.put(('rerenderSentToLabels',''))
shared.reloadMyAddressHashes()

View File

@ -470,15 +470,13 @@ def handlech(c, stdscr):
label = t
shared.config.set(a, "label", label)
# Write config
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
addresses[addrcur][0] = label
elif t == "4": # Enable address
a = addresses[addrcur][2]
shared.config.set(a, "enabled", "true") # Set config
# Write config
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# Change color
if shared.safeConfigGetBoolean(a, 'chan'):
addresses[addrcur][3] = 9 # orange
@ -493,16 +491,14 @@ def handlech(c, stdscr):
shared.config.set(a, "enabled", "false") # Set config
addresses[addrcur][3] = 8 # Set color to gray
# Write config
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
addresses[addrcur][1] = False
shared.reloadMyAddressHashes() # Reload address hashes
elif t == "6": # Delete address
r, t = d.inputbox("Type in \"I want to delete this address\"", width=50)
if r == d.DIALOG_OK and t == "I want to delete this address":
shared.config.remove_section(addresses[addrcur][2])
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
del addresses[addrcur]
elif t == "7": # Special address behavior
a = addresses[addrcur][2]
@ -533,8 +529,7 @@ def handlech(c, stdscr):
shared.config.set(a, "mailinglistname", mn)
addresses[addrcur][3] = 6 # Set color to magenta
# Write config
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
elif menutab == 5:
d.set_background_title("Subscriptions Dialog Box")
r, t = d.menu("Do what with subscription to \""+subscriptions[subcur][0]+"\"?",

View File

@ -462,8 +462,7 @@ class MyForm(QtGui.QMainWindow):
self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
shared.config.remove_section(addressInKeysFile)
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# Configure Bitmessage to start on startup (or remove the
# configuration) based on the setting in the keys.dat file
@ -1338,7 +1337,7 @@ class MyForm(QtGui.QMainWindow):
reply = QtGui.QMessageBox.question(self, _translate("MainWindow", "Open keys.dat?"), _translate(
"MainWindow", "You may manage your keys by editing the keys.dat file stored in\n %1 \nIt is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.)").arg(shared.appdata), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
self.openKeysFile()
shared.openKeysFile()
def click_actionDeleteAllTrashedMessages(self):
if QtGui.QMessageBox.question(self, _translate("MainWindow", "Delete trash?"), _translate("MainWindow", "Are you sure you want to delete all trashed messages?"), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) == QtGui.QMessageBox.No:
@ -1428,17 +1427,10 @@ class MyForm(QtGui.QMainWindow):
if self.connectDialogInstance.exec_():
if self.connectDialogInstance.ui.radioButtonConnectNow.isChecked():
shared.config.remove_option('bitmessagesettings', 'dontconnect')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
else:
self.click_actionSettings()
def openKeysFile(self):
if 'linux' in sys.platform:
subprocess.call(["xdg-open", shared.appdata + 'keys.dat'])
else:
os.startfile(shared.appdata + 'keys.dat')
def changeEvent(self, event):
if event.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized:
@ -2385,8 +2377,7 @@ class MyForm(QtGui.QMainWindow):
# shared.config.set('bitmessagesettings', 'maxcores',
# str(self.settingsDialogInstance.ui.comboBoxMaxCores.currentText()))
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
if 'win32' in sys.platform or 'win64' in sys.platform:
# Auto-startup for Windows
@ -2406,8 +2397,7 @@ class MyForm(QtGui.QMainWindow):
if shared.appdata != '' and self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): # If we are NOT using portable mode now but the user selected that we should...
# Write the keys.dat file to disk in the new location
sqlStoredProcedure('movemessagstoprog')
with open('keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# Write the knownnodes.dat file to disk in the new location
shared.knownNodesLock.acquire()
output = open('knownnodes.dat', 'wb')
@ -2431,8 +2421,7 @@ class MyForm(QtGui.QMainWindow):
os.makedirs(shared.appdata)
sqlStoredProcedure('movemessagstoappdata')
# Write the keys.dat file to disk in the new location
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# Write the knownnodes.dat file to disk in the new location
shared.knownNodesLock.acquire()
output = open(shared.appdata + 'knownnodes.dat', 'wb')
@ -2451,8 +2440,7 @@ class MyForm(QtGui.QMainWindow):
def click_radioButtonBlacklist(self):
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white':
shared.config.set('bitmessagesettings', 'blackwhitelist', 'black')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# self.ui.tableWidgetBlacklist.clearContents()
self.ui.tableWidgetBlacklist.setRowCount(0)
self.loadBlackWhiteList()
@ -2461,8 +2449,7 @@ class MyForm(QtGui.QMainWindow):
def click_radioButtonWhitelist(self):
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black':
shared.config.set('bitmessagesettings', 'blackwhitelist', 'white')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# self.ui.tableWidgetBlacklist.clearContents()
self.ui.tableWidgetBlacklist.setRowCount(0)
self.loadBlackWhiteList()
@ -2534,8 +2521,7 @@ class MyForm(QtGui.QMainWindow):
shared.config.set(str(addressAtCurrentRow), 'mailinglistname', str(
self.dialog.ui.lineEditMailingListName.text().toUtf8()))
self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) # magenta
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
self.rerenderInboxToLabels()
def click_NewAddressDialog(self):
@ -3037,8 +3023,7 @@ class MyForm(QtGui.QMainWindow):
addressAtCurrentRow = str(
self.ui.tableWidgetYourIdentities.item(currentRow, 1).text())
shared.config.set(addressAtCurrentRow, 'enabled', 'true')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
self.ui.tableWidgetYourIdentities.item(
currentRow, 0).setTextColor(QApplication.palette().text().color())
self.ui.tableWidgetYourIdentities.item(
@ -3064,8 +3049,7 @@ class MyForm(QtGui.QMainWindow):
currentRow, 2).setTextColor(QtGui.QColor(128, 128, 128))
if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'):
self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) # magenta
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
shared.reloadMyAddressHashes()
def on_action_YourIdentitiesClipboard(self):
@ -3262,8 +3246,7 @@ class MyForm(QtGui.QMainWindow):
currentRow, 1).text()
shared.config.set(str(addressAtCurrentRow), 'label', str(
self.ui.tableWidgetYourIdentities.item(currentRow, 0).text().toUtf8()))
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
self.rerenderComboBoxSendFrom()
# self.rerenderInboxFromLabels()
self.rerenderInboxToLabels()

View File

@ -129,8 +129,7 @@ class addressGenerator(threading.Thread):
address, 'privSigningKey', privSigningKeyWIF)
shared.config.set(
address, 'privEncryptionKey', privEncryptionKeyWIF)
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# The API and the join and create Chan functionality
# both need information back from the address generator.
@ -244,8 +243,7 @@ class addressGenerator(threading.Thread):
address, 'privSigningKey', privSigningKeyWIF)
shared.config.set(
address, 'privEncryptionKey', privEncryptionKeyWIF)
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
shared.UISignalQueue.put(('writeNewAddressToTable', (
label, address, str(streamNumber))))

View File

@ -150,8 +150,7 @@ class singleWorker(threading.Thread):
try:
shared.config.set(
myAddress, 'lastpubkeysendtime', str(int(time.time())))
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
except:
# The user deleted the address out of the keys.dat file before this
# finished.
@ -236,8 +235,7 @@ class singleWorker(threading.Thread):
try:
shared.config.set(
myAddress, 'lastpubkeysendtime', str(int(time.time())))
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
except:
# The user deleted the address out of the keys.dat file before this
# finished.
@ -332,8 +330,7 @@ class singleWorker(threading.Thread):
try:
shared.config.set(
myAddress, 'lastpubkeysendtime', str(int(time.time())))
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
except Exception as err:
logger.error('Error: Couldn\'t add the lastpubkeysendtime to the keys.dat file. Error message: %s' % err)

View File

@ -86,8 +86,7 @@ class sqlThread(threading.Thread):
shared.config.set('bitmessagesettings', 'sockslisten', 'false')
shared.config.set('bitmessagesettings', 'keysencrypted', 'false')
shared.config.set('bitmessagesettings', 'messagesencrypted', 'false')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# People running earlier versions of PyBitmessage do not have the
# usedpersonally field in their pubkeys table. Let's add it.
@ -98,8 +97,7 @@ class sqlThread(threading.Thread):
self.conn.commit()
shared.config.set('bitmessagesettings', 'settingsversion', '3')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# People running earlier versions of PyBitmessage do not have the
# encodingtype field in their inbox and sent tables or the read field
@ -119,8 +117,7 @@ class sqlThread(threading.Thread):
self.conn.commit()
shared.config.set('bitmessagesettings', 'settingsversion', '4')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
if shared.config.getint('bitmessagesettings', 'settingsversion') == 4:
shared.config.set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(
@ -135,8 +132,7 @@ class sqlThread(threading.Thread):
shared.config.set(
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', '0')
shared.config.set('bitmessagesettings', 'settingsversion', '6')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# From now on, let us keep a 'version' embedded in the messages.dat
# file so that when we make changes to the database, the database
@ -251,8 +247,7 @@ class sqlThread(threading.Thread):
if int(shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte')) == shared.networkDefaultProofOfWorkNonceTrialsPerByte:
shared.config.set('bitmessagesettings','defaultnoncetrialsperbyte', str(shared.networkDefaultProofOfWorkNonceTrialsPerByte * 2))
shared.config.set('bitmessagesettings', 'settingsversion', '7')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# Add a new column to the pubkeys table to store the address version.
# We're going to trash all of our pubkeys and let them be redownloaded.
@ -275,8 +270,7 @@ class sqlThread(threading.Thread):
if not shared.config.has_option('bitmessagesettings', 'identiconsuffix'): # acts as a salt
shared.config.set('bitmessagesettings', 'identiconsuffix', ''.join(random.choice("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") for x in range(12))) # a twelve character pseudo-password to salt the identicons
# Since we've added a new config entry, let's write keys.dat to disk.
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
#Adjusting time period to stop sending messages
if shared.config.getint('bitmessagesettings', 'settingsversion') == 7:
@ -286,8 +280,7 @@ class sqlThread(threading.Thread):
'bitmessagesettings', 'stopresendingafterxmonths', '')
#shared.config.set(
shared.config.set('bitmessagesettings', 'settingsversion', '8')
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
shared.writeKeysFile()
# Add a new table: objectprocessorqueue with which to hold objects
# that have yet to be processed if the user shuts down Bitmessage.

View File

@ -131,8 +131,7 @@ def loadConfig():
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)
shared.writeKeysFile()
_loadTrustedPeer()

View File

@ -20,6 +20,8 @@ import sys
import stat
import threading
import time
import shutil # used for moving the data folder and copying keys.dat
import datetime
from os import path, environ
from struct import Struct
@ -792,6 +794,22 @@ def checkAndShareBroadcastWithPeers(data):
shared.objectProcessorQueueSize += len(data)
objectProcessorQueue.put((objectType,data))
def openKeysFile():
if 'linux' in sys.platform:
subprocess.call(["xdg-open", shared.appdata + 'keys.dat'])
else:
os.startfile(shared.appdata + 'keys.dat')
def writeKeysFile():
fileName = shared.appdata + 'keys.dat'
fileNameBak = fileName + "." + datetime.datetime.now().strftime("%Y%j%H%M%S%f") + '.bak'
# create a backup copy to prevent the accidental loss due to the disk write failure
shutil.copyfile(fileName, fileNameBak)
# write the file
with open(fileName, 'wb') as configfile:
shared.config.write(configfile)
# delete a backup
os.remove(fileNameBak)
helper_startup.loadConfig()
from debug import logger