diff -upr lib.orig/auth_unix.c lib/auth_unix.c --- lib.orig/auth_unix.c 2004-07-03 03:19:44.000000000 +0200 +++ lib/auth_unix.c 2004-07-03 03:18:16.000000000 +0200 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,126 @@ #include "libcyr_cfg.h" #include "xmalloc.h" +#ifdef __FreeBSD__ +/* + * __getgrent.c - This file is part of the libc-8086/grp package for ELKS, + * Copyright (C) 1995, 1996 Nat Friedman . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include + +static struct group *__getgrent(int grp_fd, char *line_buff, char **members) +{ + short line_index; + short buff_size; + static struct group group; + register char *ptr; + char *field_begin; + short member_num; + char *endptr; + int line_len; + + /* We use the restart label to handle malformatted lines */ + restart: + line_index = 0; + buff_size = 256; + + line_buff = realloc(line_buff, buff_size); + while (1) { + if ((line_len = read(grp_fd, line_buff + line_index, + buff_size - line_index)) <= 0) { + return NULL; + } + field_begin = strchr(line_buff, '\n'); + if (field_begin != NULL) { + lseek(grp_fd, + (long) (1 + field_begin - + (line_len + line_index + line_buff)), SEEK_CUR); + *field_begin = '\0'; + if (*line_buff == '#' || *line_buff == ' ' + || *line_buff == '\n' || *line_buff == '\t') + goto restart; + break; + } else { + /* Allocate some more space */ + line_index = buff_size; + buff_size += 256; + line_buff = realloc(line_buff, buff_size); + } + } + + /* Now parse the line */ + group.gr_name = line_buff; + ptr = strchr(line_buff, ':'); + if (ptr == NULL) + goto restart; + *ptr++ = '\0'; + + group.gr_passwd = ptr; + ptr = strchr(ptr, ':'); + if (ptr == NULL) + goto restart; + *ptr++ = '\0'; + + field_begin = ptr; + ptr = strchr(ptr, ':'); + if (ptr == NULL) + goto restart; + *ptr++ = '\0'; + + group.gr_gid = (gid_t) strtoul(field_begin, &endptr, 10); + if (*endptr != '\0') + goto restart; + + member_num = 0; + field_begin = ptr; + + if (members != NULL) + free(members); + members = (char **) malloc((member_num + 1) * sizeof(char *)); + for ( ; field_begin && *field_begin != '\0'; field_begin = ptr) { + if ((ptr = strchr(field_begin, ',')) != NULL) + *ptr++ = '\0'; + members[member_num++] = field_begin; + members = (char **) realloc(members, + (member_num + 1) * sizeof(char *)); + } + members[member_num] = NULL; + + group.gr_mem = members; + return &group; +} + +static char *line_buff = NULL; +static char **members = NULL; + +struct group *fgetgrent(FILE *file) +{ + if (file == NULL) { + errno = EINTR; + return NULL; + } + return __getgrent(fileno(file), line_buff, members); +} +#endif /* __FreeBSD__ */ + const char *auth_method_desc = "unix"; struct auth_state { @@ -144,6 +265,25 @@ static char allowedchars[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static struct group* fgetgrnam(const char* name) +{ + struct group *grp; + FILE *groupfile; + + groupfile = fopen( SYSCONFDIR "/imapd.group", "r"); + if (!groupfile) groupfile = fopen("/etc/group", "r"); + if (groupfile) { + while ((grp = fgetgrent(groupfile))) { + if (strcmp(grp->gr_name, name) == 0) { + fclose(groupfile); + return grp; + } + } + } + if (groupfile) fclose(groupfile); + return NULL; +} + /* * Convert 'identifier' into canonical form. * Returns a pointer to a static buffer containing the canonical form @@ -179,7 +319,7 @@ size_t len; */ if (!strncmp(retbuf, "group:", 6)) { - grp = getgrnam(retbuf+6); + grp = fgetgrnam(retbuf+6); if (!grp) return 0; strcpy(retbuf+6, grp->gr_name); return retbuf; @@ -224,6 +364,7 @@ struct auth_state *auth_newstate(const c struct passwd *pwd; struct group *grp; char **mem; + FILE *groupfile; identifier = auth_canonifyid(identifier, 0); if (!identifier) return 0; @@ -240,20 +381,23 @@ struct auth_state *auth_newstate(const c pwd = getpwnam(identifier); - 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)) { - newstate->ngroups++; - newstate->group = (char **)xrealloc((char *)newstate->group, - newstate->ngroups * sizeof(char *)); - newstate->group[newstate->ngroups-1] = xstrdup(grp->gr_name); - } - } - endgrent(); + groupfile = fopen( SYSCONFDIR "/imapd.group", "r"); + if (!groupfile) groupfile = fopen("/etc/group", "r"); + if (groupfile) { + while ((grp = fgetgrent(groupfile))) { + for (mem = grp->gr_mem; *mem; mem++) { + if (!strcmp(*mem, identifier)) break; + } + + if (*mem || (pwd && pwd->pw_gid == grp->gr_gid)) { + newstate->ngroups++; + newstate->group = (char **)xrealloc((char *)newstate->group, + newstate->ngroups * sizeof(char *)); + newstate->group[newstate->ngroups-1] = xstrdup(grp->gr_name); + } + } + fclose(groupfile); + } return newstate; }