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