Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120824968
cyr_deny.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None
cyr_deny.c
View Options
/* cyr_deny.c - tool to manipulate the deny database
*
* Copyright (c) 1994-2012 Carnegie Mellon University. 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.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Carnegie Mellon University
* Center for Technology Transfer and Enterprise Creation
* 4615 Forbes Avenue
* Suite 302
* Pittsburgh, PA 15213
* (412) 268-7393, fax: (412) 268-7395
* innovation@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include
<config.h>
#ifdef HAVE_UNISTD_H
#include
<unistd.h>
#endif
#include
<stdlib.h>
#include
<stdio.h>
#include
<string.h>
#include
<ctype.h>
#include
<fcntl.h>
#include
<sys/stat.h>
#include
<syslog.h>
#include
<errno.h>
#include
<signal.h>
#include
"global.h"
#include
"exitcodes.h"
#include
"libcyr_cfg.h"
#include
"proc.h"
#include
"userdeny.h"
#include
"imap/imap_err.h"
#include
"util.h"
#include
"ptrarray.h"
#include
"xmalloc.h"
static
void
usage
(
void
)
{
fprintf
(
stderr
,
"Usage: cyr_deny [-C <altconfig>] [ -s services ] [ -m message ] user
\n
"
);
fprintf
(
stderr
,
" cyr_deny [-C <altconfig>] -a user
\n
"
);
fprintf
(
stderr
,
" cyr_deny [-C <altconfig>] -l
\n
"
);
exit
(
EC_USAGE
);
}
static
int
list_one
(
const
char
*
user
,
const
char
*
services
,
const
char
*
message
,
void
*
rock
__attribute__
((
unused
)))
{
printf
(
"%-30s %-20s %s
\n
"
,
user
,
services
,
message
);
return
0
;
}
struct
kill_rock
{
const
char
*
user
;
ptrarray_t
pids
;
};
/*
* We use proc_foreach() to kill any existing servers which are serving
* the user. There are two problems with this approach.
*
* - proc_foreach() reads a directory full of files, which is inherently racy
*
* - the proc file does not contain the service identifier of the process that
* wrote it; the only mapping between those and pids is in those processes
* themselves and in the master process.
*
* The first problem we can live with, the raciness is no worse than
* running 'cyr_info proc' and grepping the results.
*
* The second problem means that we have no way cleanly to support the
* existing userdeny feature of denying users access to only some services.
* Without a clear idea of which service a pid represents, we cannot helpfully
* kill the existing processes for only some of the services. Instead we have
* to kill all the processes for the user, and hope any others will reconnect.
*/
static
int
gather_one
(
int
pid
,
const
char
*
servicename
__attribute__
((
unused
)),
const
char
*
clienthost
__attribute__
((
unused
)),
const
char
*
userid
,
const
char
*
mailbox
__attribute__
((
unused
)),
void
*
rock
)
{
struct
kill_rock
*
kr
=
(
struct
kill_rock
*
)
rock
;
if
(
!
strcmp
(
userid
,
kr
->
user
))
ptrarray_append
(
&
kr
->
pids
,
xmemdup
(
&
pid
,
sizeof
(
pid
)));
return
0
;
}
static
void
kill_existing_services
(
const
char
*
user
)
{
struct
kill_rock
kr
=
{
NULL
,
PTRARRAY_INITIALIZER
};
int
delay
=
1
;
int
i
;
int
*
pidp
;
int
sig
;
int
prejudice
=
0
;
int
probing
=
0
;
int
r
;
kr
.
user
=
user
;
proc_foreach
(
gather_one
,
&
kr
);
/*
* Send a graceful shutdown message to all the processes and wait
* for them to die. This is a poor approximation of the correct
* behaviour, which can only be done in the master process (but we
* currently have no way to tell it to do so).
*/
for
(;;)
{
/* send all the pids a signal */
for
(
i
=
0
;
i
<
kr
.
pids
.
count
;
i
++
)
{
pidp
=
(
int
*
)
kr
.
pids
.
data
[
i
];
sig
=
(
probing
?
0
:
(
prejudice
?
SIGKILL
:
SIGTERM
));
r
=
kill
(
*
pidp
,
sig
);
if
(
r
<
0
)
{
/* gone (yay!) or some error */
ptrarray_remove
(
&
kr
.
pids
,
i
);
free
(
pidp
);
continue
;
}
}
if
(
!
kr
.
pids
.
count
)
break
;
probing
=
1
;
sleep
(
delay
);
delay
*=
2
;
if
(
delay
>
8
)
{
if
(
prejudice
++
)
{
syslog
(
LOG_ALERT
,
"cannot kill some processes even with SIGKILL"
);
break
;
}
delay
=
1
;
probing
=
0
;
}
}
ptrarray_fini
(
&
kr
.
pids
);
}
int
main
(
int
argc
,
char
**
argv
)
{
int
opt
;
enum
{
DENY
,
ALLOW
,
LIST
}
mode
=
DENY
;
const
char
*
alt_config
=
NULL
;
const
char
*
user
=
NULL
;
const
char
*
message
=
NULL
;
const
char
*
services
=
NULL
;
int
r
;
if
((
geteuid
())
==
0
&&
(
become_cyrus
()
!=
0
))
{
fatal
(
"must run as the Cyrus user"
,
EC_USAGE
);
}
while
((
opt
=
getopt
(
argc
,
argv
,
"C:alm:s:"
))
!=
EOF
)
{
switch
(
opt
)
{
case
'C'
:
/* alt config file */
alt_config
=
optarg
;
break
;
case
'a'
:
if
(
mode
!=
DENY
)
usage
();
mode
=
ALLOW
;
break
;
case
'l'
:
if
(
mode
!=
DENY
)
usage
();
mode
=
LIST
;
break
;
case
'm'
:
message
=
optarg
;
break
;
case
's'
:
services
=
optarg
;
break
;
default
:
usage
();
break
;
}
}
if
(
mode
!=
DENY
&&
(
message
||
services
))
usage
();
if
(
mode
==
LIST
)
{
if
(
optind
!=
argc
)
usage
();
}
else
{
if
(
optind
!=
argc
-1
)
usage
();
user
=
argv
[
optind
];
}
cyrus_init
(
alt_config
,
"cyr_deny"
,
0
,
0
);
denydb_init
(
0
);
r
=
denydb_open
(
/*create*/
(
mode
==
DENY
));
if
(
r
)
{
if
(
mode
!=
DENY
&&
r
==
IMAP_NOTFOUND
)
r
=
0
;
else
fprintf
(
stderr
,
"cyr_deny: failed to open deny db: %s
\n
"
,
error_message
(
r
));
goto
out
;
}
switch
(
mode
)
{
case
ALLOW
:
r
=
denydb_delete
(
user
);
if
(
r
)
fprintf
(
stderr
,
"cyr_deny: failed to allow access for %s: %s
\n
"
,
user
,
error_message
(
r
));
break
;
case
DENY
:
r
=
denydb_set
(
user
,
services
,
message
);
if
(
r
)
fprintf
(
stderr
,
"cyr_deny: failed to deny access for %s: %s
\n
"
,
user
,
error_message
(
r
));
else
kill_existing_services
(
user
);
break
;
case
LIST
:
printf
(
"%-30s %-20s %s
\n
"
,
"Username"
,
"Service(s)"
,
"Message"
);
r
=
denydb_foreach
(
list_one
,
NULL
);
if
(
r
)
fprintf
(
stderr
,
"cyr_deny: failed to list entries: %s
\n
"
,
error_message
(
r
));
break
;
}
denydb_close
();
out
:
denydb_done
();
return
!!
r
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Apr 24, 10:30 AM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18780669
Default Alt Text
cyr_deny.c (7 KB)
Attached To
Mode
R111 cyrus-imapd
Attached
Detach File
Event Timeline