From a8001e07a0a6eafe699578bd97cf5efd54ab363f Mon Sep 17 00:00:00 2001 From: gad Date: Fri, 31 Dec 2004 00:18:42 +0000 Subject: Do more extensive checking of the userid field which is read in from the control-file for each print job. This is partially because the previous checks still let through some characters which would cause trouble for other applications which try to process the resulting userid -- such as accounting programs. But the main reason is to handle the case where some remote host sends a print job where the given userid is an uppercase-version of the real userid. For that case, lpd will now check for uppercase letters in the userid. If there are any, it will check to see if the given userid (with the uppercase letters) is a valid one. If it is *not* valid, then lpd will change the userid to all-lowercase right when the job is received. MFC after: 2 weeks --- usr.sbin/lpr/common_source/ctlinfo.c | 53 +++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'usr.sbin/lpr/common_source') diff --git a/usr.sbin/lpr/common_source/ctlinfo.c b/usr.sbin/lpr/common_source/ctlinfo.c index 67cac6b..20a153f 100644 --- a/usr.sbin/lpr/common_source/ctlinfo.c +++ b/usr.sbin/lpr/common_source/ctlinfo.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -73,6 +74,18 @@ struct cjprivate { int cji_dumpit; }; +/* + * All the following take a parameter of 'int', but expect values in the + * range of unsigned char. Define wrappers which take values of type 'char', + * whether signed or unsigned, and ensure they end up in the right range. + */ +#define isdigitch(Anychar) isdigit((u_char)(Anychar)) +#define islowerch(Anychar) islower((u_char)(Anychar)) +#define isupperch(Anychar) isupper((u_char)(Anychar)) +#define tolowerch(Anychar) tolower((u_char)(Anychar)) + +#define OTHER_USERID_CHARS "-_" /* special chars valid in a userid */ + #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* @@ -345,11 +358,11 @@ ctl_readcf(const char *ptrname, const char *cfname) cpriv->pub.cji_mailto = strdup(lbuff); break; case 'P': - /* don't allow userid's with a leading minus, either */ - if (*lbuff == '-') - break; if (*lbuff == '\0') break; + /* The userid must not start with a minus sign */ + if (*lbuff == '-') + *lbuff = '_'; cpriv->pub.cji_acctuser = strdup(lbuff); break; default: @@ -414,7 +427,7 @@ ctl_readcf(const char *ptrname, const char *cfname) char * ctl_renametf(const char *ptrname, const char *tfname) { - int chk3rd, newfd, nogood, res; + int chk3rd, has_uc, newfd, nogood, res; FILE *newcf; struct cjobinfo *cjinf; char *lbuff, *slash, *cp; @@ -531,10 +544,36 @@ ctl_renametf(const char *ptrname, const char *tfname) nogood = 0; if (cjinf->cji_acctuser == NULL) nogood = 1; + else if (strcmp(cjinf->cji_acctuser, ".na.") == 0) + ; /* No further checks needed... */ else { - for (cp = cjinf->cji_acctuser; *cp != '\0'; cp++) { - if (*cp <= ' ') - *cp = '_'; + has_uc = 0; + cp = cjinf->cji_acctuser; + if (*cp == '-') + *cp++ = '_'; + for (; *cp != '\0'; cp++) { + if (islowerch(*cp) || isdigitch(*cp)) + continue; /* Standard valid characters */ + if (strchr(OTHER_USERID_CHARS, *cp) != NULL) + continue; /* Some more valid characters */ + if (isupperch(*cp)) { + has_uc = 1; /* These may be valid... */ + continue; + } + *cp = '_'; + } + /* + * Some Windows hosts send print jobs where the correct userid + * has been converted to uppercase, and that can cause trouble + * for sites that expect the correct value (for something like + * accounting). On the other hand, some sites do use uppercase + * in their userids, so we can't blindly convert to lowercase. + */ + if (has_uc && (getpwnam(cjinf->cji_acctuser) == NULL)) { + for (cp = cjinf->cji_acctuser; *cp != '\0'; cp++) { + if (isupperch(*cp)) + *cp = tolowerch(*cp); + } } } if (nogood) -- cgit v1.1