Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120824866
add-cyrus-user
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
8 KB
Referenced Files
None
Subscribers
None
add-cyrus-user
View Options
#!/usr/bin/perl
#---------------------------------------------------------------------
# This script was designed to ease adding Cyrus-IMAP users for
# a very specific kind of configuration: Postfix+Cyrus, where
#
# mailbox_transport = default (mailbox delivery),
# fallback_transport = cyrus
#
# in such a configuration, an IMAP-user without a local account
# will requires no additional Postfix configuration, but an
# IMAP-user who is also a local user requires that a user-specific
# line be added to the transports file to force the use of the
# 'cyrus' transport. The Postfix-specific configuration can be
# suppressed with the "-no_mta_cfg" flag.
#
# In order for the script to be able to edit the two Postfix config
# files correctly, the files must have 'tag-lines' in them which
# the script uses to orient itself when inserting the new lines.
# The tag-lines are:
#
# /etc/postfix/transport:
# "# add-cyrus-user tag (don't remove this line)"
#
# /etc/postfix/virtual:
# "# Cyrus IMAP users (do not remove this line)"
#
# Without these tag-lines the script will fail.
#
# This script assumes the use of 'sasldb2' authentication.
#
# USAGE:
#
# add-cyrus-user -u <IMAP-username> -p <IMAP-password [options]
#
# options are:
# -q[uota] set quota for mailbox (in KB)
# -part[ition] specify a partition (default = "default")
# -no_mta_cfg do not perform Postfix-specific steps
#
# yes, I know, specifying the password on the command-line is
# insecure. The script will prompt you for the cyrus username
# and password if you do not specify them on the command line.
#
# AUTHOR
#
# Robert Urban <urban@tru64.org>
#
#---------------------------------------------------------------------
use
Cyrus::IMAP::Admin
;
use
FileHandle
;
use
File::Basename
;
use
Fcntl
':flock'
;
# import LOCK_* constants
my
$DEBUG
=
0
;
my
$VERBOSE
=
1
;
my
$mta_cfg
=
1
;
my
$TRANSPORT_FILE
=
'/etc/postfix/transport'
;
my
$VIRTUAL_FILE
=
'/etc/postfix/virtual'
;
my
$user
=
''
;
my
$pass
=
''
;
my
$quota
=
''
;
my
$partition
=
'default'
;
#--------------------------------------------------------------------
# parse arguments
#--------------------------------------------------------------------
while
(
$_
=
shift
)
{
if
(
/^-h/
)
{
usage
();
exit
;
}
elsif
(
/^-u(ser)?$/
)
{
$user
=
shift
;
}
elsif
(
/^-p(ass)?$/
)
{
$pass
=
shift
;
}
elsif
(
/^-part(ition)?/
)
{
$partition
=
shift
;
}
elsif
(
/^-q(uota)?/
)
{
$quota
=
shift
;
if
(
$quota
=~
/^(\d+)m/i
)
{
$quota
*=
1024
;
}
}
elsif
(
/^-no_mta_cfg/
)
{
$mta_cfg
=
0
;
}
else
{
print
"unknown param [$_]\n\n"
;
usage
();
exit
;
}
}
#--------------------------------------------------------------------
# main(), if you like
#--------------------------------------------------------------------
if
(
!
$user
)
{
$user
=
query
(
'Enter new Cyrus user'
);
}
if
(
!
$pass
)
{
$pass
=
query
(
'Enter password for new Cyrus user'
,
1
);
}
if
(
$DEBUG
)
{
print
"USERNAME: $user, PASSWORD: $pass\n"
;
print
"PARTITION = [$partition]\n"
;
print
"QUOTA = [$quota]\n"
;
print
"MTA_CFG = [$mta_cfg]\n"
;
}
$unix_user
=
(
getpwnam
(
$user
))
?
1
:
0
;
$VERBOSE
&&
print
"$user is"
.
(
$unix_user
?
''
:
' NOT'
)
.
" a unix user\n"
;
$client
=
Cyrus::IMAP::Admin
->
new
(
'localhost'
);
defined
(
$client
)
||
die
"failed to get Admin obj."
;
#--------------------------------------------------------------------
# authenticate administrator
#--------------------------------------------------------------------
while
(
1
)
{
$cp
=
getCyrusPassword
();
$ret
=
$client
->
authenticate
(
User
=>
'cyrus'
,
Password
=>
$cp
,
);
if
(
$ret
)
{
last
;
}
print
"Cyrus password incorrect.\n"
;
}
#--------------------------------------------------------------------
# create IMAP mailbox
#--------------------------------------------------------------------
$mbox
=
"user.$user"
;
$VERBOSE
&&
print
"adding CYRUS user [$mbox]\n"
;
if
(
!
$DEBUG
)
{
if
(
!
$client
->
create
(
$mbox
,
$partition
))
{
die
"failed to create mailbox [$mbox]"
;
}
#----------------------------------------------------------------
# give user "cyrus" all permissions on mailbox
#----------------------------------------------------------------
if
(
!
$client
->
setacl
(
$mbox
,
cyrus
=>
'all'
))
{
die
"failed to give cyrus user permissions for [$mbox]"
;
}
}
#--------------------------------------------------------------------
# set quota for mailbox
#--------------------------------------------------------------------
if
(
$quota
&&
!
$DEBUG
)
{
$VERBOSE
&&
print
"setting quota for [$mbox] to $quota\n"
;
if
(
!
$client
->
setquota
(
$mbox
,
STORAGE
=>
$quota
))
{
#die "failed to set quota for [$mbox]";
# does not necessarily need to be fatal
print
"failed to set quota for [$mbox]\n"
;
}
}
#--------------------------------------------------------------------
# create SASL entry
#--------------------------------------------------------------------
setSaslPassword
(
$user
,
$pass
);
#--------------------------------------------------------------------
# the following code is Postfix-specific
#--------------------------------------------------------------------
if
(
$unix_user
&&
$mta_cfg
)
{
addTransportLine
(
$user
);
addVirtualLine
(
$user
);
$VERBOSE
&&
print
"generating new postfix maps\n"
;
myExec
(
"postmap $TRANSPORT_FILE"
);
myExec
(
"postmap $VIRTUAL_FILE"
);
}
exit
;
sub
usage
{
print
<<
_EOF_
;
usage: $0 -u NEWUSER -p NEWPASSWORD [options]
options:
-q[uota] <quota> quota for mailbox in KB, or MB, if suffixed with 'm'
-part[ition] <part> partition on which to create mailbox. none = 'default'
-no_mta_cfg do not perform MTA-specific steps (Postfix)
If "-u USER" or "-p PASS" is not specified on command line, script
will prompt for it/them.
_EOF_
}
sub
query
{
my
$prompt
=
shift
;
my
$echo_off
=
shift
;
print
"${prompt}? "
;
my
$ans
;
do
{
if
(
$echo_off
)
{
system
(
"stty -echo"
);
}
chomp
(
$ans
=
<STDIN>
);
if
(
$echo_off
)
{
system
(
"stty echo"
);
}
if
(
!
$ans
)
{
print
"you must enter something here\n"
;
}
}
while
(
!
length
(
$ans
));
$ans
;
}
sub
setSaslPassword
{
my
(
$user
,
$pass
)
=
@_
;
my
$fh
=
FileHandle
->
new
;
open
(
$fh
,
"|saslpasswd2 -p $user"
)
||
die
"popen to saslpasswd2 failed"
;
print
$fh
"$pass\n"
;
close
(
$fh
);
}
sub
getCyrusPassword
{
print
"Please Enter Cyrus administration password: "
;
system
(
'stty -echo'
);
my
$p
;
chomp
(
$p
=
<STDIN>
);
system
(
'stty echo'
);
print
"\n"
;
$p
;
}
sub
addTransportLine
{
my
$user
=
shift
;
my
$line
=
"${user}\@y42.org\tcyrus:"
;
editFile
(
$TRANSPORT_FILE
,
'add-cyrus-user'
,
$line
);
}
sub
addVirtualLine
{
my
$user
=
shift
;
my
$line
=
"${user}\t${user}\@y42.org"
;
editFile
(
$VIRTUAL_FILE
,
'Cyrus IMAP users'
,
$line
);
}
#-----------------------------------------------------------------
# editFile()
#
# in order to work with flock(), the contents must be kept in
# memory and written back to input file.
#-----------------------------------------------------------------
sub
editFile
{
my
(
$file
,
$tag
,
$line
)
=
@_
;
my
(
@contents
);
$VERBOSE
&&
print
"editing [$file]\n"
;
my
$dn
=
dirname
(
$file
);
my
$bn
=
basename
(
$file
);
my
$fh
=
FileHandle
->
new
(
"+<$file"
);
defined
(
$fh
)
||
die
"open $file for reading"
;
lockFile
(
$fh
);
my
$state
=
'looking'
;
while
(
<$fh>
)
{
if
(
$state
eq
'found'
)
{
if
(
/^\s*#/
)
{
push
(
@contents
,
$_
);
next
;
}
push
(
@contents
,
"$line\n"
);
push
(
@contents
,
$_
);
$state
=
'copyrest'
;
}
elsif
(
$state
eq
'looking'
)
{
push
(
@contents
,
$_
);
if
(
/$tag/
)
{
$state
=
'found'
;
}
}
else
{
# state = copyrest
push
(
@contents
,
$_
);
}
}
if
(
$state
eq
'looking'
)
{
die
"tag [$tag] not found in file [$file]"
;
}
if
(
$DEBUG
)
{
unlockFile
(
$fh
);
return
;
}
# rewind file-pointer
seek
(
$fh
,
0
,
0
)
||
die
"seek"
;
truncate
(
$fh
,
0
)
||
die
"truncate"
;
# write new contents
foreach
(
@contents
)
{
print
$fh
$_
;
}
unlockFile
(
$fh
);
$fh
->
close
;
}
sub
myRename
{
my
(
$old
,
$new
)
=
@_
;
(
$VERBOSE
>
1
)
&&
print
"rename: $old --> $new\n"
;
$DEBUG
&&
return
;
if
(
!
rename
(
$old
,
$new
))
{
die
"rename of $old to $new failed"
;
}
}
sub
myExec
{
my
$cmd
=
shift
;
(
$VERBOSE
>
1
)
&&
print
"CMD: $cmd\n"
;
$DEBUG
&&
return
;
return
!
system
(
$cmd
);
}
sub
unlockFile
{
my
$fh
=
shift
;
$DEBUG
&&
print
"unlocking file\n"
;
flock
(
$fh
,
LOCK_UN
)
||
die
"flock lock_un ($!)"
;
}
sub
lockFile
{
my
$fh
=
shift
;
$DEBUG
&&
print
"locking file\n"
;
flock
(
$fh
,
LOCK_EX
)
||
die
"flock lock_ex ($!)"
;
}
File Metadata
Details
Attached
Mime Type
text/x-perl
Expires
Fri, Apr 24, 10:29 AM (1 d, 21 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
b4/46/5a857d9108005921e34e74e57fe9
Default Alt Text
add-cyrus-user (8 KB)
Attached To
Mode
R111 cyrus-imapd
Attached
Detach File
Event Timeline