雑記

2000|01|
2003|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|
2007|01|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|09|11|
2009|02|03|05|06|07|08|10|11|12|
2010|01|03|04|05|06|07|08|09|10|
2011|05|06|09|10|
2012|03|07|09|12|
2013|01|02|04|05|07|08|10|11|
2014|04|05|08|10|12|
2015|01|05|
2016|09|
2024|06|
2025|01|

2015-01-27 [長年日記]

[Ruby] Net::FTP でワンタイムパスワード(OTP)認証

7行コードを追加するだけであら不思議。Net::FtpがOTP対応に。

という訳でレッツモンキー!!

require 'net/ftp'
{~orangered:require 'otp'~}

module Net
    class FTP
        {~orangered:CHALLENGE_RE = /otp-md5 ([0-9]+) ([a-zA-Z0-9]+)\s+/~}

        def login(user = "anonymous", passwd = nil, acct = nil)
            if user == "anonymous" and passwd == nil
                passwd = "anonymous@"
            end

            resp = ""
            synchronize do
                resp = sendcmd('USER ' + user)
                if resp[0] == ?3
                    raise FTPReplyError, resp if passwd.nil?
                    {~orangered:m = resp.match(CHALLENGE_RE)~}
                    {~orangered:unless m.nil?~}
                        {~orangered:otp = OTP.new(m[1].to_i, m[2], passwd, "md5")~}
                        {~orangered:passwd =  otp.to_s~}
                    {~orangered:end~}
                    resp = sendcmd('PASS ' + passwd)
                end
                if resp[0] == ?3
                    raise FTPReplyError, resp if acct.nil?
                    resp = sendcmd('ACCT ' + acct)
                end
            end
            if resp[0] != ?2
                raise FTPReplyError, resp
            end
            @welcome = resp
            send_type_command
            @logged_in = true
        end
    end
end

あとは普通に使うだけ。

ftp = Net::FTP.new("host name")
ftp.login("user","password")
ftp.passive = true
files = ftp.list
files.each do |f|
 puts f
end

はたして需要は有るのか。