Fixing issue #262 & #263, bad keyfile permissions. #262

Merged
fiatflux merged 12 commits from keyfile_perm_fix into master 2013-07-15 21:51:28 +02:00
Showing only changes of commit 1ed34b0084 - Show all commits

View File

@ -202,30 +202,35 @@ def reloadMyAddressHashes():
hasEnabledKeys = False hasEnabledKeys = False
for addressInKeysFile in configSections: for addressInKeysFile in configSections:
if addressInKeysFile <> 'bitmessagesettings': if addressInKeysFile <> 'bitmessagesettings':
hasEnabledKeys = True
isEnabled = config.getboolean(addressInKeysFile, 'enabled') isEnabled = config.getboolean(addressInKeysFile, 'enabled')
if isEnabled: if isEnabled:
if keyfileSecure: hasEnabledKeys = True
status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile) status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile)
if addressVersionNumber == 2 or addressVersionNumber == 3: if addressVersionNumber == 2 or addressVersionNumber == 3:
# 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( privEncryptionKey = decodeWalletImportFormat(
config.get(addressInKeysFile, 'privencryptionkey')).encode('hex') config.get(addressInKeysFile, 'privencryptionkey')).encode('hex')
if len(privEncryptionKey) == 64:#It is 32 bytes encoded as 64 hex characters if len(privEncryptionKey) == 64:#It is 32 bytes encoded as 64 hex characters
myECCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey) myECCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey)
myAddressesByHash[hash] = addressInKeysFile myAddressesByHash[hash] = addressInKeysFile
else:
sys.stderr.write('Error in reloadMyAddressHashes: Can\'t handle address versions other than 2 or 3.\n') if not keyfileSecure:
else:
# Insecure keyfile permissions. Disable key. # Insecure keyfile permissions. Disable key.
config.set(addressInKeysFile, 'enabled', 'false') config.set(addressInKeysFile, 'enabled', 'false')
try: else:
sys.stderr.write('Error in reloadMyAddressHashes: Can\'t handle address '
'versions other than 2 or 3.\n')
if not keyfileSecure: if not keyfileSecure:
fixSensitiveFilePermissions(appdata + 'keys.dat', hasEnabledKeys)
if hasEnabledKeys:
try:
with open(appdata + 'keys.dat', 'wb') as keyfile: with open(appdata + 'keys.dat', 'wb') as keyfile:
config.write(keyfile) config.write(keyfile)
except: except:
print 'Failed to disable vulnerable keyfiles.' print 'Failed to disable vulnerable keys.'
raise raise
def reloadBroadcastSendersForWhichImWatching(): def reloadBroadcastSendersForWhichImWatching():
@ -318,49 +323,45 @@ def fixPotentiallyInvalidUTF8Data(text):
output = 'Part of the message is corrupt. The message cannot be displayed the normal way.\n\n' + repr(text) output = 'Part of the message is corrupt. The message cannot be displayed the normal way.\n\n' + repr(text)
return output 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): def checkSensitiveFilePermissions(filename):
if sys.platform == 'win32': if sys.platform == 'win32':
# TODO: This might deserve extra checks by someone familiar with # TODO: This might deserve extra checks by someone familiar with
# Windows systems. # Windows systems.
fileSecure = True return True
else: else:
fileSecure = secureFilePermissions(filename) present_permissions = os.stat(filename)[0]
if not fileSecure: 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:
print print
print '******************************************************************' print '******************************************************************'
print '** !! WARNING !! **' print '** !! WARNING !! **'
print '******************************************************************' print '******************************************************************'
print '** Possibly major security problem: **' print '** Possibly major security problem: **'
print '** Your keyfiles were vulnerable to being read by other users **' print '** Your keyfile was vulnerable to being read by other users **'
print '** (including some untrusted daemons). You may wish to consider **' print '** (including some untrusted daemons). You may wish to consider **'
print '** generating new keys and discontinuing use of your old ones. **' print '** generating new keys and discontinuing use of your old ones. **'
print '** Your private keys have been disabled for your security, but **' print '** Your private keys have been disabled for your security, but **'
print '** you may re-enable them using the "Your Identities" tab in **' print '** you may re-enable them using the "Your Identities" tab in **'
print '** the default GUI or by modifying keys.dat such that your keys **' print '** the default GUI or by modifying keys.dat such that your keys **'
print '** show "enabled = true". **' print '** show "enabled = true". **'
else:
print '******************************************************************'
print '** !! WARNING !! **'
print '******************************************************************'
print '** Possibly major security problem: **'
print '** Your keyfile was vulnerable to being read by other users. **'
print '** Fortunately, you don\'t have any enabled keys, but be aware **'
print '** that any disabled keys may have been compromised by malware **'
print '** running by other users and that you should reboot before **'
print '** generating any new keys. **'
try: try:
fixSensitiveFilePermissions(filename)
print '** The problem has been automatically fixed. **'
print '******************************************************************'
print
except Exception, e:
print '** Could NOT automatically fix permissions. **'
print '******************************************************************'
print
raise
return fileSecure
# 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 secureFilePermissions(filename):
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):
present_permissions = os.stat(filename)[0] present_permissions = os.stat(filename)[0]
disallowed_permissions = stat.S_IRWXG | stat.S_IRWXO disallowed_permissions = stat.S_IRWXG | stat.S_IRWXO
allowed_permissions = ((1<<32)-1) ^ disallowed_permissions allowed_permissions = ((1<<32)-1) ^ disallowed_permissions
@ -368,3 +369,12 @@ def fixSensitiveFilePermissions(filename):
allowed_permissions & present_permissions) allowed_permissions & present_permissions)
os.chmod(filename, new_permissions) os.chmod(filename, new_permissions)
print '** The file permissions have been automatically fixed. **'
print '******************************************************************'
print
except Exception, e:
print '** Could NOT automatically fix permissions. **'
print '******************************************************************'
print
raise