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