#!@RUBY@
#
# dtcpauth, manipulate POP authorization DB
#
#
# Copyright (c) 2002-2004 Hajimu UMEMOTO <ume@mahoroba.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $Mahoroba: src/dtcp/dtcpauth.rb,v 1.4 2005/12/28 08:33:06 ume Exp $
#
require 'getopts'
require 'dbm'
require 'etc'
POPAUTHUID = 'pop'
POPAUTHDB = '@POPAUTHDB@'
#$debug = true
def usage
$stderr.print "usage: #{File.basename($0)} [--init] [--list [user | ALL]] [--delete user] [--user user [password]]\n"
end
def errmsg(msg)
$stderr.print "#{File.basename($0)}: #{msg}\n"
end
class PopAuthDb
def each
@f.each { |user, password|
yield(user.chop, obscure(strip_null(password)))
}
end
def user(user)
key = user + "\0"
if !@f.has_key?(key)
errmsg("no entry for \"#{user}\" in POP authentication DB")
return false
end
return obscure(strip_null(@f[key]))
end
def set(user, password)
@f[user + "\0"] = obscure(password) + "\0\0"
end
def delete(user)
key = user + "\0"
if !@f.has_key?(key)
errmsg("User '#{user}' not found in authentication database")
return false
end
@f.delete(key)
return true
end
def close
@f.close
@f = nil
Process.euid = @origuid
end
def opend?
if @f
return true
end
return false
end
private
def initialize(mode = nil)
pw = Etc.getpwnam(POPAUTHUID)
if !pw
errmsg("no user named #{POPAUTHUID}")
return
end
@origuid = Process.euid
begin
Process.euid = pw[2]
rescue
errmsg("no permission to asscess POP authentication DB")
return
end
@f = DBM.open(POPAUTHDB, mode)
if !@f
if mode
errmsg("no password database found")
end
Process.euid = @origuid
return
end
end
def strip_null(p)
while p.length > 0 && p[p.length - 1] == 0
p = p[0, p.length - 1]
end
return p
end
def obscure(p)
for i in 0 .. p.length - 1
p[i] = [p[i] ^ 0xff].pack('C')
end
return p
end
end
def getpassword(prompt = "Password")
password = ''
while true
open('/dev/tty', 'r') { |tty|
system("stty -echo")
$stderr.print "#{prompt}: "
password = tty.readline.chop!
}
system("stty sane")
$stderr.print "\n"
if password.size > 4
break
end
print "Please use a longer password.\n"
end
return password
end
def initdb
popauthdb = PopAuthDb.new
if popauthdb.opend?
popauthdb.close
errmsg("there is POP authentication DB already")
return false
end
popauthdb = PopAuthDb.new(0600)
if popauthdb.opend?
return false
end
popauthdb.close
return true
end
def listuser(popauthdb, user)
if user == 'ALL'
popauthdb.each { |u, p|
if $debug
print "#{u.ljust(16)}: #{p}\n"
else
print "#{u.ljust(16)}: APOP\n"
end
}
else
p = popauthdb.user(user)
if p
if $debug
print "#{user.ljust(16)}: #{p}\n"
else
print "#{user.ljust(16)}: APOP\n"
end
end
end
return true
end
def setuser(popauthdb, user, password)
if !password
print "Changing only APOP password for #{user}.\n"
password = getpassword("New Password")
password2 = getpassword("Retype new Password")
if password != password2
print "Mismatch -- password unchanged.\n"
return false
end
end
popauthdb.set(user, password)
return true
end
if !getopts('dilu', 'delete', 'init', 'list', 'user')
usage()
exit 1
end
$OPT_delete = true if $OPT_d
$OPT_init = true if $OPT_i
$OPT_list = true if $OPT_l
$OPT_user = true if $OPT_u
optnum = 0
[$OPT_delete, $OPT_init, $OPT_list, $OPT_user].each { |opt|
if opt
optnum += 1
end
}
if optnum != 1
usage()
exit 1
end
if $OPT_init
r = initdb()
else
if ARGV.length < 1
usage()
exit 1
end
popauthdb = PopAuthDb.new
if !popauthdb.opend?
exit 1
end
if $OPT_list
r = listuser(popauthdb, ARGV[0])
elsif $OPT_user
r = setuser(popauthdb, ARGV[0], ARGV[1])
elsif $OPT_delete
r = popauthdb.delete(ARGV[0])
end
popauthdb.close
end
if !r
exit 1
end
exit 0
syntax highlighted by Code2HTML, v. 0.9.1