| 1 | # -*- test-case-name: twisted.conch.test.test_openssh_compat -*- |
|---|
| 2 | # Copyright (c) Twisted Matrix Laboratories. |
|---|
| 3 | # See LICENSE for details. |
|---|
| 4 | |
|---|
| 5 | """ |
|---|
| 6 | Factory for reading openssh configuration files: public keys, private keys, and |
|---|
| 7 | moduli file. |
|---|
| 8 | """ |
|---|
| 9 | |
|---|
| 10 | import os, errno |
|---|
| 11 | |
|---|
| 12 | from twisted.python import log |
|---|
| 13 | from twisted.python.util import runAsEffectiveUser |
|---|
| 14 | |
|---|
| 15 | from twisted.conch.ssh import keys, factory, common |
|---|
| 16 | from twisted.conch.openssh_compat import primes |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | class OpenSSHFactory(factory.SSHFactory): |
|---|
| 21 | dataRoot = '/usr/local/etc' |
|---|
| 22 | moduliRoot = '/usr/local/etc' # for openbsd which puts moduli in a different |
|---|
| 23 | # directory from keys |
|---|
| 24 | |
|---|
| 25 | |
|---|
| 26 | def getPublicKeys(self): |
|---|
| 27 | """ |
|---|
| 28 | Return the server public keys. |
|---|
| 29 | """ |
|---|
| 30 | ks = {} |
|---|
| 31 | for filename in os.listdir(self.dataRoot): |
|---|
| 32 | if filename[:9] == 'ssh_host_' and filename[-8:]=='_key.pub': |
|---|
| 33 | try: |
|---|
| 34 | k = keys.Key.fromFile( |
|---|
| 35 | os.path.join(self.dataRoot, filename)) |
|---|
| 36 | t = common.getNS(k.blob())[0] |
|---|
| 37 | ks[t] = k |
|---|
| 38 | except Exception, e: |
|---|
| 39 | log.msg('bad public key file %s: %s' % (filename, e)) |
|---|
| 40 | return ks |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | def getPrivateKeys(self): |
|---|
| 44 | """ |
|---|
| 45 | Return the server private keys. |
|---|
| 46 | """ |
|---|
| 47 | privateKeys = {} |
|---|
| 48 | for filename in os.listdir(self.dataRoot): |
|---|
| 49 | if filename[:9] == 'ssh_host_' and filename[-4:]=='_key': |
|---|
| 50 | fullPath = os.path.join(self.dataRoot, filename) |
|---|
| 51 | try: |
|---|
| 52 | key = keys.Key.fromFile(fullPath) |
|---|
| 53 | except IOError, e: |
|---|
| 54 | if e.errno == errno.EACCES: |
|---|
| 55 | # Not allowed, let's switch to root |
|---|
| 56 | key = runAsEffectiveUser(0, 0, keys.Key.fromFile, fullPath) |
|---|
| 57 | keyType = keys.objectType(key.keyObject) |
|---|
| 58 | privateKeys[keyType] = key |
|---|
| 59 | else: |
|---|
| 60 | raise |
|---|
| 61 | except Exception, e: |
|---|
| 62 | log.msg('bad private key file %s: %s' % (filename, e)) |
|---|
| 63 | else: |
|---|
| 64 | keyType = keys.objectType(key.keyObject) |
|---|
| 65 | privateKeys[keyType] = key |
|---|
| 66 | return privateKeys |
|---|
| 67 | |
|---|
| 68 | |
|---|
| 69 | def getPrimes(self): |
|---|
| 70 | try: |
|---|
| 71 | return primes.parseModuliFile(self.moduliRoot+'/moduli') |
|---|
| 72 | except IOError: |
|---|
| 73 | return None |
|---|