/* * $Id: queries.c,v 1.22 2009-10-13 22:55:37 didg Exp $ * * Copyright (c) 1990,1994 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #ifdef KRB #ifdef SOLARIS #include #else /* SOLARIS */ #include #endif /* SOLARIS */ #endif /* KRB */ #include "file.h" #include "comment.h" #include "printer.h" #include "ppd.h" #include "lp.h" #include "uam_auth.h" int cq_default( struct papfile *, struct papfile * ); int cq_k4login( struct papfile *, struct papfile * ); int cq_uameth( struct papfile *, struct papfile * ); int gq_balance( struct papfile * ); int gq_pagecost( struct papfile * ); int gq_true( struct papfile * ); int gq_rbispoolerid( struct papfile * ); int gq_rbiuamlist( struct papfile * ); int cq_query( struct papfile *, struct papfile * ); void cq_font_answer( char *, char *, struct papfile * ); int cq_font( struct papfile *, struct papfile * ); int cq_feature( struct papfile *, struct papfile * ); int cq_printer( struct papfile *, struct papfile * ); int cq_rmjob( struct papfile *, struct papfile * ); #ifndef HAVE_CUPS int cq_listq( struct papfile *, struct papfile * ); int cq_rbilogin( struct papfile *, struct papfile * ); #endif /* HAVE_CUPS */ int cq_default( struct papfile *in, struct papfile *out) { char *start, *stop, *p; int linelength, crlflength; struct papd_comment *comment = compeek(); for (;;) { switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } stop = start+linelength; if ( comgetflags() == 0 ) { /* started */ if ( comment->c_end ) { comsetflags( 1 ); } else { compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } } else { /* return default */ if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) { for ( p = start; p < stop; p++ ) { if ( *p == ':' ) { break; } } if (p < stop) { p++; while ( *p == ' ' ) { p++; } } append( out, p, stop - p + crlflength ); compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } } CONSUME( in, linelength + crlflength ); } } #ifdef KRB char *LoginOK = "LoginOK\n"; char *LoginFailed = "LoginFailed\n"; #define h2b(x) (isdigit((x))?(x)-'0':(isupper((x))?(x)-'A':(x)-'a')+10) int cq_k4login( struct papfile *in, struct papfile *out) { char *start, *p; int linelength, crlflength; unsigned char *t; struct papd_comment *comment = compeek(); KTEXT_ST tkt; AUTH_DAT ad; int rc, i; switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } p = start + strlen( comment->c_begin ); while ( *p == ' ' ) { p++; } bzero( &tkt, sizeof( tkt )); stop = start+linelength; /* FIXME */ for ( i = 0, t = tkt.dat; p < stop; p += 2, t++, i++ ) { *t = ( h2b( (unsigned char)*p ) << 4 ) + h2b( (unsigned char)*( p + 1 )); } tkt.length = i; if (( rc = krb_rd_req( &tkt, "LaserWriter", printer->p_name, 0, &ad, "" )) != RD_AP_OK ) { LOG(log_error, logtype_papd, "cq_k4login: %s", krb_err_txt[ rc ] ); append( out, LoginFailed, strlen( LoginFailed )); compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } LOG(log_info, logtype_papd, "cq_k4login: %s.%s@%s", ad.pname, ad.pinst, ad.prealm ); lp_person( ad.pname ); lp_host( ad.prealm ); append( out, LoginOK, strlen( LoginOK )); compop(); CONSUME( in, linelength + crlflength); return( CH_DONE ); } char *uameth = "UMICHKerberosIV\n*\n"; int cq_uameth( struct papfile *in, struct papfile *out) { char *start; int linelength, crlflength; struct papd_comment *c, *comment = compeek(); for (;;) { switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } if ( comgetflags() == 0 ) { /* start */ if (( printer->p_flags & P_KRB ) == 0 ) { /* no kerberos */ if ( comswitch( queries, cq_default ) < 0 ) { LOG(log_error, logtype_papd, "cq_uameth: can't find default!" ); exit( 1 ); } return( CH_DONE ); } comsetflags( 1 ); } else { if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { /* end */ append( out, uameth, strlen( uameth )); compop(); return( CH_DONE ); } } CONSUME( in, linelength + crlflength ); } } #endif /* KRB */ int gq_true( struct papfile *out) { if ( printer->p_flags & P_SPOOLED ) { append( out, "true\n", 5 ); return( 0 ); } else { return( -1 ); } } int gq_pagecost( struct papfile *out) { char cost[ 60 ]; /* check for spooler? XXX */ if ( printer->p_pagecost_msg != NULL ) { append( out, printer->p_pagecost_msg, strlen( printer->p_pagecost_msg )); } else if ( printer->p_flags & P_ACCOUNT ) { #ifdef ABS_PRINT lp_pagecost(); #endif /* ABS_PRINT */ sprintf( cost, "%d", printer->p_pagecost ); append( out, cost, strlen( cost )); } else { return( -1 ); } append( out, "\n", 1 ); return( 0 ); } #ifdef ABS_PRINT int gq_balance( struct papfile *out) { char balance[ 60 ]; if ( lp_pagecost() != 0 ) { return( -1 ); } sprintf( balance, "$%1.2f\n", printer->p_balance ); append( out, balance, strlen( balance )); return( 0 ); } #endif /* ABS_PRINT */ /* * Handler for RBISpoolerID */ static const char *spoolerid = "(PAPD Spooler) 1.0 (" VERSION ")\n"; int gq_rbispoolerid( struct papfile *out) { append( out, spoolerid, strlen( spoolerid )); return(0); } /* * Handler for RBIUAMListQuery */ static const char *nouams = "*\n"; int gq_rbiuamlist( struct papfile *out) { char uamnames[128] = "\0"; if (printer->p_flags & P_AUTH_PSSP) { if (getuamnames(UAM_SERVER_PRINTAUTH, uamnames) < 0) { append(out, nouams, strlen(nouams)); return(0); } else { append(out, uamnames, strlen(uamnames)); return(0); } } else { append(out, nouams, strlen(nouams)); return(0); } } struct genquery { char *gq_name; int (*gq_handler)(); } genqueries[] = { { "UMICHCostPerPage", gq_pagecost }, #ifdef notdef { "UMICHUserBalance", gq_balance }, #endif /* notdef */ { "RBISpoolerID", gq_rbispoolerid }, { "RBIUAMListQuery", gq_rbiuamlist }, { "ADOIsBinaryOK?", gq_true }, { "UMICHListQueue", gq_true }, { "UMICHDeleteJob", gq_true }, { NULL, NULL }, }; int cq_query( struct papfile *in, struct papfile *out) { char *start, *stop, *p, *q; int linelength, crlflength; struct papd_comment *comment = compeek(); struct genquery *gq; for (;;) { switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } stop = start+linelength; if ( comgetflags() == 0 ) { /* started */ comsetflags( 1 ); for ( p = start; p < stop; p++ ) { if ( *p == ':' ) { break; } } if (p < stop) for ( p++; p < stop; p++ ) { if ( *p != ' ' && *p != '\t' ) { break; } } for ( q = p; q < stop; q++ ) { if ( *q == ' ' || *q == '\t' || *q == '\r' || *q == '\n' ) { break; } } for ( gq = genqueries; gq->gq_name; gq++ ) { if (( strlen( gq->gq_name ) == (size_t)(q - p) ) && ( strncmp( gq->gq_name, p, q - p ) == 0 )) { break; } } if ( gq->gq_name == NULL || gq->gq_handler == NULL || (gq->gq_handler)( out ) < 0 ) { if ( comswitch( queries, cq_default ) < 0 ) { LOG(log_error, logtype_papd, "cq_feature: can't find default!" ); exit( 1 ); } return( CH_DONE ); } } else { if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } } CONSUME( in, linelength + crlflength ); } } void cq_font_answer( char *start, char *stop, struct papfile *out) { char *p, *q, buf[ 256 ]; struct ppd_font *pfo; p = start; while ( p < stop ) { unsigned int count = 0; while (( *p == ' ' || *p == '\t' ) && p < stop ) { p++; } q = buf; while ( *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r' && p < stop && count < sizeof(buf)) { *q++ = *p++; count++; } if ( q != buf ) { *q = '\0'; append( out, "/", 1 ); append( out, buf, strlen( buf )); append( out, ":", 1 ); if (( pfo = ppd_font( buf )) == NULL ) { append( out, "No\n", 3 ); } else { append( out, "Yes\n", 4 ); } } } return; } int cq_font(struct papfile *in, struct papfile *out) { char *start, *stop, *p; int linelength, crlflength; struct papd_comment *comment = compeek(); for (;;) { switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } stop = start + linelength; if ( comgetflags() == 0 ) { comsetflags( 1 ); for ( p = start; p < stop; p++ ) { if ( *p == ':' ) { break; } } if (p < stop) p++; cq_font_answer( p, stop, out ); } else { if ( comgetflags() == 1 && comcmp( start, stop, comcont, 0 ) == 0 ) { /* continuation */ for ( p = start; p < stop; p++ ) { if ( *p == ' ' ) { break; } } if (p < stop) p++; cq_font_answer( p, stop, out ); } else { comsetflags( 2 ); if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { append( out, "*\n", 2 ); compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } } } CONSUME( in, linelength + crlflength ); } } int cq_feature( struct papfile *in, struct papfile *out) { char *start, *stop, *p; int linelength, crlflength; struct papd_comment *comment = compeek(); struct ppd_feature *pfe; for (;;) { switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } stop = start + linelength; if ( comgetflags() == 0 ) { comsetflags( 1 ); /* parse for feature */ for ( p = start; p < stop; p++ ) { if ( *p == ':' ) { break; } } if (p < stop) p++; while ( *p == ' ' ) { p++; } if (( pfe = ppd_feature( p, stop - p )) == NULL ) { if ( comswitch( queries, cq_default ) < 0 ) { LOG(log_error, logtype_papd, "cq_feature: can't find default!" ); exit( 1 ); } return( CH_DONE ); } append( out, pfe->pd_value, strlen( pfe->pd_value )); append( out, "\r", 1 ); } else { if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } } CONSUME( in, linelength + crlflength ); } } static const char *psver = "*PSVersion\n"; static const char *prod = "*Product\n"; int cq_printer(struct papfile *in, struct papfile *out) { char *start, *p; int linelength, crlflength; struct papd_comment *comment = compeek(); struct ppd_feature *pdpsver, *pdprod; for (;;) { switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } if ( comgetflags() == 0 ) { comsetflags( 1 ); if (( pdpsver = ppd_feature( psver, strlen( psver ))) == NULL ) { if ( comswitch( queries, cq_default ) < 0 ) { LOG(log_error, logtype_papd, "cq_printer: can't find default!" ); exit( 1 ); } return( CH_DONE ); } for ( p = pdpsver->pd_value; *p != '\0'; p++ ) { if ( *p == ' ' ) { break; } } if ( *p == '\0' ) { LOG(log_error, logtype_papd, "cq_printer: can't parse PSVersion!" ); if ( comswitch( queries, cq_default ) < 0 ) { LOG(log_error, logtype_papd, "cq_printer: can't find default!" ); exit( 1 ); } return( CH_DONE ); } if (( pdprod = ppd_feature( prod, strlen( prod ))) == NULL ) { if ( comswitch( queries, cq_default ) < 0 ) { LOG(log_error, logtype_papd, "cq_printer: can't find default!" ); exit( 1 ); } return( CH_DONE ); } /* revision */ append( out, p + 1, strlen( p + 1 )); append( out, "\r", 1 ); /* version */ append( out, pdpsver->pd_value, p - pdpsver->pd_value ); append( out, "\r", 1 ); /* product */ append( out, pdprod->pd_value, strlen( pdprod->pd_value )); append( out, "\r", 1 ); } else { if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) { compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } } CONSUME( in, linelength + crlflength ); } } #ifndef HAVE_CUPS static const char *rmjobfailed = "Failed\n"; static const char *rmjobok = "Ok\n"; int cq_rmjob( struct papfile *in, struct papfile *out) { char *start, *stop, *p; int linelength, crlflength; int job; switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } stop = start + linelength; for ( p = start; p < stop; p++ ) { if ( *p == ' ' || *p == '\t' ) { break; } } for ( ; p < stop; p++ ) { if ( *p != ' ' && *p != '\t' ) { break; } } *stop = '\0'; if ( p < stop && ( job = atoi( p )) > 0 ) { lp_rmjob( job ); append( out, rmjobok, strlen( rmjobok )); } else { append( out, rmjobfailed, strlen( rmjobfailed )); } compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } int cq_listq( struct papfile *in, struct papfile *out) { char *start; int linelength, crlflength; switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } if ( lp_queue( out )) { LOG(log_error, logtype_papd, "cq_listq: lp_queue failed" ); } compop(); CONSUME( in, linelength + crlflength ); return( CH_DONE ); } #endif /* HAVE_CUPS */ /* * Handler for RBILogin */ static struct uam_obj *papd_uam = NULL; static const char *rbiloginok = "0\r"; static const char *rbiloginbad = "-1\r"; static const char *rbiloginerrstr = "%%[Error: SecurityError; \ SecurityViolation: Unknown user, incorrect password or log on is \ disabled ]%%\r%%[Flushing: rest of job (to end-of-file) will be \ ignored ]%%\r"; int cq_rbilogin( struct papfile *in, struct papfile *out) { char *start, *stop, *p, *begin; int linelength, crlflength; char username[UAM_USERNAMELEN + 1] = "\0"; struct papd_comment *comment = compeek(); char uamtype[20]; for (;;) { switch ( markline( in, &start, &linelength, &crlflength )) { case 0 : return( 0 ); case -1 : return( CH_MORE ); case -2 : return( CH_ERROR ); } stop = start + linelength; if ( comgetflags() == 0 ) { /* first line */ begin = start + strlen(comment->c_begin); p = begin; while (*p != ' ' && p < stop) { p++; } memset(uamtype, 0, sizeof(uamtype)); if ((size_t)(p -begin) <= sizeof(uamtype) -1) { strncpy(uamtype, begin, p - begin); } if ( !*uamtype || (papd_uam = auth_uamfind(UAM_SERVER_PRINTAUTH, uamtype, strlen(uamtype))) == NULL) { LOG(log_info, logtype_papd, "Could not find uam: %s", uamtype); append(out, rbiloginbad, strlen(rbiloginbad)); append(out, rbiloginerrstr, strlen(rbiloginerrstr)); } else { if ( (papd_uam->u.uam_printer(p,stop,username,out)) == 0 ) { lp_person( username ); append(out, rbiloginok, strlen( rbiloginok )); LOG(log_info, logtype_papd, "RBILogin: Logged in '%s'", username); } else { append(out, rbiloginbad, strlen( rbiloginbad)); append(out, rbiloginerrstr, strlen(rbiloginerrstr)); } } comsetflags( 1 ); } else { if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { compop(); return( CH_DONE ); } } CONSUME( in, linelength + crlflength ); } } /* * All queries start with %%?Begin and end with %%?End. Note that the * "Begin"/"End" general queries have to be last. */ struct papd_comment queries[] = { #ifdef KRB { "%%Login: UMICHKerberosIV", NULL, cq_k4login, 0 }, { "%%?BeginUAMethodsQuery", "%%?EndUAMethodsQuery:", cq_uameth,C_FULL }, #endif /* KRB */ #ifndef HAVE_CUPS { "%UMICHListQueue", NULL, cq_listq, C_FULL }, { "%UMICHDeleteJob", NULL, cq_rmjob, 0 }, #endif /* HAVE_CUPS */ { "%%?BeginQuery: RBILogin ", "%%?EndQuery", cq_rbilogin, 0 }, { "%%?BeginQuery", "%%?EndQuery", cq_query, 0 }, { "%%?BeginFeatureQuery", "%%?EndFeatureQuery", cq_feature, 0 }, { "%%?BeginFontQuery", "%%?EndFontQuery", cq_font, 0 }, { "%%?BeginPrinterQuery", "%%?EndPrinterQuery", cq_printer,C_FULL }, { "%%?Begin", "%%?End", cq_default, 0 }, { NULL, NULL, NULL, 0 }, };