2

For migrating from the de-factor closed source glftpd 2.01 to proftpd I need to migrate password hashes of the user accounts from glftpd to proftpd. Reading about the topic I figured mod_sql_passwd should do the trick.

I therefore set up my proftpd server like this:

<global>
    SQLBackend              mysql
    SQLAuthTypes            Crypt
    SQLAuthenticate         users groups

    SQLConnectInfo  testdbuser@testdbhost testdb

    SQLUserInfo     ftpuser userid passwd uid gid homedir shell
    SQLGroupInfo    ftpgroup groupname gid members
    SQLMinID        500
    CreateHome on

[...]

    RootLogin off
    RequireValidShell off
    DefaultRoot ~
</global>

DefaultServer                   off
ServerType                      standalone

<VirtualHost 0.0.0.0>
    Port 21
    PassivePorts 10000 10250
    MasqueradeAddress 123.123.123.123

    SQLAuthTypes pbkdf2
    SQLPasswordPBKDF2 sha1 100 40

    SQLNamedQuery get-user-salt SELECT "salt FROM ftpuser WHERE userid = '%{0}'"
    SQLPasswordUserSalt sql:/get-user-salt Prepend
</VirtualHost>

The hashes in the glftpd passwd look like this:

$7e8ab0c7$bf044082ab83875eeb3a2158cd6253f8e88f40cf

The database looks like this (CSV representation):

"id","userid","passwd","salt","uid","gid","homedir","shell","count","accessed","modified"
"1","test","bf044082ab83875eeb3a2158cd6253f8e88f40cf","7e8ab0c7","5500","5500","/data/test","/sbin/nologin","20","2020-03-31 20:02:45","2020-03-25 16:30:49"

All configurations so far result in:

USER test (Login failed): No such user found

While in fact the user exists and by changing the hash to a Crypt() Bcrypt-style hash, a login succeeds.

Questions/problems:

  • it is unclear how many iterations are used for glftpd's hashes from the little source available of glftpd, an iteration value of 100 can be derived
  • it is unclear if the dollar sign should be prepended to the salt and the hash values or not
  • proftpd with DebugLevel 10 yields no other information than "USER test (Login failed): No such user found", though, with a normal Crypt() Bcrypt-type hash it works flawlessly (see the top of the config)
  • it is unclear how the glftpd 2.01 hashes are constructed, I tried SQLPasswordOptions HashPassword HashSalt which seemed the most logical, without success [²]

It would be great to hear from someone how had a similar task and made some experience with this kind of migration. Additional clues that help solving this topic are also welcome.

[¹] https://glftpd.io/files/glftpd-LNX_2.01.tgz (bin/sources/PassChk/passhk.c) glftpd 2.01 "passchk.c":

    PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), real_salt, SHA_SALT_LEN, 100,
               mdlen, md);

[²] http://www.proftpd.org/docs/contrib/mod_sql_passwd.html#Transformations

M. Schmidt
  • 193
  • 14

1 Answers1

1

Resolved:

<global>
    SQLBackend              mysql
    SQLAuthTypes            Crypt
    SQLAuthenticate         users groups

    SQLConnectInfo  testdbuser@testdbhost testdb

    SQLUserInfo     ftpuser userid passwd uid gid homedir shell
    SQLGroupInfo    ftpgroup groupname gid members
    SQLMinID        500
    CreateHome on

[...]

    RootLogin off
    RequireValidShell off
    DefaultRoot ~
</global>

DefaultServer                   off
ServerType                      standalone
Port 0

<VirtualHost 0.0.0.0>
    Port 21
    PassivePorts 10000 10250
    MasqueradeAddress 123.123.123.123

    SQLPasswordEngine on

    SQLAuthTypes pbkdf2
    SQLPasswordPBKDF2 sha1 100 20

    SQLNamedQuery get-user-salt SELECT "salt FROM ftpuser WHERE userid = '%{0}'"
    SQLPasswordUserSalt sql:/get-user-salt Prepend

    SQLPasswordEncoding hex
    SQLPasswordSaltEncoding hex

    SQLPasswordOptions HashEncodeSalt HashEncodePassword
</VirtualHost>

Had to

  • define the lowercase character hex encoding with SQLPasswordEncoding and SQLPasswordSaltEncoding
  • correct the output length from 40 to 20 bytes with SQLPasswordPBKDF2
  • add the SQLPasswordOptions to instruct the module to first decode the hex values and then use the hashes
  • enable the SQLPasswordEngine
M. Schmidt
  • 193
  • 14