]> andersk Git - moira.git/blame - gen/cups-print.pc
More permission tweaking.
[moira.git] / gen / cups-print.pc
CommitLineData
f50216d7 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#include <krb.h>
23#include <krb5.h>
24
25#include "util.h"
26
27
28
29EXEC SQL INCLUDE sqlca;
30
31RCSID("$Header$");
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 Send-Document Send-URI Hold-Job Release-Job\
39 Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription\
40 Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job\
41 Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job>";
42const char *submitjob = "<Limit Create-Job Print-Job Print-URI>";
43const char *alterpntr = "<Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer\
44 CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>";
45const char *lpcpntr = "<Limit Pause-Printer Resume-Printer Enable-Printer\
46 Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs\
47 Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer\
48 Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After\
49 CUPS-Accept-Jobs CUPS-Reject-Jobs>";
50const char *canceljob = "<Limit Cancel-Job CUPS-Authenticate-Job>";
51const char *catchall = "<Limit All>";
52
53void do_host(char *host);
54void sqlerr(void);
55#ifndef MAX
56#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
57#endif
58
59int main(int argc, char **argv)
60{
61 EXEC SQL BEGIN DECLARE SECTION;
62 char name[MACHINE_NAME_SIZE];
63 EXEC SQL END DECLARE SECTION;
64
65 init_acls();
66
67 EXEC SQL CONNECT :db;
68
69 EXEC SQL WHENEVER SQLERROR DO sqlerr();
70
71 EXEC SQL DECLARE csr_hosts CURSOR FOR
72 SELECT m.name FROM machine m, serverhosts sh
c3c53552 73 WHERE m.mach_id = sh.mach_id AND sh.service = 'CUPS-PRINT' AND sh.enable = 1;
f50216d7 74 EXEC SQL OPEN csr_hosts;
75 while (1)
76 {
77 EXEC SQL FETCH csr_hosts INTO :name;
78 if (sqlca.sqlcode)
79 break;
80
81 strtrim(name);
82 do_host(name);
83 }
84 EXEC SQL CLOSE csr_hosts;
85
86 exit(MR_SUCCESS);
87}
88
89void printer_user_list(FILE *out, char *type, int id, char *str)
90{
91 struct save_queue *sq;
92 struct imember *m;
93
94 sq = get_acl(type, id, NULL);
95 while (sq_remove_data(sq, &m))
96 {
97 if (m->type == 'U')
98 fprintf(out, "%s %s\n", str, m->name);
99 freeimember(m);
100 }
101 sq_destroy(sq);
102}
103
104
105
106void do_host(char *host)
107{
108 EXEC SQL BEGIN DECLARE SECTION;
109 char rp[PRINTERS_RP_SIZE], name[PRINTERS_NAME_SIZE];
110 char duplexname[PRINTERS_DUPLEXNAME_SIZE], location[PRINTERS_LOCATION_SIZE];
111 char hwtype[PRINTERS_HWTYPE_SIZE], lowerhwtype[PRINTERS_HWTYPE_SIZE];
112 char modtime[PRINTERS_MODTIME_SIZE], lmodtime[LIST_MODTIME_SIZE];
113 char contact[PRINTERS_CONTACT_SIZE], hostname[MACHINE_NAME_SIZE];
114 char cupshosts[MACHINE_NAME_SIZE], prtype [PRINTERS_TYPE_SIZE];
115 char *spoolhost = host, *unixtime_fmt = UNIXTIME_FMT, *p;
116 char *lhost;
117 int ka, pc, ac, lpc_acl, top_lpc_acl, banner, rm;
118 EXEC SQL END DECLARE SECTION;
119 TARFILE *tf;
120 FILE *out;
121 char filename[MAXPATHLEN], *duptc;
122 time_t mtime, now = time(NULL);
123
124 lhost = (char *) strdup (host);
125 for (p = lhost; *p; p++)
126 *p = tolower(*p);
127
128 EXEC SQL SELECT mach_id INTO :rm FROM machine
129 WHERE name = :spoolhost;
130
c3c53552 131 sprintf(filename, "%s/cups-print/%s", DCM_DIR, host);
f50216d7 132 tf = tarfile_open(filename);
133
134 /* printers.conf */
135 out = tarfile_start(tf, "/etc/cups/printers.conf", 0644, 0, 0,
136 "root", "lp", now);
137
138 EXEC SQL DECLARE csr_printers CURSOR FOR
139 SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
140 m.name, pr.banner, pr.location, pr.contact, pr.ka,
141 pr.ac
142 FROM printers pr, machine m
143 WHERE pr.rm = :rm AND m.mach_id = pr.mach_id
144 AND pr.type != 'ALIAS';
145 EXEC SQL OPEN csr_printers;
146 while (1)
147 {
148 EXEC SQL FETCH csr_printers INTO :rp, :name, :duplexname,
149 :hwtype, :hostname, :banner, :location, :contact, :ka, :ac;
150 if (sqlca.sqlcode)
151 break;
152
153 strtrim(rp);
154 strtrim(name);
155 strtrim(duplexname);
156 strtrim(hwtype);
157 strtrim(hostname);
158 strtrim(location);
159 strtrim(contact);
160 strcpy(lowerhwtype, hwtype);
161 for (p = lowerhwtype; *p; p++)
162 *p = tolower(*p);
163
164 fprintf(out, "<Printer %s>\n",rp);
165 fprintf(out, "Info %s:%s\n", rp, hwtype);
166 /* Note the use of "beh" to keep the CUPS from disabling print queues
167 * should they not respond versus discarding the job.
168 * See the "beh" page for details.
169 * The 1/0/60 says "don't disable/try 20 times/try every 60s */
170 if (!strncmp(hwtype, "HP", 2))
171 fprintf(out, "DeviceURI beh:/1/20/60/socket://%s:9100\n", hostname);
172 else
173 fprintf(out, "DeviceURI beh:/1/20/60/socket://%s\n", hostname);
174 fprintf(out, "State Idle\n"); // Always with the Idle
175 fprintf(out, "StateTime %ld\n", (long)time(NULL));
176 fprintf(out, "Accepting Yes\n");
177 fprintf(out, "Shared Yes\n");
178 fprintf(out, "QuotaPeriod 0\n");
179 fprintf(out, "PageLimit 0\n");
180 fprintf(out, "Klimit 0\n");
181 fprintf(out, "Option sides one-sided\n");
182 if (location[0])
183 fprintf(out, "Location %s\n", location);
184 fprintf(out, "ErrorPolicy abort-job\n");
185 if (! ka || ! lpc_acl)
186 fprintf(out, "OpPolicy default\n");
187 else
188 fprintf(out, "OpPolicy %s-policy\n", rp);
189
190 /* Access-control list. */
191 if (ac)
192 {
193 if (ka)
194 fprintf(out, "AuthType Negotiate\n");
195 else
196 fprintf(out, "AuthType Negotiate\n");
197 printer_user_list(out, "LIST", ac, "AllowUser");
198 }
199
200 if (banner == PRN_BANNER_NONE)
201 fprintf(out, "JobSheets none none\n");
202 else
203 fprintf(out, "JobSheets athena none\n");
204 fprintf(out, "</Printer>\n");
205
206 }
207 EXEC SQL CLOSE csr_printers;
208 tarfile_end(tf);
209
210
211 /* aliases are in classes.conf */
212 out = tarfile_start(tf, "/etc/cups/classes.conf", 0644, 0, 0,
213 "root", "root", now);
214 EXEC SQL DECLARE csr_duplexqs CURSOR FOR
215 SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
216 m.name, pr.banner, pr.location, pr.contact, pr.ka,
217 pr.type as prtype, pr.ac
218 FROM printers pr, machine m
219 WHERE pr.rm = :rm AND m.mach_id = pr.mach_id;
220 EXEC SQL OPEN csr_duplexqs;
221 while (1)
222 {
223 EXEC SQL FETCH csr_duplexqs INTO :rp, :name, :duplexname,
224 :hwtype, :hostname, :banner, :location, :contact, :ka, :prtype, :ac;
225 if (sqlca.sqlcode)
226 break;
227
228 strtrim(hwtype);
229 strtrim(rp);
230 strtrim(location);
231 strtrim(contact);
232 strtrim(prtype);
233
234 /* Define alias queues as classes to the regular queues for
235 * accounting reasons. Annoyingly, classes don't always inherit
236 * their printer definitions.
237 */
238 if (!strcmp(prtype,"ALIAS"))
239 {
240 strtrim(name);
241 fprintf(out, "<Class %s>\n",name);
242 fprintf(out, "Info Alias Queue to %s:%s\n", rp, hwtype);
243 fprintf(out, "Printer %s\n", rp);
244 fprintf(out, "Option sides one-sided\n");
245 fprintf(out, "State Idle\n"); // Always with the Idle
246 fprintf(out, "StateTime %ld\n", (long)time(NULL));
247 fprintf(out, "Accepting Yes\n");
248 fprintf(out, "Shared Yes\n");
249 fprintf(out, "QuotaPeriod 0\n");
250 fprintf(out, "PageLimit 0\n");
251 if (location[0])
252 fprintf(out, "Location %s\n", location);
253 fprintf(out, "ErrorPolicy abort-job\n");
254 if (! ka || ! lpc_acl)
255 fprintf(out, "OpPolicy default\n");
256 else
257 fprintf(out, "OpPolicy %s-policy\n", rp);
258
259 /* Access-control list. */
260 if (ac)
261 {
262 if (ka)
263 fprintf(out, "AuthType Negotiate\n");
264 else
265 fprintf(out, "AuthType Negotiate\n");
266 printer_user_list(out, "LIST", ac, "AllowUser");
267 }
268
269 if (banner == PRN_BANNER_NONE)
270 fprintf(out, "JobSheets none none\n");
271 else
272 fprintf(out, "JobSheets athena none\n");
273 fprintf(out, "</Class>\n");
274 }
275
276 /* Define duplex queues as aliases to the regular queues for
277 * accounting reasons. Annoyingly, classes don't always inherit
278 * their printer definitions.
279 */
280 if (*duplexname)
281 {
282 strtrim(duplexname);
283 fprintf(out, "<Class %s>\n",duplexname);
284 if (!strcmp(prtype,"ALIAS"))
285 fprintf(out, "Info Duplex Alias Queue to %s:%s\n", rp, hwtype);
286 else
287 fprintf(out, "Info Duplex Queue for %s:%s\n", rp, hwtype);
288 fprintf(out, "Option sides two-sided-long-edge\n"); // duplex
289 fprintf(out, "Printer %s\n", rp);
290 fprintf(out, "State Idle\n"); // Always with the Idle
291 fprintf(out, "StateTime %ld\n", (long)time(NULL));
292 fprintf(out, "Accepting Yes\n");
293 fprintf(out, "Shared Yes\n");
294 fprintf(out, "QuotaPeriod 0\n");
295 fprintf(out, "PageLimit 0\n");
296 if (location[0])
297 fprintf(out, "Location %s\n", location);
298 fprintf(out, "ErrorPolicy abort-job\n");
299 if (! ka || ! lpc_acl)
300 fprintf(out, "OpPolicy default\n");
301 else
302 fprintf(out, "OpPolicy %s-policy\n", rp);
303
304 /* Access-control list. */
305 if (ac)
306 {
307 if (ka)
308 fprintf(out, "AuthType Negotiate\n");
309 else
310 fprintf(out, "AuthType Negotiate\n");
311 printer_user_list(out, "LIST", ac, "AllowUser");
312 }
313
314 if (banner == PRN_BANNER_NONE)
315 fprintf(out, "JobSheets none none\n");
316 else if (banner == PRN_BANNER_LAST)
317 fprintf(out, "JobSheets athena none\n");
318 fprintf(out, "</Class>\n");
319 }
320 }
321 EXEC SQL CLOSE csr_duplexqs;
322 tarfile_end(tf);
323
324 /* cups.conf */
325 out = tarfile_start(tf, "/etc/cups/cupsd.conf", 0755, 1, 1,
326 "root", "lp", now);
327
328 fprintf(out, "LogLevel info\n");
329 fprintf(out, "SystemGroup sys root ops-group\n");
330 fprintf(out, "Port 631\n");
331 fprintf(out, "Listen /var/run/cups/cups.sock\n");
332 fprintf(out, "Browsing On\n");
333 fprintf(out, "BrowseOrder allow,deny\n");
334 fprintf(out, "BrowseAllow all\n");
335 fprintf(out, "BrowseAddress @LOCAL\n");
336 fprintf(out, "DefaultAuthType Negotiate\n");
337 fprintf(out, "ServerCertificate /etc/cups/ssl/%s-ipp-crt.pem\n", lhost);
338 fprintf(out, "ServerKey /etc/cups/ssl/%s-ipp-key.pem\n", lhost);
339 fprintf(out, "ServerName %s\n", lhost);
340 fprintf(out, "Krb5Keytab /etc/krb5-ipp.keytab\n");
341 fprintf(out, "Browsing On\n");
342 fprintf(out, "BrowseProtocols cups\n");
343
344 /* The other CUPS servers should be aware of the other hosts'
345 queues, so we'll let them browse each other. */
346
347 EXEC SQL DECLARE csr_cupshosts CURSOR FOR
348 SELECT m.name AS cupshosts FROM machine m, printservers ps
349 WHERE m.mach_id = ps.mach_id AND ps.kind = 'CUPS';
350 EXEC SQL OPEN csr_cupshosts;
351 while (1)
352 {
353 EXEC SQL FETCH csr_cupshosts INTO :cupshosts;
354 if (sqlca.sqlcode)
355 break;
356
357 strtrim(cupshosts);
358
359 /* Don't poll yourself looking for answers! */
360 if (strcmp(cupshosts,host))
361 fprintf(out, "BrowsePoll %s\n", cupshosts);
362 }
363 EXEC SQL CLOSE csr_cupshosts;
364 fprintf(out, "Include cups.locations.conf\n");
365 fprintf(out, "Include cups.policies.conf\n");
366
367 tarfile_end(tf);
368
369 /* cups.policies.conf */
370 out = tarfile_start(tf, "/etc/cups/cups.policies.conf", 0755, 1, 1,
371 "root", "lp", now);
372 fprintf(out, "# Printer-specific LPC and LPR ACLs\n");
373 /* lpcaccess.top */
374 EXEC SQL SELECT ps.lpc_acl INTO :top_lpc_acl
375 FROM printservers ps, machine m
376 WHERE m.name = :spoolhost AND m.mach_id = ps.mach_id;
377 if (!sqlca.sqlcode && lpc_acl)
378 {
379 fprintf (out, "<Policy default>\n");
380 fprintf (out, "%s\n", alterjob);
381 fprintf (out, "AuthType Default\n");
382 fprintf (out, "Require user @OWNER @SYSTEM\n");
383 printer_user_list(out, "LIST", top_lpc_acl, "Require user");
384 fprintf (out, "Order deny,allow\n");
385 fprintf (out, "</Limit>\n");
386 fprintf (out, "%s\n", submitjob);
11bc6bdc 387 fprintf (out, "AuthType None\n");
f50216d7 388 fprintf (out, "Order deny,allow\n");
11bc6bdc 389 fprintf (out, "Allow from all\n");
f50216d7 390 fprintf (out, "</Limit>\n");
391 fprintf (out, "%s\n", alterpntr);
392 fprintf (out, "AuthType Default\n");
393 fprintf (out, "Require user @SYSTEM\n");
394 fprintf (out, "Order deny,allow\n");
395 fprintf (out, "</Limit>\n");
396 fprintf (out, "%s\n", lpcpntr);
397 fprintf (out, "AuthType Default\n");
398 fprintf (out, "Require user @SYSTEM\n");
399 printer_user_list(out, "LIST", top_lpc_acl, "Require user");
400 fprintf (out, "Order deny,allow\n");
401 fprintf (out, "</Limit>\n");
402 fprintf (out, "%s\n", canceljob);
403 fprintf (out, "AuthType Default\n");
404 fprintf (out, "Require user @OWNER @SYSTEM\n");
405 printer_user_list(out, "LIST", top_lpc_acl, "Require user");
406 fprintf (out, "Order deny,allow\n");
03e05c1a 407 fprintf (out, "Allow from all\n");
408 fprintf (out, "AuthType None\n");
f50216d7 409 fprintf (out, "</Limit>\n");
11bc6bdc 410 fprintf (out, "AuthType None\n");
f50216d7 411 fprintf (out, "%s\n", catchall);
412 fprintf (out, "Order deny,allow\n");
11bc6bdc 413 fprintf (out, "Allow from all\n");
f50216d7 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");
03e05c1a 440 fprintf (out, "Allow from all\n");
f50216d7 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");
11bc6bdc 454 fprintf (out, "Allow from all\n");
f50216d7 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");
11bc6bdc 476 fprintf (out, "Allow from all\n");
f50216d7 477 fprintf (out, "</Limit>\n");
478 fprintf (out, "%s\n", catchall);
11bc6bdc 479 fprintf (out, "AuthType None\n");
f50216d7 480 fprintf (out, "Order deny,allow\n");
11bc6bdc 481 fprintf (out, "Allow from all\n");
f50216d7 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}
This page took 0.108723 seconds and 5 git commands to generate.