Example #1
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 sawalpha;
    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);
    sawalpha = 0;
    for(p = retbuf; *p; p++) {
	if (username_tolower && Uisupper(*p))
	    *p = tolower((unsigned char)*p);

	switch (allowedchars[*(unsigned char*) p]) {
	case 0:
	    return NULL;
	    
	case 2:
	    sawalpha = 1;
	    /* FALL THROUGH */
	    
	default:
	    ;
	}
    }

    /* we used to enforce "has to be one alpha char" */
    /* now we don't */
    /* if (!sawalpha) return NULL;  */

    return retbuf;
}
Example #2
0
/*
 * 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;
}