source: trunk/third/moira/gen/cups-print.pc @ 23882

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