Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120827176
auth_unix.c
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
auth_unix.c
View Options
/* auth_unix.c -- Unix passwd file authorization
*
* Copyright (c) 1994-2008 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>
#include
<stdlib.h>
#include
<pwd.h>
#include
<grp.h>
#include
<ctype.h>
#include
<string.h>
#include
"auth.h"
#include
"libcyr_cfg.h"
#include
"xmalloc.h"
#include
"strarray.h"
#include
"util.h"
struct
auth_state
{
char
userid
[
81
];
strarray_t
groups
;
};
static
struct
auth_state
auth_anonymous
=
{
"anonymous"
,
STRARRAY_INITIALIZER
};
/*
* Determine if the user is a member of 'identifier'
* Returns one of:
* 0 User does not match identifier
* 1 identifier matches everybody
* 2 User is in the group that is identifier
* 3 User is identifer
*/
static
int
mymemberof
(
struct
auth_state
*
auth_state
,
const
char
*
identifier
)
{
int
i
;
if
(
!
auth_state
)
auth_state
=
&
auth_anonymous
;
if
(
strcmp
(
identifier
,
"anyone"
)
==
0
)
return
1
;
if
(
strcmp
(
identifier
,
auth_state
->
userid
)
==
0
)
return
3
;
if
(
strncmp
(
identifier
,
"group:"
,
6
)
!=
0
)
return
0
;
for
(
i
=
0
;
i
<
auth_state
->
groups
.
count
;
i
++
)
{
if
(
strcmp
(
identifier
+
6
,
auth_state
->
groups
.
data
[
i
])
==
0
)
return
2
;
}
return
0
;
}
/* Map of which characters are allowed by auth_canonifyid.
* Key: 0 -> not allowed (special, ctrl, or would confuse Unix or imapd)
* 1 -> allowed, but requires an alpha somewhere else in the string
* 2 -> allowed, and is an alpha
*
* At least one character must be an alpha.
*
* This may not be restrictive enough.
* Here are the reasons for the restrictions:
*
* & forbidden because of MUTF-7. (This could be fixed.)
* : forbidden because it's special in /etc/passwd
* / forbidden because it can't be used in a mailbox name
* * % forbidden because they're IMAP magic in the LIST/LSUB commands
* ? it just scares me
* ctrl chars, DEL
* can't send them as IMAP characters in plain folder names, I think
* 80-FF forbidden because you can't send them in IMAP anyway
* (and they're forbidden as folder names). (This could be fixed.)
*
* + and - are *allowed* although '+' is probably used for userid+detail
* subaddressing and qmail users use '-' for subaddressing.
*
* Identifiers don't require a digit, really, so that should probably be
* relaxed, too.
*/
static
char
allowedchars
[
256
]
=
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 00-0F */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 10-1F */
1
,
1
,
1
,
1
,
1
,
0
,
0
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
/* 20-2F */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
/* 30-3F */
1
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
/* 40-4F */
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
1
,
1
,
1
,
1
,
1
,
/* 50-5F */
1
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
/* 60-6F */
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
1
,
1
,
1
,
1
,
0
,
/* 70-7F */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
/*
* Convert 'identifier' into canonical form.
* Returns a pointer to a static buffer containing the canonical form
* or NULL if 'identifier' is invalid.
*
* XXX If any of the characters marked with 0 are valid and are cropping up,
* the right thing to do is probably to canonicalize the identifier to two
* representations: one for getpwent calls and one for folder names. The
* latter canonicalizes to a MUTF7 representation.
*/
static
const
char
*
mycanonifyid
(
const
char
*
identifier
,
size_t
len
)
{
static
char
retbuf
[
81
];
struct
group
*
grp
;
char
*
p
;
int
username_tolower
=
0
;
if
(
!
len
)
len
=
strlen
(
identifier
);
if
(
len
>=
sizeof
(
retbuf
))
return
NULL
;
memmove
(
retbuf
,
identifier
,
len
);
retbuf
[
len
]
=
'\0'
;
/* This used to be far more restrictive, but many sites seem to ignore the
* ye olde Unix conventions of username. Specifically, we used to
* - drop case on the buffer
* - disallow lots of non-alpha characters ('-', '_', others)
* Now we do neither of these, but impose a very different policy based on
* the character map above.
*/
if
(
!
strncmp
(
retbuf
,
"group:"
,
6
))
{
grp
=
getgrnam
(
retbuf
+
6
);
if
(
!
grp
)
return
NULL
;
if
(
strlen
(
grp
->
gr_name
)
>=
sizeof
(
retbuf
)
-6
)
return
NULL
;
strcpy
(
retbuf
+
6
,
grp
->
gr_name
);
return
retbuf
;
}
/* Copy the string and look up values in the allowedchars array above.
* If we see any we don't like, reject the string.
* Lowercase usernames if requested.
*/
username_tolower
=
libcyrus_config_getswitch
(
CYRUSOPT_USERNAME_TOLOWER
);
for
(
p
=
retbuf
;
*
p
;
p
++
)
{
if
(
username_tolower
&&
Uisupper
(
*
p
))
*
p
=
tolower
((
unsigned
char
)
*
p
);
switch
(
allowedchars
[
*
(
unsigned
char
*
)
p
])
{
case
0
:
return
NULL
;
default
:
break
;
}
}
return
retbuf
;
}
/*
* Set the current user to 'identifier'. 'cacheid', if non-null,
* points to a 16-byte binary key to cache identifier's information
* with.
*/
static
struct
auth_state
*
mynewstate
(
const
char
*
identifier
)
{
struct
auth_state
*
newstate
;
struct
passwd
*
pwd
;
struct
group
*
grp
;
#if defined(HAVE_GETGROUPLIST) && defined(__GLIBC__)
gid_t
gid
,
*
groupids
=
NULL
;
int
ret
,
ngroups
=
10
,
oldngroups
;
#else
char
**
mem
;
#endif
identifier
=
mycanonifyid
(
identifier
,
0
);
if
(
!
identifier
)
return
0
;
if
(
!
strncmp
(
identifier
,
"group:"
,
6
))
return
0
;
newstate
=
(
struct
auth_state
*
)
xmalloc
(
sizeof
(
struct
auth_state
));
strcpy
(
newstate
->
userid
,
identifier
);
strarray_init
(
&
newstate
->
groups
);
if
(
!
libcyrus_config_getswitch
(
CYRUSOPT_AUTH_UNIX_GROUP_ENABLE
))
return
newstate
;
pwd
=
getpwnam
(
identifier
);
#if defined(HAVE_GETGROUPLIST) && defined(__GLIBC__)
gid
=
pwd
?
pwd
->
pw_gid
:
(
gid_t
)
-1
;
/* get the group ids */
do
{
groupids
=
(
gid_t
*
)
xrealloc
((
gid_t
*
)
groupids
,
ngroups
*
sizeof
(
gid_t
));
oldngroups
=
ngroups
;
/* copy of ngroups for comparision */
ret
=
getgrouplist
(
identifier
,
gid
,
groupids
,
&
ngroups
);
/*
* This is tricky. We do this as long as getgrouplist tells us to
* realloc _and_ the number of groups changes. It tells us to realloc
* also in the case of failure...
*/
}
while
(
ret
==
-1
&&
ngroups
!=
oldngroups
);
if
(
ret
==
-1
)
goto
err
;
while
(
ngroups
--
)
{
if
(
pwd
||
groupids
[
ngroups
]
!=
gid
)
{
if
((
grp
=
getgrgid
(
groupids
[
ngroups
])))
strarray_append
(
&
newstate
->
groups
,
grp
->
gr_name
);
}
}
err
:
if
(
groupids
)
free
(
groupids
);
#else
/* !HAVE_GETGROUPLIST */
setgrent
();
while
((
grp
=
getgrent
()))
{
for
(
mem
=
grp
->
gr_mem
;
*
mem
;
mem
++
)
{
if
(
!
strcmp
(
*
mem
,
identifier
))
break
;
}
if
(
*
mem
||
(
pwd
&&
pwd
->
pw_gid
==
grp
->
gr_gid
))
strarray_append
(
&
newstate
->
groups
,
grp
->
gr_name
);
}
endgrent
();
#endif
/* HAVE_GETGROUPLIST */
return
newstate
;
}
static
void
myfreestate
(
struct
auth_state
*
auth_state
)
{
strarray_fini
(
&
auth_state
->
groups
);
free
(
auth_state
);
}
HIDDEN
struct
auth_mech
auth_unix
=
{
"unix"
,
/* name */
&
mycanonifyid
,
&
mymemberof
,
&
mynewstate
,
&
myfreestate
,
};
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Apr 24, 11:07 AM (1 w, 5 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
06/89/93bc06f2373b6924317127cf363c
Default Alt Text
auth_unix.c (8 KB)
Attached To
Mode
R111 cyrus-imapd
Attached
Detach File
Event Timeline