Problem with cyradm and krb5 */admin principals

Paul M Fleming pfleming at siumed.edu
Fri Mar 28 10:27:58 EST 2003


I've attached the code. Put this in the lib directory as auth_regexp.c
When you configure you must do --with-auth=regexp This code requires
POSIX regex functions, you may have to include additional libraries
depending on the OS. On RedHat the regex functions are part of libc.
Someday I'll get a web page up with this code and some more
explaination.

Once compiled with this module you can use any regular expression to
match identifiers.. 

For example from my configs:

admins: regexp:.+/admin
proxyservers: regexp:murder/.+\.siumed\.edu
lmtp_admins: regexp:murder/.+\.siumed\.edu



Ben Poliakoff wrote:
> 
> That certainly would explain this behavior.
> 
> How involved is your regex auth module?  And would you feel comfortable
> sharing it?
> 
> Ben
> 
> * Paul M Fleming <pfleming at siumed.edu> [030326 13:10]:
> > The / is considered an illegal character under auth_unix. I wrote a
> > regular expression based auth module which will work with Kerb V. That
> > is how we solved the problem..
> >
> >
> >
> > Rudolph T Maceyko wrote:
> > >--On Wednesday, March 26, 2003 11:47:34 -0800 Ben Poliakoff
> > ><benp at reed.edu> wrote:
> > >
> > >>Anyone out there using */admin principals with cyradm?
> > >
> > >
> > >I tried and gave up, so I'd like to discover the way to do this too...
> > >It worked under 2.0.x releases of Cyrus IMAPd.
> > >
> > >Rudy
> > >
> > >
> 
> --
> ---------------------------------------------------------------------------
> Ben Poliakoff                                       email: <benp at reed.edu>
> Reed College                                          tel:  (503)-788-6674
> Unix System Administrator      PGP key: http://www.reed.edu/~benp/key.html
> ---------------------------------------------------------------------------
> 0x6AF52019 fingerprint = A131 F813 7A0F C5B7 E74D  C972 9118 A94D 6AF5 2019
-------------- next part --------------
/* auth_regexp.c -- Regular Expression Authorization 
   based on Unix passwd file authorization by CMU

   Paul M Fleming
   Nov 17, 2002
   Southern Illinois University
   School of Medicine
   pfleming at siumed.edu

*/

#include <config.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <regex.h>
#include <syslog.h>
#include "auth.h"
#include "xmalloc.h"

const char *auth_method_desc = "regexp";

struct auth_state {
    char userid[81];
};

static struct auth_state auth_anonymous = {
    "anonymous"
};

/*
 * 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
 */
int auth_memberof(auth_state, identifier)
struct auth_state *auth_state;
const char *identifier;
{
    regex_t compiled_reg;


    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, "regexp:", 7) != 0) return 0;

    /* we're looking at a regular expression 
       compile and compare identifier to auth_state->userid
    */

    if ( regcomp(&compiled_reg,identifier+7,REG_EXTENDED | REG_NOSUB) != 0 ) return 0;

    /* we have a compiled reg exp. evaluate */
    if ( regexec(&compiled_reg,auth_state->userid,0,0,0) == 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, 1, /* 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.
 */
char *auth_canonifyid(identifier, len)
const char *identifier;
size_t len;
{
    static char retbuf[81];
    char sawalpha;
    char *p;
    regex_t compiled_reg;

    if(!len) len = strlen(identifier);
    if(len >= sizeof(retbuf)) return NULL;

    if (strcasecmp(identifier, "anonymous") == 0) {
	return "anonymous";
    }
    if (strcasecmp(identifier, "anybody") == 0 ||
	strcasecmp(identifier, "anyone") == 0) {
	return "anyone";
    }
    
    memcpy(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, "regexp:", 7)) {
	/* we're checking a regular expression try and compile it
	   if OK return retbuf otherwise NULL
	*/

	if ( regcomp(&compiled_reg,retbuf+7,REG_EXTENDED | REG_NOSUB) != 0 )
	{
		/* error with compiling reg exp return 0 */
		return 0;
	}
	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.
     */
    sawalpha = 0;
    for(p = retbuf; *p; p++) {
	switch (allowedchars[*(unsigned char*) p]) {
	case 0:
	    return NULL;
	    
	case 2:
	    sawalpha = 1;
	    /* FALL THROUGH */
	    
	default:
	    ;
	}
    }

    if (!sawalpha) return NULL;  /* has to be one alpha char */

    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.
 */
struct auth_state *
auth_newstate(identifier, cacheid)
const char *identifier;
const char *cacheid;
{
    struct auth_state *newstate;

    identifier = auth_canonifyid(identifier, 0);
    if (!identifier) return 0;
    if (!strncmp(identifier, "regexp:", 7)) return 0;
    
    newstate = (struct auth_state *)xmalloc(sizeof(struct auth_state));

    strcpy(newstate->userid, identifier);

    return newstate;
}

void
auth_freestate(auth_state)
struct auth_state *auth_state;
{
    free((char *)auth_state);
}




More information about the Info-cyrus mailing list