char *db = "moira/moira";
void do_host(char *host);
-void dump_acl(FILE *out, int id, int realms);
void sqlerr(void);
#ifndef MAX
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
char name[MACHINE_NAME_SIZE];
EXEC SQL END DECLARE SECTION;
+ init_acls();
+
EXEC SQL CONNECT :db;
EXEC SQL WHENEVER SQLERROR DO sqlerr();
EXEC SQL BEGIN DECLARE SECTION;
char rp[PRINTERS_RP_SIZE], name[PRINTERS_NAME_SIZE];
char duplexname[PRINTERS_DUPLEXNAME_SIZE], location[PRINTERS_LOCATION_SIZE];
- char hwtype[PRINTERS_HWTYPE_SIZE], hostname[MACHINE_NAME_SIZE];
- char rm[MACHINE_NAME_SIZE], rq[MACHINE_NAME_SIZE];
+ char hwtype[PRINTERS_HWTYPE_SIZE], lowerhwtype[PRINTERS_HWTYPE_SIZE];
char modtime[PRINTERS_MODTIME_SIZE], lmodtime[LIST_MODTIME_SIZE];
- char contact[PRINTERS_CONTACT_SIZE];
- char *spoolhost = host, *unixtime_fmt = UNIXTIME_FMT;
- int ka, pc, ac, lpc_acl, banner;
+ char contact[PRINTERS_CONTACT_SIZE], hostname[MACHINE_NAME_SIZE];
+ char *spoolhost = host, *unixtime_fmt = UNIXTIME_FMT, *p;
+ int ka, pc, ac, lpc_acl, banner, rm;
EXEC SQL END DECLARE SECTION;
TARFILE *tf;
FILE *out;
- char filename[MAXPATHLEN];
+ char filename[MAXPATHLEN], *duptc;
time_t mtime, now = time(NULL);
+ EXEC SQL SELECT mach_id INTO :rm FROM machine
+ WHERE name = :spoolhost;
+
sprintf(filename, "%s/print/%s", DCM_DIR, host);
tf = tarfile_open(filename);
+ /* printcap */
out = tarfile_start(tf, "/etc/printcap.moira", 0644, 0, 0,
"root", "root", now);
EXEC SQL DECLARE csr_printcap CURSOR FOR
SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
- m.name, mrm.name, mrq.name, pr.ka, pr.pc, pr.ac,
- pr.location, pr.contact
- FROM printers pr, machine m, machine mrm, machine mrq
- WHERE m.mach_id = pr.mach_id AND mrq.mach_id = pr.rq
- AND mrm.mach_id = pr.rm AND mrm.name = :spoolhost
- AND pr.type != 'ALIAS';
+ m.name, pr.banner, pr.location, pr.contact
+ FROM printers pr, machine m
+ WHERE pr.rm = :rm AND m.mach_id = pr.mach_id
+ AND pr.type != 'ALIAS'
+ AND ( pr.hwtype LIKE 'HP%' OR pr.hwtype LIKE 'LPR%' );
EXEC SQL OPEN csr_printcap;
while (1)
{
EXEC SQL FETCH csr_printcap INTO :rp, :name, :duplexname,
- :hwtype, :hostname, :rm, :rq, :ka, :pc, :ac, :location, :contact;
+ :hwtype, :hostname, :banner, :location, :contact;
if (sqlca.sqlcode)
break;
strtrim(duplexname);
strtrim(hwtype);
strtrim(hostname);
- strtrim(rm);
- strtrim(rq);
strtrim(location);
strtrim(contact);
+ strcpy(lowerhwtype, hwtype);
+ for (p = lowerhwtype; *p; p++)
+ *p = tolower(*p);
if (location[0])
fprintf(out, "# %s: %s\n", name, location);
if (strcmp(location, contact))
fprintf(out, "# contact: %s\n", contact);
- fprintf(out, "%s|%s %s", rp, location, hwtype);
- if (*duplexname)
- fprintf(out, "|%s", duplexname);
- fprintf(out, ":\\\n\t:lp=/dev/null:rp=%s:rm=%s:\\\n"
- "\t:sd=/var/spool/printer/%s:\\\n"
- "\t:lf=/var/spool/printer/%s/%s-log:\\\n"
- "\t:af=/var/spool/printer/%s/%s-acct:\\\n"
- "\t:ka#%d:pc#%d:\\\n",
- !strcmp(hwtype, "LPR") ? "raw" : rp,
- !strncmp(hwtype, "HP", 2) ? rm : hostname,
- rp, rp, rp, rp, rp, ka, pc);
- if (strcmp(rq, "[NONE]"))
- fprintf(out, "\t:rq=%s:\\\n", rq);
- if (ac)
- fprintf(out, "\t:ac=/var/spool/printer/%s/restrict.list:pa:\\\n", rp);
+ fprintf(out, "%s\n\t:server:cm=%s %s\n\t", rp, hwtype, location);
+ if (banner == PRN_BANNER_NONE)
+ fprintf(out, ":sh");
+ else if (banner == PRN_BANNER_LAST)
+ fprintf(out, ":hl");
if (!strncmp(hwtype, "HP", 2))
{
- fprintf(out, "\t:if=/usr/athena/lib/lpdfilters/hpif:\\\n"
- "\t:of=/usr/athena/lib/lpdfilters/hpof:\\\n"
- "\t:gf=/usr/athena/lib/lpdfilters/hpgf:\\\n"
- "\t:nf=/usr/athena/lib/lpdfilters/hpnf:\\\n"
- "\t:tf=/usr/athena/lib/lpdfilters/hptf:\\\n"
- "\t:rf=/usr/athena/lib/lpdfilters/hprf:\\\n"
- "\t:vf=/usr/athena/lib/lpdfilters/hpvf:\\\n"
- "\t:cf=/usr/athena/lib/lpdfilters/hpcf:\\\n"
- "\t:df=/usr/athena/lib/lpdfilters/hpdf:\\\n"
- "\t:sf:sb:mx#0:\n\n");
+ fprintf(out, ":lp=%s%%9100:ifhp=model=%s:tc=.hp\n\n",
+ hostname, lowerhwtype);
+ duptc = ".hp2";
+ }
+ else if (!strncmp(hwtype, "LPR", 3))
+ {
+ fprintf(out, ":lp=raw@%s:tc=.apple\n\n", hostname);
+ duptc = ".apple2";
+ }
+
+ if (*duplexname)
+ {
+ fprintf(out, "%s\n\t:server:bq=%s:cm=%s duplex queue\n\t",
+ duplexname, rp, rp);
+ if (!strncmp(hwtype, "HP", 2))
+ fprintf(out, ":ifhp=model=%s", lowerhwtype);
+ fprintf(out, ":tc=%s\n\n", duptc);
}
- else
- fprintf(out, "\t:mx#0:\n\n");
}
EXEC SQL CLOSE csr_printcap;
tarfile_end(tf);
- EXEC SQL DECLARE csr_spool CURSOR FOR
- SELECT UNIQUE pr.rp, pr.duplexname, pr.hwtype, m.name, pr.ac,
- pr.lpc_acl, pr.banner, TO_CHAR(pr.modtime, :unixtime_fmt)
- FROM printers pr, machine m, machine mrm
- WHERE m.mach_id = pr.mach_id
- AND mrm.mach_id = pr.rm AND mrm.name = :spoolhost;
- EXEC SQL OPEN csr_spool;
+ /* lpd.perms */
+ out = tarfile_start(tf, "/etc/lpd.perms", 0755, 1, 1,
+ "daemon", "daemon", now);
+ fprintf(out, "# Allow anybody to connect, get status, list queue, or "
+ "print (once a\n# job is spooled)\n");
+ fprintf(out, "ACCEPT SERVICE=X,S,Q,P\nACCEPT LPC=status,lpq,printcap\n\n");
+
+ fprintf(out, "# Only trust certain host keys to forward jobs/commands\n");
+ fprintf(out, "REJECT SERVICE=R AUTHFROM=?* "
+ "PRINTER=</var/spool/printer/queues.secure "
+ "NOT AUTHFROM=</var/spool/printer/hostkeys.allow FORWARD\n");
+ fprintf(out, "REJECT SERVICE=R AUTHFROM=?* AUTHJOB "
+ "NOT AUTHFROM=</var/spool/printer/hostkeys.allow FORWARD\n\n");
+
+ fprintf(out, "# Allow root to control and remove jobs\n");
+ fprintf(out, "ACCEPT SERVICE=C,R SERVER REMOTEUSER=root\n\n");
+
+ fprintf(out, "# Allow admins to control and remove jobs\n");
+ fprintf(out, "ACCEPT SERVICE=C,R AUTH=USER AUTHUSER=</var/spool/printer/lpcaccess.top\n\n");
+
+ fprintf(out, "# Printer-specific LPC ACLs\n");
+ EXEC SQL DECLARE csr_lpc CURSOR FOR
+ SELECT rp, duplexname FROM printers
+ WHERE rm = :rm AND lpc_acl != 0;
+ EXEC SQL OPEN csr_lpc;
while (1)
{
- EXEC SQL FETCH csr_spool INTO :name, :duplexname, :hwtype,
- :hostname, :ac, :lpc_acl, :banner, :modtime;
+ EXEC SQL FETCH csr_lpc INTO :name, :duplexname;
if (sqlca.sqlcode)
break;
strtrim(name);
strtrim(duplexname);
- strtrim(hwtype);
- strtrim(hostname);
- mtime = unixtime(strtrim(modtime));
+ fprintf(out, "ACCEPT SERVICE=C,R PRINTER=%s%s%s AUTH=USER "
+ "AUTHUSER=</var/spool/printer/%s/lpcaccess\n",
+ name, *duplexname ? "," : "", duplexname, name);
+ }
+ EXEC SQL CLOSE csr_lpc;
+ fprintf(out, "\n");
+
+ fprintf(out, "# Reject jobs from unauthorized users to restricted queues\n");
+ EXEC SQL DECLARE csr_ac CURSOR FOR
+ SELECT rp, duplexname, ka FROM printers
+ WHERE rm = :rm AND ac != 0;
+ EXEC SQL OPEN csr_ac;
+ while (1)
+ {
+ EXEC SQL FETCH csr_ac INTO :name, :duplexname, ka;
+ if (sqlca.sqlcode)
+ break;
- sprintf(filename, "/var/spool/printer/%s", name);
- tarfile_mkdir(tf, filename, 0755, 1, 1, "daemon", "daemon", mtime);
+ strtrim(name);
+ strtrim(duplexname);
+ fprintf(out, "REJECT SERVICE=R PRINTER=%s%s%s NOT "
+ "%sUSER=</var/spool/printer/%s/restrict.list\n",
+ name, *duplexname ? "," : "", duplexname,
+ ka ? "AUTH" : "", name);
+ }
+ EXEC SQL CLOSE csr_ac;
+ fprintf(out, "\n");
+
+ fprintf(out, "# Allow us to lock out users\n");
+ fprintf(out, "REJECT SERVICE=R USER=</var/spool/printer/users.deny\n");
+ fprintf(out, "# Accept authenticated jobs to all other printers\n");
+ fprintf(out, "ACCEPT SERVICE=R AUTH=USER,FWD\n");
+ fprintf(out, "# Allow authenticated users to lprm their jobs\n");
+ fprintf(out, "ACCEPT SERVICE=M AUTH=USER,FWD AUTHJOB AUTHSAMEUSER\n\n");
+
+ fprintf(out, "# Reject unauthentic print/lprm requests to authenticated queues\n");
+ fprintf(out, "REJECT SERVICE=R,M NOT AUTH "
+ "PRINTER=</var/spool/printer/queues.secure\n\n");
+
+ fprintf(out, "# Reject unauthentic print requests from off MITnet\n");
+ fprintf(out, "REJECT SERVICE=R NOT REMOTEIP=</var/spool/printer/masks.allow\n\n\n");
+
+ fprintf(out, "# Accept unauthentic print requests if same user and on MITnet\n");
+ fprintf(out, "ACCEPT SERVICE=M NOT AUTHJOB SAMEUSER REMOTEIP=</var/spool/printer/masks.allow\n\n");
+
+ fprintf(out, "# Reject any other lpc, or lprm. Accept all else\n");
+ fprintf(out, "REJECT SERVICE=C,M\n");
+ fprintf(out, "DEFAULT ACCEPT\n");
+ tarfile_end(tf);
- /* If spooling to an HP printer, make a .options file. */
- if (!strncmp(hwtype, "HP", 2))
- {
- sprintf(filename, "/var/spool/printer/%s/.options", name);
- out = tarfile_start(tf, filename, 0755, 1, 1, "daemon", "daemon",
- mtime);
- fprintf(out, "BANNERFIRST=%d\nBANNERLAST=%d\nREVERSE=\n"
- "DUPLEXING=0\nINTERFACE=0\nNETNAME=%s\nPRINTER=%s\n"
- "export BANNERFIRST BANNERLAST REVERSE DUPLEXING\n"
- "export PRINTER NETNAME INTERFACE VERBOSELOG\n",
- banner == PRN_BANNER_FIRST, banner == PRN_BANNER_LAST,
- hostname, name);
- tarfile_end(tf);
- }
+ /* list of kerberized queues */
+ out = tarfile_start(tf, "/var/spool/printer/queues.secure", 0755, 1, 1,
+ "daemon", "daemon", now);
+ EXEC SQL DECLARE csr_kq CURSOR FOR
+ SELECT rp, duplexname FROM printers
+ WHERE rm = :rm AND ka = 1;
+ EXEC SQL OPEN csr_kq;
+ while (1)
+ {
+ EXEC SQL FETCH csr_kq INTO :name, :duplexname;
+ if (sqlca.sqlcode)
+ break;
- /* If we have a duplex name, make a .spooler file. */
+ strtrim(name);
+ strtrim(duplexname);
+ fprintf(out, "%s\n", name);
if (*duplexname)
- {
- sprintf(filename, "/var/spool/printer/%s/.spooler", name);
- out = tarfile_start(tf, filename, 0755, 1, 1, "daemon", "daemon",
- mtime);
- fprintf(out, "%s -F /usr/athena/lib/lpdfilters/duplex2\n",
- duplexname);
- tarfile_end(tf);
- }
+ fprintf(out, "%s\n", duplexname);
+ }
+ tarfile_end(tf);
+
+ /* restrict lists and lpcaccess files */
+ EXEC SQL DECLARE csr_spool CURSOR FOR
+ SELECT UNIQUE rp, ka, ac, lpc_acl
+ FROM printers
+ WHERE rm = :rm AND ( ac != 0 OR lpc_acl != 0);
+ EXEC SQL OPEN csr_spool;
+ while (1)
+ {
+ EXEC SQL FETCH csr_spool INTO :name, :ka, :ac, :lpc_acl;
+ if (sqlca.sqlcode)
+ break;
+
+ strtrim(name);
+
+ sprintf(filename, "/var/spool/printer/%s", name);
+ tarfile_mkdir(tf, filename, 0755, 1, 1, "daemon", "daemon", now);
/* The ac and lpc_acl lists may have sublists, and changes to those
* won't affect the superlist's modtime. So we just set the modtime
sprintf(filename, "/var/spool/printer/%s/restrict.list", name);
out = tarfile_start(tf, filename, 0755, 1, 1, "daemon", "daemon",
now);
- dump_acl(out, ac, 0);
+ if (ka)
+ dump_krb_acl(out, "LIST", ac, 5);
+ else
+ dump_user_list(out, "LIST", ac);
tarfile_end(tf);
}
/* printer-specific lpc access. */
if (lpc_acl)
{
- sprintf(filename, "/var/spool/printer/%s/lpcaccess.%s", name, name);
+ sprintf(filename, "/var/spool/printer/%s/lpcaccess", name);
out = tarfile_start(tf, filename, 0755, 1, 1, "daemon", "daemon",
now);
- fprintf(out, "all:\n");
- dump_acl(out, lpc_acl, 1);
+ dump_krb_acl(out, "LIST", lpc_acl, 5);
tarfile_end(tf);
}
}
- EXEC SQL CLOSE csr_spool;
-
- tarfile_close(tf);
-}
-void dump_acl(FILE *out, int id, int realms)
-{
- EXEC SQL BEGIN DECLARE SECTION;
- int lid = id;
- char login[USERS_LOGIN_SIZE], princ[STRINGS_STRING_SIZE];
- EXEC SQL END DECLARE SECTION;
-
- EXEC SQL DECLARE csr_users CURSOR FOR
- SELECT u.login FROM users u, imembers im
- WHERE u.users_id = im.member_id
- AND im.member_type = 'USER' AND im.list_id = :lid;
- EXEC SQL OPEN csr_users;
- while (1)
+ /* lpcaccess.top */
+ EXEC SQL SELECT ps.lpc_acl INTO :lpc_acl
+ FROM printservers ps, machine m
+ WHERE m.name = :spoolhost AND m.mach_id = ps.mach_id;
+ if (!sqlca.sqlcode && lpc_acl)
{
- EXEC SQL FETCH csr_users INTO :login;
- if (sqlca.sqlcode)
- break;
-
- fprintf(out, "%s%s\n", strtrim(login), realms ? "@ATHENA.MIT.EDU" : "");
+ out = tarfile_start(tf, "/var/spool/printer/lpcaccess.top",
+ 0755, 1, 1, "daemon", "daemon", now);
+ dump_krb_acl(out, "LIST", lpc_acl, 5);
+ tarfile_end(tf);
}
- EXEC SQL CLOSE csr_users;
-
- EXEC SQL DECLARE csr_krb CURSOR FOR
- SELECT s.string FROM strings s, imembers im
- WHERE s.string_id = im.member_id
- AND im.member_type = 'KERBEROS' AND im.list_id = :lid;
- EXEC SQL OPEN csr_krb;
- while (1)
- {
- EXEC SQL FETCH csr_krb INTO :princ;
- if (sqlca.sqlcode)
- break;
- if (!realms)
- {
- if (strchr(princ, '@'))
- *strchr(princ, '@') = '\0';
- }
+ EXEC SQL CLOSE csr_spool;
- fprintf(out, "%s\n", strtrim(princ));
- }
- EXEC SQL CLOSE csr_krb;
+ tarfile_close(tf);
}
void sqlerr(void)