Advertisement
Guest User

Untitled

a guest
Mar 4th, 2017
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.10 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. # Simple script for exporting gnome2 (seahorse) keyrings,
  4. # and re-importing on another machine.
  5.  
  6. # Usage:
  7. #
  8. # 1) Export:
  9. #
  10. # gnome_keyring_import_export.py export somefile.json
  11. #
  12. #
  13. # Please note - this dumps all your passwords *unencrypted*
  14. # into somefile.json
  15. #
  16. # 2) Import:
  17. #
  18. # gnome_keyring_import_export.py import somefile.json
  19. #
  20. # OR
  21. #
  22. # cat somefile.json | gnome_keyring_import_export.py import
  23. #
  24. # This attempts to be intelligent about not duplicating
  25. # secrets already in the keyrings - see messages.
  26. #
  27. # However, if you are moving machines, sometimes an application
  28. # name changes (e.g. "chrome-12345" -> "chrome-54321") so
  29. # you might need to do some manual fixes on somefile.json first.
  30. #
  31. # Please make BACKUP copies of your existing keyring files
  32. # before importing into them, in case anything goes wrong.
  33. # They are normally found in:
  34. #
  35. # ~/.gnome2/keyrings
  36. # ~/.local/share/keyrings
  37. #
  38. #
  39. # 3) Export Chrome passwords to Firefox
  40. #
  41. # This takes Chrome passwords stored in the Gnome keyring manager and creates a
  42. # file than can be imported by the Firefox "Password Exporter" extension:
  43. # https://addons.mozilla.org/en-US/firefox/addon/password-exporter/
  44. #
  45. # gnome_keyring_import_export.py export_chrome_to_firefox somefile.xml
  46. #
  47.  
  48.  
  49.  
  50. import json
  51. import sys
  52. import urlparse
  53.  
  54. import lxml.etree
  55. from lxml.etree import Element
  56. import pygtk
  57. pygtk.require('2.0')
  58. import gtk # sets app name
  59. import gnomekeyring
  60.  
  61. def mk_copy(item):
  62. c = item.copy()
  63. c['attributes'] = c['attributes'].copy()
  64. return c
  65.  
  66. def remove_insignificant_data(item, ignore_secret=False):
  67. item.pop('mtime', None)
  68. item.pop('ctime', None)
  69. item.pop('mtime', None)
  70. item['attributes'].pop('date_created', None)
  71. if ignore_secret:
  72. item.pop('secret', None)
  73.  
  74. def items_roughly_equal(item1, item2, ignore_secret=False):
  75. c1 = mk_copy(item1)
  76. c2 = mk_copy(item2)
  77.  
  78. remove_insignificant_data(c1, ignore_secret=ignore_secret)
  79. remove_insignificant_data(c2, ignore_secret=ignore_secret)
  80.  
  81. return c1 == c2
  82.  
  83. def export_keyrings(to_file):
  84. file(to_file, "w").write(json.dumps(get_gnome_keyrings(), indent=2))
  85.  
  86. def get_gnome_keyrings():
  87. keyrings = {}
  88. for keyring_name in gnomekeyring.list_keyring_names_sync():
  89. keyring_items = []
  90. keyrings[keyring_name] = keyring_items
  91. for id in gnomekeyring.list_item_ids_sync(keyring_name):
  92. item = get_item(keyring_name, id)
  93. if item is not None:
  94. keyring_items.append(item)
  95.  
  96. return keyrings
  97.  
  98. def export_chrome_to_firefox(to_file):
  99. """
  100. Finds Google Chrome passwords and exports them to an XML file that can be
  101. imported by the Firefox extension "Password Exporter"
  102. """
  103. keyrings = get_gnome_keyrings()
  104. items = []
  105. item_set = set()
  106. for keyring_name, keyring_items in keyrings.items():
  107. for item in keyring_items:
  108. if (not item['display_name'].startswith('http')
  109. and not item['attributes'].get('application', '').startswith('chrome')):
  110. continue
  111. items.append(item)
  112.  
  113. attribs = item['attributes']
  114. item_def = (attribs['signon_realm'],
  115. attribs['username_value'],
  116. attribs['action_url'],
  117. attribs['username_element'],
  118. attribs['password_element'],
  119. )
  120. if item_def in item_set:
  121. sys.stderr.write("Warning: duplicate found for %rnn" % (item_def,))
  122. item_set.add(item_def)
  123.  
  124. xml = items_to_firefox_xml(items)
  125. file(to_file, "w").write(xml)
  126.  
  127. def items_to_firefox_xml(items):
  128. doc = Element('xml')
  129. entries = Element('entries',
  130. dict(ext="Password Exporter", extxmlversion="1.1", type="saved", encrypt="false"))
  131. doc.append(entries)
  132. for item in items:
  133. attribs = item['attributes']
  134. url = urlparse.urlparse(attribs['signon_realm'])
  135. entries.append(Element('entry',
  136. dict(host=url.scheme + "://" + url.netloc,
  137. user=attribs['username_value'],
  138. password=item['secret'],
  139. formSubmitURL=attribs['action_url'],
  140. httpRealm=url.path.lstrip('/'),
  141. userFieldName=attribs['username_element'],
  142. passFieldName=attribs['password_element'],
  143. )))
  144. return lxml.etree.tostring(doc, pretty_print=True)
  145.  
  146. def get_item(keyring_name, id):
  147. try:
  148. item = gnomekeyring.item_get_info_sync(keyring_name, id)
  149. except gnomekeyring.IOError as e:
  150. sys.stderr.write("Could not examine item (%s, %s): %sn" % (keyring_name, id, e.message))
  151. return None
  152. return {
  153. 'display_name': item.get_display_name(),
  154. 'secret': item.get_secret(),
  155. 'mtime': item.get_mtime(),
  156. 'ctime': item.get_ctime(),
  157. 'attributes': gnomekeyring.item_get_attributes_sync(keyring_name, id),
  158. }
  159.  
  160.  
  161. def fix_attributes(d):
  162. return {str(k): str(v) if isinstance(v, unicode) else v for k, v in d.items()}
  163.  
  164.  
  165. def import_keyrings(file_p, file_name):
  166. keyrings = json.loads(file_p.read())
  167.  
  168. for keyring_name, keyring_items in keyrings.items():
  169. try:
  170. existing_ids = gnomekeyring.list_item_ids_sync(keyring_name)
  171. except gnomekeyring.NoSuchKeyringError:
  172. sys.stderr.write("No keyring '%s' found. Please create this keyring first" % keyring_name)
  173. sys.exit(1)
  174.  
  175. existing_items = [get_item(keyring_name, id) for id in existing_ids]
  176. existing_items = [i for i in existing_items if i is not None]
  177.  
  178. for item in keyring_items:
  179. if any(items_roughly_equal(item, i) for i in existing_items):
  180. print "Skipping %s because it already exists" % item['display_name']
  181. else:
  182. nearly = [i for i in existing_items if items_roughly_equal(i, item, ignore_secret=True)]
  183. if nearly:
  184. print "Existing secrets found for '%s'" % item['display_name']
  185. for i in nearly:
  186. print " " + i['secret']
  187.  
  188. print "So skipping value from '%s':" % file_name
  189. print " " + item['secret']
  190. else:
  191. schema = item['attributes']['xdg:schema']
  192. item_type = None
  193. if schema == u'org.freedesktop.Secret.Generic':
  194. item_type = gnomekeyring.ITEM_GENERIC_SECRET
  195. elif schema == u'org.gnome.keyring.Note':
  196. item_type = gnomekeyring.ITEM_NOTE
  197. elif schema == u'org.gnome.keyring.NetworkPassword':
  198. item_type = gnomekeyring.ITEM_NETWORK_PASSWORD
  199.  
  200. if item_type is not None:
  201. item_id = gnomekeyring.item_create_sync(keyring_name,
  202. item_type,
  203. item['display_name'],
  204. fix_attributes(item['attributes']),
  205. item['secret'],
  206. False)
  207. print "Copying secret %s" % item['display_name']
  208. else:
  209. print "Can't handle secret '%s' of type '%s', skipping" % (item['display_name'], schema)
  210.  
  211.  
  212. if __name__ == '__main__':
  213. if len(sys.argv) == 3:
  214. if sys.argv[1] == "export":
  215. export_keyrings(sys.argv[2])
  216. if sys.argv[1] == "import":
  217. file_name = sys.argv[2]
  218. import_keyrings(file(file_name), file_name)
  219. if sys.argv[1] == "export_chrome_to_firefox":
  220. export_chrome_to_firefox(sys.argv[2])
  221. elif len(sys.argv) == 2 and sys.argv[1] == "import" and not sys.stdin.isatty():
  222. import_keyrings(sys.stdin, "stdin")
  223.  
  224. else:
  225. print "See source code for usage instructions"
  226. sys.exit(1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement