]> andersk Git - moira.git/blob - gen/cups-print.pc
74bcb507a183a417d08ebe5345099658e55ceb08
[moira.git] / gen / cups-print.pc
1 /* $Id$
2  *
3  * This generates printcaps and other files for Athena print servers
4  *
5  * Copyright (C) 1992-1998 by the Massachusetts Institute of Technology.
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include <moira.h>
12 #include <moira_site.h>
13
14 #include <sys/stat.h>
15 #include <sys/types.h>
16
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <string.h>
20
21 #include <time.h>
22 #ifdef HAVE_KRB4
23 #include <krb.h>
24 #endif
25 #include <krb5.h>
26
27 #include "util.h"
28
29 EXEC SQL INCLUDE sqlca;
30
31 RCSID("$Header$");
32
33 char *whoami = "cups-print.gen";
34 char *db = "moira/moira";
35
36 const int krbvers = 5;  /* use Kerberos 5 */
37
38 /* OMG, I hate this, but it's cleaner, I guess? */
39
40 const char *alterjob = "<Limit Hold-Job Release-Job\
41  Restart-Job Purge-Jobs Reprocess-Job Set-Job-Attributes\
42  Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job>";
43 const char *submitjob = "<Limit Create-Job Print-Job Print-URI Send-Document\
44  Set-Job-Attributes Send-URI Create-Job-Subscription Renew-Subscription\
45  Cancel-Subscription Get-Notifications CUPS-Move-Job>";
46 const char *alterpntr = "<Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer\
47  CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>";
48 const char *lpcpntr = "<Limit Pause-Printer Resume-Printer Enable-Printer\
49  Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs\
50  Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer\
51  Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After\
52  CUPS-Accept-Jobs CUPS-Reject-Jobs>";
53 const char *canceljob = "<Limit Cancel-Job CUPS-Authenticate-Job>";
54 const char *catchall = "<Limit All>";
55 const char *phost = "printers.MIT.EDU";
56
57 void do_host(char *host);
58 void sqlerr(void);
59 #ifndef MAX
60 #define MAX(a, b) ( (a) > (b) ? (a) : (b) )
61 #endif
62
63 int main(int argc, char **argv)
64 {
65   EXEC SQL BEGIN DECLARE SECTION;
66   char name[MACHINE_NAME_SIZE];
67   EXEC SQL END DECLARE SECTION;
68
69   init_acls();
70
71   EXEC SQL CONNECT :db;
72
73   EXEC SQL WHENEVER SQLERROR DO sqlerr();
74
75   EXEC SQL DECLARE csr_hosts CURSOR FOR
76     SELECT m.name FROM machine m, serverhosts sh
77     WHERE m.mach_id = sh.mach_id AND sh.service = 'CUPS-PRINT' AND sh.enable = 1;
78   EXEC SQL OPEN csr_hosts;
79   while (1)
80     {
81       EXEC SQL FETCH csr_hosts INTO :name;
82       if (sqlca.sqlcode)
83         break;
84
85       strtrim(name);
86       do_host(name);
87     }
88   EXEC SQL CLOSE csr_hosts;
89
90   exit(MR_SUCCESS);
91 }
92
93 void printer_user_list(FILE *out, char *type, int id, char *str)
94 {
95   struct save_queue *sq;
96   struct imember *m;
97   char kbuf[MAX_K_NAME_SZ];
98   char *cp;
99
100   sq = get_acl(type, id, NULL);
101   while (sq_remove_data(sq, &m))
102     {
103       if (m->type != 'S' && m->type != NULL) {
104         /* CUPS wants mmanley/root, not mmanley.root@ATHENA.MIT.EDU */
105         canon_krb(m, krbvers, kbuf, sizeof(kbuf));
106
107         /* now, take out all the @realm */
108         for (cp=kbuf; *cp; cp++) {
109           if (*cp == '@') *cp = '\0';
110         }
111         fprintf(out, "%s %s\n", str, kbuf);
112       }
113       freeimember(m);
114     }
115   sq_destroy(sq);
116 }
117
118
119
120 void do_host(char *host)
121 {
122   EXEC SQL BEGIN DECLARE SECTION;
123   char rp[PRINTERS_RP_SIZE], name[PRINTERS_NAME_SIZE];
124   char duplexname[PRINTERS_DUPLEXNAME_SIZE], location[PRINTERS_LOCATION_SIZE];
125   char hwtype[PRINTERS_HWTYPE_SIZE], lowerhwtype[PRINTERS_HWTYPE_SIZE];
126   char modtime[PRINTERS_MODTIME_SIZE], lmodtime[LIST_MODTIME_SIZE];
127   char contact[PRINTERS_CONTACT_SIZE], hostname[MACHINE_NAME_SIZE];
128   char cupshosts[MACHINE_NAME_SIZE], prtype [PRINTERS_TYPE_SIZE];
129   char *spoolhost = host, *unixtime_fmt = UNIXTIME_FMT, *p;
130   char *lhost;
131   int ka, pc, ac, lpc_acl, top_lpc_acl, banner, rm;
132   EXEC SQL END DECLARE SECTION;
133   TARFILE *tf;
134   FILE *out;
135   char filename[MAXPATHLEN], *duptc;
136   time_t mtime, now = time(NULL);
137
138   lhost = (char *) strdup (host);
139   for (p = lhost; *p; p++)
140      *p = tolower(*p);
141
142   EXEC SQL SELECT mach_id INTO :rm FROM machine
143     WHERE name = :spoolhost;
144
145   sprintf(filename, "%s/cups-print/%s", DCM_DIR, host);
146   tf = tarfile_open(filename);
147
148   /* printers.conf */
149   out = tarfile_start(tf, "/etc/cups/printers.conf", 0644, 0, 0,
150                       "lp", "lp", now);
151
152   EXEC SQL DECLARE csr_printers CURSOR FOR
153     SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
154     m.name, pr.banner, pr.location, pr.contact, pr.ka,
155     pr.ac, pr.lpc_acl
156     FROM printers pr, machine m
157     WHERE pr.rm = :rm AND m.mach_id = pr.mach_id
158     AND pr.type != 'ALIAS';
159   EXEC SQL OPEN csr_printers;
160   while (1)
161     {
162       EXEC SQL FETCH csr_printers INTO :rp, :name, :duplexname,
163         :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl;
164       if (sqlca.sqlcode)
165         break;
166
167       strtrim(rp);
168       strtrim(name);
169       strtrim(duplexname);
170       strtrim(hwtype);
171       strtrim(hostname);
172       strtrim(location);
173       strtrim(contact);
174       strcpy(lowerhwtype, hwtype);
175       for (p = lowerhwtype; *p; p++)
176         *p = tolower(*p);
177
178       fprintf(out, "<Printer %s>\n",rp);
179       fprintf(out, "Info %s:%s\n", rp, hwtype);
180       /* Note the use of "beh" to keep the CUPS from disabling print queues
181        * should they not respond versus discarding the job.  
182        * See the "beh" page for details.  
183        * The 1/0/60 says "don't disable/try 20 times/try every 60s */
184       if (!strncmp(hwtype, "HP", 2)) 
185           fprintf(out, "DeviceURI beh:/1/20/60/socket://%s:9100\n", hostname);
186       else
187           fprintf(out, "DeviceURI beh:/1/20/60/socket://%s\n", hostname);
188       fprintf(out, "State Idle\n");     // Always with the Idle
189       fprintf(out, "StateTime %ld\n", (long)time(NULL));
190       fprintf(out, "Accepting Yes\n");
191       fprintf(out, "Shared Yes\n");
192       fprintf(out, "QuotaPeriod 0\n");
193       fprintf(out, "PageLimit 0\n");
194       fprintf(out, "Klimit 0\n");
195       fprintf(out, "Option sides one-sided\n");
196       if (location[0])
197         fprintf(out, "Location %s\n", location);
198       fprintf(out, "ErrorPolicy abort-job\n");
199       if (ka || lpc_acl)
200         fprintf(out, "OpPolicy %s-policy\n", rp);
201       else
202         fprintf(out, "OpPolicy default\n");
203
204       /* Access-control list. */
205       if (ac)
206         {
207           if (ka)
208             fprintf(out, "AuthType Negotiate\n");
209           else
210             fprintf(out, "AuthType Default\n");
211           printer_user_list(out, "LIST", ac, "AllowUser");
212         }
213
214       if (banner == PRN_BANNER_NONE)
215         fprintf(out, "JobSheets none none\n");
216       else 
217         fprintf(out, "JobSheets athena none\n");
218       fprintf(out, "</Printer>\n");
219
220     }
221   EXEC SQL CLOSE csr_printers;
222   tarfile_end(tf);
223
224
225   /* aliases are in classes.conf */
226   out = tarfile_start(tf, "/etc/cups/classes.conf", 0644, 0, 0,
227                   "lp", "lp", now);
228   EXEC SQL DECLARE csr_duplexqs CURSOR FOR
229     SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
230     m.name, pr.banner, pr.location, pr.contact, pr.ka, 
231     pr.type as prtype, pr.ac
232     FROM printers pr, machine m
233     WHERE pr.rm = :rm AND m.mach_id = pr.mach_id;
234   EXEC SQL OPEN csr_duplexqs;
235   while (1)
236     {
237       EXEC SQL FETCH csr_duplexqs INTO :rp, :name, :duplexname,
238         :hwtype, :hostname, :banner, :location, :contact, :ka, :prtype, :ac;
239       if (sqlca.sqlcode)
240         break;
241
242       strtrim(hwtype);
243       strtrim(rp);
244       strtrim(location);
245       strtrim(contact);
246       strtrim(prtype);
247
248       /* Define alias queues as classes to the regular queues for
249        * accounting reasons.  Annoyingly, classes don't always inherit
250        * their printer definitions.
251       */
252       if (!strcmp(prtype,"ALIAS")) 
253         {
254           strtrim(name);
255           fprintf(out, "<Class %s>\n",name);
256           fprintf(out, "Info Alias Queue to %s:%s\n", rp, hwtype);
257           fprintf(out, "Printer %s\n", rp);
258           fprintf(out, "Option sides one-sided\n");
259           fprintf(out, "State Idle\n");     // Always with the Idle
260           fprintf(out, "StateTime %ld\n", (long)time(NULL));
261           fprintf(out, "Accepting Yes\n");
262           fprintf(out, "Shared Yes\n");
263           fprintf(out, "QuotaPeriod 0\n");
264           fprintf(out, "PageLimit 0\n");
265           if (location[0])
266             fprintf(out, "Location %s\n", location);
267           fprintf(out, "ErrorPolicy abort-job\n");
268           if (ka || lpc_acl)
269             fprintf(out, "OpPolicy %s-policy\n", rp);
270           else
271             fprintf(out, "OpPolicy default\n");
272     
273           /* Access-control list. */
274           if (ac)
275             {
276               if (ka)
277                 fprintf(out, "AuthType Negotiate\n");
278               else
279                 fprintf(out, "AuthType Default\n");
280               printer_user_list(out, "LIST", ac, "AllowUser");
281             }
282     
283           if (banner == PRN_BANNER_NONE)
284             fprintf(out, "JobSheets none none\n");
285           else 
286             fprintf(out, "JobSheets athena none\n");
287           fprintf(out, "</Class>\n");
288       }
289
290       /* Define duplex queues as aliases to the regular queues for
291        * accounting reasons.  Annoyingly, classes don't always inherit
292        * their printer definitions.
293       */
294       if (*duplexname)
295         {
296           strtrim(duplexname);
297           fprintf(out, "<Class %s>\n",duplexname);
298           if (!strcmp(prtype,"ALIAS")) 
299             fprintf(out, "Info Duplex Alias Queue to %s:%s\n", rp, hwtype);
300           else
301             fprintf(out, "Info Duplex Queue for %s:%s\n", rp, hwtype);
302           fprintf(out, "Option sides two-sided-long-edge\n");   // duplex
303           fprintf(out, "Printer %s\n", rp);
304           fprintf(out, "State Idle\n");     // Always with the Idle
305           fprintf(out, "StateTime %ld\n", (long)time(NULL));
306           fprintf(out, "Accepting Yes\n");
307           fprintf(out, "Shared Yes\n");
308           fprintf(out, "QuotaPeriod 0\n");
309           fprintf(out, "PageLimit 0\n");
310           if (location[0])
311             fprintf(out, "Location %s\n", location);
312           fprintf(out, "ErrorPolicy abort-job\n");
313           if (ka || lpc_acl)
314             fprintf(out, "OpPolicy %s-policy\n", rp);
315           else
316             fprintf(out, "OpPolicy default\n");
317     
318           /* Access-control list. */
319           if (ac)
320             {
321               if (ka)
322                 fprintf(out, "AuthType Negotiate\n");
323               else
324                 fprintf(out, "AuthType Default\n");
325               printer_user_list(out, "LIST", ac, "AllowUser");
326             }
327     
328           if (banner == PRN_BANNER_NONE)
329             fprintf(out, "JobSheets none none\n");
330           else if (banner == PRN_BANNER_LAST)
331             fprintf(out, "JobSheets athena none\n");
332           fprintf(out, "</Class>\n");
333         }
334     }
335   EXEC SQL CLOSE csr_duplexqs;
336   tarfile_end(tf);
337
338   /* cups.conf */
339   out = tarfile_start(tf, "/etc/cups/cupsd.conf", 0755, 1, 1,
340                       "root", "lp", now);
341
342   fprintf(out, "LogLevel info\n");
343   fprintf(out, "SystemGroup sys root ops-group\n");
344   fprintf(out, "Port 631\n");
345   fprintf(out, "Listen /var/run/cups/cups.sock\n");
346   fprintf(out, "Browsing On\n");
347   fprintf(out, "BrowseOrder allow,deny\n");
348   fprintf(out, "BrowseAllow all\n");
349   fprintf(out, "BrowseAddress @LOCAL\n");
350   fprintf(out, "DefaultAuthType Negotiate\n");
351   fprintf(out, "ServerCertificate /etc/cups/ssl/%s-ipp-crt.pem\n", lhost);
352   fprintf(out, "ServerKey /etc/cups/ssl/%s-ipp-key.pem\n", lhost);
353   fprintf(out, "ServerName %s\n", lhost);
354   fprintf(out, "ServerAlias %s\n", phost);
355   fprintf(out, "Krb5Keytab /etc/krb5-ipp.keytab\n");
356
357   /* The other CUPS servers should be aware of the other hosts'
358      queues, so we'll let them browse each other. */
359   fprintf(out, "Include cups.local.conf\n");
360   fprintf(out, "Include cups.locations.conf\n");
361   fprintf(out, "Include cups.policies.conf\n");
362   tarfile_end(tf);
363
364   /* cups.hosts.conf */
365   out = tarfile_start(tf, "/etc/cups/cups.hosts.conf", 0755, 1, 1,
366                       "root", "lp", now);
367   EXEC SQL DECLARE csr_cupshosts CURSOR FOR
368     SELECT m.name AS cupshosts FROM machine m, printservers ps
369     WHERE m.mach_id = ps.mach_id AND ps.kind = 'CUPS';
370   EXEC SQL OPEN csr_cupshosts;
371   while (1)
372     {
373       EXEC SQL FETCH csr_cupshosts INTO :cupshosts;
374       if (sqlca.sqlcode)
375         break;
376
377       strtrim(cupshosts);
378
379       /* Don't poll yourself looking for answers! */
380       if (strcmp(cupshosts,host))
381          fprintf(out, "BrowsePoll %s\n", cupshosts);
382     }
383   EXEC SQL CLOSE csr_cupshosts;
384
385   tarfile_end(tf);
386
387   /* cups.policies.conf */
388   out = tarfile_start(tf, "/etc/cups/cups.policies.conf", 0755, 1, 1,
389                       "root", "lp", now);
390   fprintf(out, "# Printer-specific LPC and LPR ACLs\n");
391   /* lpcaccess.top */
392   EXEC SQL SELECT ps.lpc_acl INTO :top_lpc_acl
393     FROM printservers ps, machine m
394     WHERE m.name = :spoolhost AND m.mach_id = ps.mach_id;
395   if (!sqlca.sqlcode && lpc_acl)
396     {
397       fprintf (out, "<Policy default>\n");
398       fprintf (out, "%s\n", alterjob);
399       fprintf (out, "AuthType Default\n");
400       fprintf (out, "Require user @OWNER @SYSTEM\n");
401       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
402       fprintf (out, "Order deny,allow\n");
403       fprintf (out, "</Limit>\n");
404       fprintf (out, "%s\n", submitjob);
405       fprintf (out, "AuthType None\n");
406       fprintf (out, "Order deny,allow\n");
407       fprintf (out, "Allow from all\n");
408       fprintf (out, "</Limit>\n");
409       fprintf (out, "%s\n", alterpntr);
410       fprintf (out, "AuthType Default\n");
411       fprintf (out, "Require user @SYSTEM\n");
412       fprintf (out, "Order deny,allow\n");
413       fprintf (out, "</Limit>\n");
414       fprintf (out, "%s\n", lpcpntr);
415       fprintf (out, "AuthType Default\n");
416       fprintf (out, "Require user @SYSTEM\n");
417       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
418       fprintf (out, "Order deny,allow\n");
419       fprintf (out, "</Limit>\n");
420       fprintf (out, "%s\n", canceljob);
421       fprintf (out, "AuthType Default\n");
422       fprintf (out, "Require user @OWNER @SYSTEM\n");
423       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
424       fprintf (out, "Order deny,allow\n");
425       fprintf (out, "Allow from all\n");
426       fprintf (out, "</Limit>\n");
427       fprintf (out, "%s\n", catchall);
428       fprintf (out, "AuthType None\n");
429       fprintf (out, "Order deny,allow\n");
430       fprintf (out, "Allow from all\n");
431       fprintf (out, "</Limit>\n");
432       fprintf (out, "</Policy>\n");
433     }
434
435   /* restrict lists and lpcaccess policies.  Sadly, we have to put the
436      top level for each new policy since CUPS doesn't have a way of 
437      doing it otherwise (well, Unix groups, but not moira) */
438   EXEC SQL DECLARE csr_lpc CURSOR FOR
439     SELECT UNIQUE rp, ka, ac, lpc_acl
440     FROM printers
441     WHERE rm = :rm AND ( ac != 0 OR lpc_acl != 0);
442   EXEC SQL OPEN csr_lpc;
443   while (1)
444     {
445       EXEC SQL FETCH csr_lpc INTO :name, :ka, :ac, :lpc_acl;
446       if (sqlca.sqlcode)
447         break;
448
449       strtrim(name);
450
451       fprintf (out, "<Policy %s-policy>\n", name);
452       fprintf (out, "%s\n", alterjob);
453       fprintf (out, "AuthType Default\n");
454       fprintf (out, "Require user @OWNER @SYSTEM\n");
455       printer_user_list(out, "LIST", lpc_acl, "Require user");
456       fprintf (out, "Order deny,allow\n");
457       fprintf (out, "Allow from all\n");
458       fprintf (out, "</Limit>\n");
459       fprintf (out, "%s\n", submitjob);
460       /* If the printer is Kerberized? */
461       if (ka)
462         fprintf (out, "AuthType Negotiate\n");
463       else
464         fprintf (out, "AuthType None\n");
465       /* Access-control list. */
466       if (ac)
467         printer_user_list(out, "LIST", ac, "Require user");
468       else if (ka)
469         fprintf (out, "Require valid-user\n");
470       fprintf (out, "Order deny,allow\n");
471       fprintf (out, "Allow from all\n");
472       fprintf (out, "</Limit>\n");
473       fprintf (out, "%s\n", alterpntr);
474       fprintf (out, "AuthType Default\n");
475       fprintf (out, "Require user @SYSTEM\n");
476       fprintf (out, "Order deny,allow\n");
477       fprintf (out, "</Limit>\n");
478       fprintf (out, "%s\n", lpcpntr);
479       fprintf (out, "AuthType Default\n");
480       fprintf (out, "Require user @SYSTEM\n");
481       /* printer-specific lpc access. */
482       if (lpc_acl)
483           printer_user_list(out, "LIST", lpc_acl, "Require user");
484       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
485       fprintf (out, "Order deny,allow\n");
486       fprintf (out, "</Limit>\n");
487       fprintf (out, "%s\n", canceljob);
488       fprintf (out, "AuthType Default\n");
489       fprintf (out, "Require user @OWNER @SYSTEM\n");
490       printer_user_list(out, "LIST", lpc_acl, "Require user");
491       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
492       fprintf (out, "Order deny,allow\n");
493       fprintf (out, "Allow from all\n");
494       fprintf (out, "</Limit>\n");
495       fprintf (out, "%s\n", catchall);
496       fprintf (out, "AuthType None\n");
497       fprintf (out, "Order deny,allow\n");
498       fprintf (out, "Allow from all\n");
499       fprintf (out, "</Limit>\n");
500       fprintf (out, "</Policy>\n");
501     }
502   EXEC SQL CLOSE csr_lpc;
503   fprintf(out, "\n");
504   tarfile_end(tf);
505   tarfile_close(tf);
506 }
507
508 void sqlerr(void)
509 {
510   db_error(sqlca.sqlcode);
511 }
This page took 0.124313 seconds and 3 git commands to generate.