Ignatios Souvatzis
2011-03-25 14:35:39 UTC
Hi,
I noticed that modern Windows machines couldn't lpr-print via our
lpd anymore after upgrading it to dual-stack.
The reason is that a) Windows (post-XP) has privacy addresses and
interface id randomization enabled per default, and especially the
former somehow don't make it easy (or actually, desirable) to have
matching forward and backward resolved names in DNS.
OTOH, lpd checks for matching reverse and forward resolved names
*before* checking whether it needs to test for an explicit hostname.
The patch below makes this test, but saves the result for later, and
checks for a '+'-Entry in /etc/hosts.lpd or /etc/hosts.equiv if
needed.
This is in production use at my (work) institution.
You still need a reverse DNS entry, but this alone can be easily done
with a catch-all like
* IN PTR unknown-vlan169.department.institution.example.
(The planned big rewriting/replacing of lpd should take this situation
into account btw. - but I need a solution *now* for the existing one.)
I plan to commit next week. Comments?
-is
Index: lpd.8
===================================================================
RCS file: /cvsroot/src/usr.sbin/lpr/lpd/lpd.8,v
retrieving revision 1.33
diff -u -r1.33 lpd.8
--- lpd.8 22 Jan 2006 21:31:17 -0000 1.33
+++ lpd.8 25 Mar 2011 14:25:14 -0000
@@ -177,6 +177,9 @@
.Pa /etc/hosts.equiv
or
.Pa /etc/hosts.lpd .
+A machine using IPv6 privacy addresses (which, by definition, can't have
+name resolution in both directions) will match a '+' host entry, if the
+reverse zone has at least a catch-all name.
Lastly, if the
.Li rs
capability is specified in the
@@ -186,6 +189,7 @@
requests will only be honored for those users with accounts on the
machine with the printer.
Requests must pass all three tests.
+
.Pp
The file
.Em minfree
Index: lpd.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/lpr/lpd/lpd.c,v
retrieving revision 1.55
diff -u -r1.55 lpd.c
--- lpd.c 21 Jul 2008 13:36:58 -0000 1.55
+++ lpd.c 25 Mar 2011 14:25:14 -0000
@@ -133,6 +133,7 @@
static void chkhost(struct sockaddr *, int);
static void usage(void);
static struct pollfd *socksetup(int, int, const char *, int *);
+static void chkplushost(int, FILE *, char*);
uid_t uid, euid;
int child_count;
@@ -362,6 +363,35 @@
}
}
+/*
+ * If there was a forward/backward name resolution mismatch, check
+ * that there's a '+' entry in fhost.
+ */
+
+void
+chkplushost(int good, FILE *fhost, char *hst)
+{
+ int c1, c2, c3;
+
+ if (good) {
+ return;
+ }
+
+ rewind(fhost);
+ while (EOF != (c1 = fgetc(fhost))) {
+ if (c1 == '+') {
+ c2 = fgetc(fhost);
+ if (c2 == ' ' || c2 == '\t' || c2 == '\n') {
+ return;
+ }
+ }
+ do {
+ c3 = fgetc(fhost);
+ } while (c3 != EOF && c3 != '\n');
+ }
+ fatal("address for your hostname (%s) not matched", hst);
+}
+
static void
reapchild(int signo)
{
@@ -606,25 +636,23 @@
fatal("Cannot print address");
/* Check for spoof, ala rlogind */
+ good = 0;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
error = getaddrinfo(fromb, NULL, &hints, &res);
- if (error) {
- fatal("hostname for your address (%s) unknown: %s", hst,
- gai_strerror(error));
+ if (!error) {
+ for (r = res; good == 0 && r; r = r->ai_next) {
+ error = getnameinfo(r->ai_addr, r->ai_addrlen,
+ ip, sizeof(ip), NULL, 0, NI_NUMERICHOST);
+ if (!error && !strcmp(hst, ip))
+ good = 1;
+ }
+ if (res)
+ freeaddrinfo(res);
}
- good = 0;
- for (r = res; good == 0 && r; r = r->ai_next) {
- error = getnameinfo(r->ai_addr, r->ai_addrlen, ip, sizeof(ip),
- NULL, 0, NI_NUMERICHOST);
- if (!error && !strcmp(hst, ip))
- good = 1;
- }
- if (res)
- freeaddrinfo(res);
- if (good == 0)
- fatal("address for your hostname (%s) not matched", hst);
+
+ /* complain about !good later in chkplushost if needed. */
setproctitle("serving %s", from);
@@ -639,6 +667,7 @@
hostf = fopen(_PATH_HOSTSEQUIV, "r");
if (hostf) {
if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) {
+ chkplushost(good, hostf, hst);
(void)fclose(hostf);
return;
}
@@ -647,6 +676,7 @@
hostf = fopen(_PATH_HOSTSLPD, "r");
if (hostf) {
if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) {
+ chkplushost(good, hostf, hst);
(void)fclose(hostf);
return;
}
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
I noticed that modern Windows machines couldn't lpr-print via our
lpd anymore after upgrading it to dual-stack.
The reason is that a) Windows (post-XP) has privacy addresses and
interface id randomization enabled per default, and especially the
former somehow don't make it easy (or actually, desirable) to have
matching forward and backward resolved names in DNS.
OTOH, lpd checks for matching reverse and forward resolved names
*before* checking whether it needs to test for an explicit hostname.
The patch below makes this test, but saves the result for later, and
checks for a '+'-Entry in /etc/hosts.lpd or /etc/hosts.equiv if
needed.
This is in production use at my (work) institution.
You still need a reverse DNS entry, but this alone can be easily done
with a catch-all like
* IN PTR unknown-vlan169.department.institution.example.
(The planned big rewriting/replacing of lpd should take this situation
into account btw. - but I need a solution *now* for the existing one.)
I plan to commit next week. Comments?
-is
Index: lpd.8
===================================================================
RCS file: /cvsroot/src/usr.sbin/lpr/lpd/lpd.8,v
retrieving revision 1.33
diff -u -r1.33 lpd.8
--- lpd.8 22 Jan 2006 21:31:17 -0000 1.33
+++ lpd.8 25 Mar 2011 14:25:14 -0000
@@ -177,6 +177,9 @@
.Pa /etc/hosts.equiv
or
.Pa /etc/hosts.lpd .
+A machine using IPv6 privacy addresses (which, by definition, can't have
+name resolution in both directions) will match a '+' host entry, if the
+reverse zone has at least a catch-all name.
Lastly, if the
.Li rs
capability is specified in the
@@ -186,6 +189,7 @@
requests will only be honored for those users with accounts on the
machine with the printer.
Requests must pass all three tests.
+
.Pp
The file
.Em minfree
Index: lpd.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/lpr/lpd/lpd.c,v
retrieving revision 1.55
diff -u -r1.55 lpd.c
--- lpd.c 21 Jul 2008 13:36:58 -0000 1.55
+++ lpd.c 25 Mar 2011 14:25:14 -0000
@@ -133,6 +133,7 @@
static void chkhost(struct sockaddr *, int);
static void usage(void);
static struct pollfd *socksetup(int, int, const char *, int *);
+static void chkplushost(int, FILE *, char*);
uid_t uid, euid;
int child_count;
@@ -362,6 +363,35 @@
}
}
+/*
+ * If there was a forward/backward name resolution mismatch, check
+ * that there's a '+' entry in fhost.
+ */
+
+void
+chkplushost(int good, FILE *fhost, char *hst)
+{
+ int c1, c2, c3;
+
+ if (good) {
+ return;
+ }
+
+ rewind(fhost);
+ while (EOF != (c1 = fgetc(fhost))) {
+ if (c1 == '+') {
+ c2 = fgetc(fhost);
+ if (c2 == ' ' || c2 == '\t' || c2 == '\n') {
+ return;
+ }
+ }
+ do {
+ c3 = fgetc(fhost);
+ } while (c3 != EOF && c3 != '\n');
+ }
+ fatal("address for your hostname (%s) not matched", hst);
+}
+
static void
reapchild(int signo)
{
@@ -606,25 +636,23 @@
fatal("Cannot print address");
/* Check for spoof, ala rlogind */
+ good = 0;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
error = getaddrinfo(fromb, NULL, &hints, &res);
- if (error) {
- fatal("hostname for your address (%s) unknown: %s", hst,
- gai_strerror(error));
+ if (!error) {
+ for (r = res; good == 0 && r; r = r->ai_next) {
+ error = getnameinfo(r->ai_addr, r->ai_addrlen,
+ ip, sizeof(ip), NULL, 0, NI_NUMERICHOST);
+ if (!error && !strcmp(hst, ip))
+ good = 1;
+ }
+ if (res)
+ freeaddrinfo(res);
}
- good = 0;
- for (r = res; good == 0 && r; r = r->ai_next) {
- error = getnameinfo(r->ai_addr, r->ai_addrlen, ip, sizeof(ip),
- NULL, 0, NI_NUMERICHOST);
- if (!error && !strcmp(hst, ip))
- good = 1;
- }
- if (res)
- freeaddrinfo(res);
- if (good == 0)
- fatal("address for your hostname (%s) not matched", hst);
+
+ /* complain about !good later in chkplushost if needed. */
setproctitle("serving %s", from);
@@ -639,6 +667,7 @@
hostf = fopen(_PATH_HOSTSEQUIV, "r");
if (hostf) {
if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) {
+ chkplushost(good, hostf, hst);
(void)fclose(hostf);
return;
}
@@ -647,6 +676,7 @@
hostf = fopen(_PATH_HOSTSLPD, "r");
if (hostf) {
if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) {
+ chkplushost(good, hostf, hst);
(void)fclose(hostf);
return;
}
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de