]> arthur.barton.de Git - netatalk.git/blob - etc/papd/queries.c
Consistently set default UAMs to DHX,DHX2. From HAT.
[netatalk.git] / etc / papd / queries.c
1 /*
2  * $Id: queries.c,v 1.16.2.1.2.1.2.2 2009-02-03 08:25:00 didg Exp $
3  *
4  * Copyright (c) 1990,1994 Regents of The University of Michigan.
5  * All Rights Reserved.  See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <atalk/logger.h>
16 #include <sys/param.h>
17 #include <sys/time.h>
18 #include <sys/types.h>
19 #include <netatalk/at.h>
20 #include <atalk/atp.h>
21
22 #ifdef KRB
23 #ifdef SOLARIS
24 #include <kerberos/krb.h>
25 #else /* SOLARIS */
26 #include <krb.h>
27 #endif /* SOLARIS */
28 #endif /* KRB */
29
30 #include "file.h"
31 #include "comment.h"
32 #include "printer.h"
33 #include "ppd.h"
34 #include "lp.h"
35 #include "uam_auth.h"
36
37 int cq_default( struct papfile *, struct papfile * );
38 int cq_k4login( struct papfile *, struct papfile * );
39 int cq_uameth( struct papfile *, struct papfile * );
40
41 int gq_balance( struct papfile * );
42 int gq_pagecost( struct papfile * );
43 int gq_true( struct papfile * );
44 int gq_rbispoolerid( struct papfile * );
45 int gq_rbiuamlist( struct papfile * );
46
47 int cq_query( struct papfile *, struct papfile * );
48 void cq_font_answer( char *, char *, struct papfile * );
49 int cq_font( struct papfile *, struct papfile * );
50 int cq_feature( struct papfile *, struct papfile * );
51 int cq_printer( struct papfile *, struct papfile * );
52 int cq_rmjob( struct papfile *, struct papfile * );
53 #ifndef HAVE_CUPS
54 int cq_listq( struct papfile *, struct papfile * );
55 int cq_rbilogin( struct papfile *, struct papfile * );
56 #endif  /* HAVE_CUPS */
57
58
59
60 int cq_default( in, out )
61     struct papfile      *in, *out;
62 {
63     char                *start, *stop, *p;
64     int                 linelength, crlflength;
65     struct papd_comment *comment = compeek();
66
67     for (;;) {
68         switch ( markline( in, &start, &linelength, &crlflength )) {
69         case 0 :
70             return( 0 );
71
72         case -1 :
73             return( CH_MORE );
74
75         case -2 :
76             return( CH_ERROR );
77         }
78
79         stop = start+linelength;
80
81         if ( comgetflags() == 0 ) {     /* started */
82             if ( comment->c_end ) {
83                 comsetflags( 1 );
84             } else {
85                 compop();
86                 CONSUME( in, linelength + crlflength );
87                 return( CH_DONE );
88             }
89         } else {
90             /* return default */
91             if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
92                 for ( p = start; p < stop; p++ ) {
93                     if ( *p == ':' ) {
94                         break;
95                     }
96                 }
97                 if (p < stop) {
98                     p++;
99                     while ( *p == ' ' ) {
100                         p++;
101                     }
102                 }
103
104                 append( out, p, stop - p + crlflength );
105                 compop();
106                 CONSUME( in, linelength + crlflength );
107                 return( CH_DONE );
108             }
109         }
110
111         CONSUME( in, linelength + crlflength );
112     }
113 }
114
115 #ifdef KRB
116 char    *LoginOK = "LoginOK\n";
117 char    *LoginFailed = "LoginFailed\n";
118
119 #define h2b(x)  (isdigit((x))?(x)-'0':(isupper((x))?(x)-'A':(x)-'a')+10)
120
121 int cq_k4login( in, out )
122     struct papfile      *in, *out;
123 {
124     char                *start, *p;
125     int                 linelength, crlflength;
126     unsigned char       *t;
127     struct papd_comment *comment = compeek();
128     KTEXT_ST            tkt;
129     AUTH_DAT            ad;
130     int                 rc, i;
131
132     switch ( markline( in, &start, &linelength, &crlflength )) {
133     case 0 :
134         return( 0 );
135
136     case -1 :
137         return( CH_MORE );
138
139     case -2 :
140         return( CH_ERROR );
141     }
142
143     p = start + strlen( comment->c_begin );
144     while ( *p == ' ' ) {
145         p++;
146     }
147
148     bzero( &tkt, sizeof( tkt ));
149     stop = start+linelength;
150     /* FIXME */
151     for ( i = 0, t = tkt.dat; p < stop; p += 2, t++, i++ ) {
152         *t = ( h2b( (unsigned char)*p ) << 4 ) +
153                 h2b( (unsigned char)*( p + 1 ));
154     }
155     tkt.length = i;
156
157     if (( rc = krb_rd_req( &tkt, "LaserWriter", printer->p_name,
158             0, &ad, "" )) != RD_AP_OK ) {
159         LOG(log_error, logtype_papd, "cq_k4login: %s", krb_err_txt[ rc ] );
160         append( out, LoginFailed, strlen( LoginFailed ));
161         compop();
162         CONSUME( in, linelength + crlflength );
163         return( CH_DONE );
164     }
165     LOG(log_info, logtype_papd, "cq_k4login: %s.%s@%s", ad.pname, ad.pinst,
166             ad.prealm );
167     lp_person( ad.pname );
168     lp_host( ad.prealm );
169
170     append( out, LoginOK, strlen( LoginOK ));
171     compop();
172     CONSUME( in, linelength + crlflength);
173     return( CH_DONE );
174 }
175
176 char    *uameth = "UMICHKerberosIV\n*\n";
177
178 int cq_uameth( in, out )
179     struct papfile      *in, *out;
180 {
181     char                *start;
182     int                 linelength, crlflength;
183     struct papd_comment *c, *comment = compeek();
184
185     for (;;) {
186         switch ( markline( in, &start, &linelength, &crlflength )) {
187         case 0 :
188             return( 0 );
189
190         case -1 :
191             return( CH_MORE );
192
193         case -2 :
194             return( CH_ERROR );
195         }
196
197         if ( comgetflags() == 0 ) {     /* start */
198             if (( printer->p_flags & P_KRB ) == 0 ) {   /* no kerberos */
199                 if ( comswitch( queries, cq_default ) < 0 ) {
200                     LOG(log_error, logtype_papd, "cq_uameth: can't find default!" );
201                     exit( 1 );
202                 }
203                 return( CH_DONE );
204             }
205             comsetflags( 1 );
206         } else {
207             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { /* end */
208                 append( out, uameth, strlen( uameth ));
209                 compop();
210                 return( CH_DONE );
211             }
212         }
213
214         CONSUME( in, linelength + crlflength );
215     }
216 }
217 #endif /* KRB */
218
219 int gq_true( out )
220     struct papfile      *out;
221 {
222     if ( printer->p_flags & P_SPOOLED ) {
223         append( out, "true\n", 5 );
224         return( 0 );
225     } else {
226         return( -1 );
227     }
228 }
229
230 int gq_pagecost( out )
231     struct papfile      *out;
232 {
233     char                cost[ 60 ];
234
235     /* check for spooler? XXX */
236     if ( printer->p_pagecost_msg != NULL ) {
237         append( out, printer->p_pagecost_msg,
238                 strlen( printer->p_pagecost_msg ));
239     } else if ( printer->p_flags & P_ACCOUNT ) {
240 #ifdef ABS_PRINT
241         lp_pagecost();
242 #endif /* ABS_PRINT */
243         sprintf( cost, "%d", printer->p_pagecost );
244         append( out, cost, strlen( cost ));
245     } else {
246         return( -1 );
247     }
248     append( out, "\n", 1 );
249     return( 0 );
250 }
251
252 #ifdef ABS_PRINT
253 int gq_balance( out )
254     struct papfile      *out;
255 {
256     char                balance[ 60 ];
257
258     if ( lp_pagecost() != 0 ) {
259         return( -1 );
260     }
261     sprintf( balance, "$%1.2f\n", printer->p_balance );
262     append( out, balance, strlen( balance ));
263     return( 0 );
264 }
265 #endif /* ABS_PRINT */
266
267
268 /*
269  * Handler for RBISpoolerID
270  */
271
272 static const char *spoolerid = "(PAPD Spooler) 1.0 (" VERSION ")\n";
273
274 int gq_rbispoolerid( out )
275     struct papfile      *out;
276 {
277     append( out, spoolerid, strlen( spoolerid ));
278     return(0);
279 }
280
281
282
283 /*
284  * Handler for RBIUAMListQuery
285  */
286
287 static const char *nouams = "*\n";
288
289 int gq_rbiuamlist( out )
290     struct papfile      *out;
291 {
292     char uamnames[128] = "\0";
293
294     if (printer->p_flags & P_AUTH_PSSP) {
295         if (getuamnames(UAM_SERVER_PRINTAUTH, uamnames) < 0) {
296             append(out, nouams, strlen(nouams));
297             return(0);
298         } else {
299             append(out, uamnames, strlen(uamnames));
300             return(0);
301         }
302     } else {
303         append(out, nouams, strlen(nouams));
304         return(0);
305     }
306 }
307
308
309 struct genquery {
310     char        *gq_name;
311     int         (*gq_handler)();
312 } genqueries[] = {
313     { "UMICHCostPerPage", gq_pagecost },
314 #ifdef notdef
315     { "UMICHUserBalance", gq_balance },
316 #endif /* notdef */
317     { "RBISpoolerID",   gq_rbispoolerid },
318     { "RBIUAMListQuery", gq_rbiuamlist },
319     { "ADOIsBinaryOK?", gq_true },
320     { "UMICHListQueue", gq_true },
321     { "UMICHDeleteJob", gq_true },
322     { NULL, NULL },
323 };
324
325 int cq_query( in, out )
326     struct papfile      *in, *out;
327 {
328     char                *start, *stop, *p, *q;
329     int                 linelength, crlflength;
330     struct papd_comment *comment = compeek();
331     struct genquery     *gq;
332
333
334     for (;;) {
335         switch ( markline( in, &start, &linelength, &crlflength )) {
336         case 0 :
337             return( 0 );
338
339         case -1 :
340             return( CH_MORE );
341
342         case -2 :
343             return( CH_ERROR );
344         }
345
346         stop = start+linelength;
347
348         if ( comgetflags() == 0 ) {     /* started */
349             comsetflags( 1 );
350
351             for ( p = start; p < stop; p++ ) {
352                 if ( *p == ':' ) {
353                     break;
354                 }
355             }
356
357             if (p < stop) for ( p++; p < stop; p++ ) {
358                 if ( *p != ' ' && *p != '\t' ) {
359                     break;
360                 }
361             }
362
363             for ( q = p; q < stop; q++ ) {
364                 if ( *q == ' ' || *q == '\t' || *q == '\r' || *q == '\n' ) {
365                     break;
366                 }
367             }
368
369             for ( gq = genqueries; gq->gq_name; gq++ ) {
370                 if (( strlen( gq->gq_name ) == (size_t)(q - p) ) &&
371                         ( strncmp( gq->gq_name, p, q - p ) == 0 )) {
372                     break;
373                 }
374             }
375             if ( gq->gq_name == NULL || gq->gq_handler == NULL ||
376                     (gq->gq_handler)( out ) < 0 ) {
377                 if ( comswitch( queries, cq_default ) < 0 ) {
378                     LOG(log_error, logtype_papd, "cq_feature: can't find default!" );
379                     exit( 1 );
380                 }
381                 return( CH_DONE );
382             }
383         } else {
384             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
385                 compop();
386                 CONSUME( in, linelength + crlflength );
387                 return( CH_DONE );
388             }
389         }
390
391         CONSUME( in, linelength + crlflength );
392     }
393 }
394
395 void cq_font_answer( start, stop, out )
396     char                *start, *stop;
397     struct papfile      *out;
398 {
399     char                *p, *q, buf[ 256 ];
400     struct ppd_font     *pfo;
401
402     p = start;
403     while ( p < stop ) {
404         unsigned int count = 0;
405         while (( *p == ' ' || *p == '\t' ) && p < stop ) {
406             p++;
407         }
408
409         q = buf;
410         while ( *p != ' ' && *p != '\t' &&
411                 *p != '\n' && *p != '\r' && p < stop && count < sizeof(buf)) {
412             *q++ = *p++;
413             count++;
414         }
415
416         if ( q != buf ) {
417             *q = '\0';
418
419             append( out, "/", 1 );
420             append( out, buf, strlen( buf ));
421             append( out, ":", 1 );
422
423             if (( pfo = ppd_font( buf )) == NULL ) {
424                 append( out, "No\n", 3 );
425             } else {
426                 append( out, "Yes\n", 4 );
427             }
428         }
429     }
430
431     return;
432 }
433
434 int cq_font( in, out )
435     struct papfile      *in, *out;
436 {
437     char                *start, *stop, *p;
438     int                 linelength, crlflength;
439     struct papd_comment *comment = compeek();
440
441     for (;;) {
442         switch ( markline( in, &start, &linelength, &crlflength )) {
443         case 0 :
444             return( 0 );
445
446         case -1 :
447             return( CH_MORE );
448
449         case -2 :
450             return( CH_ERROR );
451         }
452
453         stop = start + linelength;
454
455         if ( comgetflags() == 0 ) {
456             comsetflags( 1 );
457
458             for ( p = start; p < stop; p++ ) {
459                 if ( *p == ':' ) {
460                     break;
461                 }
462             }
463             if (p < stop)
464                 p++;
465
466             cq_font_answer( p, stop, out );
467         } else {
468             if ( comgetflags() == 1 &&
469                     comcmp( start, stop, comcont, 0 ) == 0 ) {
470                 /* continuation */
471
472                 for ( p = start; p < stop; p++ ) {
473                     if ( *p == ' ' ) {
474                         break;
475                     }
476                 }
477                 if (p < stop)
478                     p++;
479
480                 cq_font_answer( p, stop, out );
481             } else {
482                 comsetflags( 2 );
483                 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
484                     append( out, "*\n", 2 );
485                     compop();
486                     CONSUME( in, linelength + crlflength );
487                     return( CH_DONE );
488                 }
489             }
490         }
491
492         CONSUME( in, linelength + crlflength );
493     }
494 }
495
496 int cq_feature( in, out )
497     struct papfile      *in, *out;
498 {
499     char                *start, *stop, *p;
500     int                 linelength, crlflength;
501     struct papd_comment *comment = compeek();
502     struct ppd_feature  *pfe;
503
504     for (;;) {
505         switch ( markline( in, &start, &linelength, &crlflength )) {
506         case 0 :
507             return( 0 );
508
509         case -1 :
510             return( CH_MORE );
511
512         case -2 :
513             return( CH_ERROR );
514         }
515
516         stop = start + linelength;
517
518         if ( comgetflags() == 0 ) {
519             comsetflags( 1 );
520
521             /* parse for feature */
522             for ( p = start; p < stop; p++ ) {
523                 if ( *p == ':' ) {
524                     break;
525                 }
526             }
527             if (p < stop)
528                 p++;
529             while ( *p == ' ' ) {
530                 p++;
531             }
532
533             if (( pfe = ppd_feature( p, stop - p )) == NULL ) {
534                 if ( comswitch( queries, cq_default ) < 0 ) {
535                     LOG(log_error, logtype_papd, "cq_feature: can't find default!" );
536                     exit( 1 );
537                 }
538                 return( CH_DONE );
539             }
540
541             append( out, pfe->pd_value, strlen( pfe->pd_value ));
542             append( out, "\r", 1 );
543         } else {
544             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
545                 compop();
546                 CONSUME( in, linelength + crlflength );
547                 return( CH_DONE );
548             }
549         }
550
551         CONSUME( in, linelength + crlflength );
552     }
553 }
554
555 static const char       *psver = "*PSVersion\n";
556 static const char       *prod = "*Product\n";
557
558 int cq_printer( in, out )
559     struct papfile      *in, *out;
560 {
561     char                *start, *p;
562     int                 linelength, crlflength;
563     struct papd_comment *comment = compeek();
564     struct ppd_feature  *pdpsver, *pdprod;
565
566     for (;;) {
567         switch ( markline( in, &start, &linelength, &crlflength )) {
568         case 0 :
569             return( 0 );
570
571         case -1 :
572             return( CH_MORE );
573
574         case -2 :
575             return( CH_ERROR );
576         }
577
578         if ( comgetflags() == 0 ) {
579             comsetflags( 1 );
580
581             if (( pdpsver = ppd_feature( psver, strlen( psver ))) == NULL ) {
582                 if ( comswitch( queries, cq_default ) < 0 ) {
583                     LOG(log_error, logtype_papd, "cq_printer: can't find default!" );
584                     exit( 1 );
585                 }
586                 return( CH_DONE );
587             }
588
589             for ( p = pdpsver->pd_value; *p != '\0'; p++ ) {
590                 if ( *p == ' ' ) {
591                     break;
592                 }
593             }
594             if ( *p == '\0' ) {
595                 LOG(log_error, logtype_papd, "cq_printer: can't parse PSVersion!" );
596                 if ( comswitch( queries, cq_default ) < 0 ) {
597                     LOG(log_error, logtype_papd, "cq_printer: can't find default!" );
598                     exit( 1 );
599                 }
600                 return( CH_DONE );
601             }
602
603             if (( pdprod = ppd_feature( prod, strlen( prod ))) == NULL ) {
604                 if ( comswitch( queries, cq_default ) < 0 ) {
605                     LOG(log_error, logtype_papd, "cq_printer: can't find default!" );
606                     exit( 1 );
607                 }
608                 return( CH_DONE );
609             }
610
611             /* revision */
612             append( out, p + 1, strlen( p + 1 ));
613             append( out, "\r", 1 );
614
615             /* version */
616             append( out, pdpsver->pd_value, p - pdpsver->pd_value );
617             append( out, "\r", 1 );
618
619             /* product */
620             append( out, pdprod->pd_value, strlen( pdprod->pd_value ));
621             append( out, "\r", 1 );
622         } else {
623             if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
624                 compop();
625                 CONSUME( in, linelength + crlflength );
626                 return( CH_DONE );
627             }
628         }
629
630         CONSUME( in, linelength + crlflength );
631     }
632 }
633
634 #ifndef HAVE_CUPS
635
636 static const char       *rmjobfailed = "Failed\n";
637 static const char       *rmjobok = "Ok\n";
638
639 int cq_rmjob( in, out )
640     struct papfile      *in, *out;
641 {
642     char                *start, *stop, *p;
643     int                 linelength, crlflength;
644     int                 job;
645
646     switch ( markline( in, &start, &linelength, &crlflength )) {
647     case 0 :
648         return( 0 );
649
650     case -1 :
651         return( CH_MORE );
652
653     case -2 :
654         return( CH_ERROR );
655     }
656
657     stop = start + linelength;
658
659     for ( p = start; p < stop; p++ ) {
660         if ( *p == ' ' || *p == '\t' ) {
661             break;
662         }
663     }
664     for ( ; p < stop; p++ ) {
665         if ( *p != ' ' && *p != '\t' ) {
666             break;
667         }
668     }
669
670     *stop = '\0';
671     if ( p < stop && ( job = atoi( p )) > 0 ) {
672         lp_rmjob( job );
673         append( out, rmjobok, strlen( rmjobok ));
674     } else {
675         append( out, rmjobfailed, strlen( rmjobfailed ));
676     }
677
678     compop();
679     CONSUME( in, linelength + crlflength );
680     return( CH_DONE );
681 }
682
683 int cq_listq( in, out )
684     struct papfile      *in, *out;
685 {
686     char                *start;
687     int                 linelength, crlflength;
688
689     switch ( markline( in, &start, &linelength, &crlflength )) {
690     case 0 :
691         return( 0 );
692
693     case -1 :
694         return( CH_MORE );
695
696     case -2 :
697         return( CH_ERROR );
698     }
699
700     if ( lp_queue( out )) {
701         LOG(log_error, logtype_papd, "cq_listq: lp_queue failed" );
702     }
703
704     compop();
705     CONSUME( in, linelength + crlflength );
706     return( CH_DONE );
707 }
708 #endif /* HAVE_CUPS */
709
710
711 /*
712  * Handler for RBILogin
713  */
714
715 static struct uam_obj *papd_uam = NULL;
716 static const char *rbiloginok = "0\r";
717 static const char *rbiloginbad = "-1\r";
718 static const char *rbiloginerrstr = "%%[Error: SecurityError; \
719 SecurityViolation: Unknown user, incorrect password or log on is \
720 disabled ]%%\r%%[Flushing: rest of job (to end-of-file) will be \
721 ignored ]%%\r";
722
723 int cq_rbilogin( in, out )
724     struct papfile      *in, *out;
725 {
726     char                *start, *stop, *p, *begin;
727     int                 linelength, crlflength;
728     char                username[UAM_USERNAMELEN + 1] = "\0";
729     struct papd_comment *comment = compeek();
730     char                uamtype[20];
731
732     for (;;) {
733         switch ( markline( in, &start, &linelength, &crlflength )) {
734         case 0 :
735             return( 0 );
736
737         case -1 :
738             return( CH_MORE );
739
740         case -2 :
741             return( CH_ERROR );
742         }
743
744         stop = start + linelength;
745
746         if ( comgetflags() == 0 ) { /* first line */
747             begin = start + strlen(comment->c_begin);
748             p = begin;
749
750             while (*p != ' ' && p < stop) {
751                 p++;
752             }
753
754             memset(uamtype, 0, sizeof(uamtype));
755             if ((size_t)(p -begin) <= sizeof(uamtype) -1) {
756                 strncpy(uamtype, begin, p - begin);
757             }
758
759             if ( !*uamtype || (papd_uam = auth_uamfind(UAM_SERVER_PRINTAUTH,
760                                 uamtype, strlen(uamtype))) == NULL) {
761                 LOG(log_info, logtype_papd, "Could not find uam: %s", uamtype);
762                 append(out, rbiloginbad, strlen(rbiloginbad));
763                 append(out, rbiloginerrstr, strlen(rbiloginerrstr));
764             } else {
765                 if ( (papd_uam->u.uam_printer(p,stop,username,out)) == 0 ) {
766                     lp_person( username );
767                    append(out, rbiloginok, strlen( rbiloginok ));
768                    LOG(log_info, logtype_papd, "RBILogin: Logged in '%s'", username);
769                 } else {
770                     append(out, rbiloginbad, strlen( rbiloginbad));
771                     append(out, rbiloginerrstr, strlen(rbiloginerrstr));
772                 }
773             }
774             comsetflags( 1 );
775         } else {
776             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
777                 compop();
778                 return( CH_DONE );
779             }
780         }
781
782         CONSUME( in, linelength + crlflength );
783     }
784 }
785
786
787 /*
788  * All queries start with %%?Begin and end with %%?End.  Note that the
789  * "Begin"/"End" general queries have to be last.
790  */
791 struct papd_comment     queries[] = {
792 #ifdef KRB
793     { "%%Login: UMICHKerberosIV", NULL,                 cq_k4login,     0 },
794     { "%%?BeginUAMethodsQuery", "%%?EndUAMethodsQuery:", cq_uameth,C_FULL },
795 #endif /* KRB */
796 #ifndef HAVE_CUPS
797     { "%UMICHListQueue",        NULL,                   cq_listq,  C_FULL },
798     { "%UMICHDeleteJob",        NULL,                   cq_rmjob,       0 },
799 #endif /* HAVE_CUPS */
800     { "%%?BeginQuery: RBILogin ", "%%?EndQuery",        cq_rbilogin,    0 },
801     { "%%?BeginQuery",          "%%?EndQuery",          cq_query,       0 },
802     { "%%?BeginFeatureQuery",   "%%?EndFeatureQuery",   cq_feature,     0 },
803     { "%%?BeginFontQuery",      "%%?EndFontQuery",      cq_font,        0 },
804     { "%%?BeginPrinterQuery",   "%%?EndPrinterQuery",   cq_printer,C_FULL },
805     { "%%?Begin",               "%%?End",               cq_default,     0 },
806     { NULL,                     NULL,                   NULL,           0 },
807 };