Once a ypserv is discovered we know the remote UDP port number, but not
authorderaadt <deraadt@openbsd.org>
Fri, 15 Jul 2022 16:59:49 +0000 (16:59 +0000)
committerderaadt <deraadt@openbsd.org>
Fri, 15 Jul 2022 16:59:49 +0000 (16:59 +0000)
the TCP port number.  Immediately reach out (syncronously via pmap_getport,
to ask the portmap on the ypserv machine) to learn the TCP port number.
Append this as 2 bytes (network byte order) to the binding file, because
an upcoming change will require this information also.
with jmatthew, also ok claudio miod

usr.sbin/ypbind/ypbind.c

index 0f1e771..fae94ff 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ypbind.c,v 1.74 2020/12/29 19:48:49 benno Exp $ */
+/*     $OpenBSD: ypbind.c,v 1.75 2022/07/15 16:59:49 deraadt Exp $ */
 
 /*
  * Copyright (c) 1992, 1993, 1996, 1997, 1998 Theo de Raadt <deraadt@openbsd.org>
@@ -955,9 +955,10 @@ void
 rpc_received(char *dom, struct sockaddr_in *raddrp, int force)
 {
        struct _dom_binding *ypdb;
-       struct iovec iov[2];
+       struct iovec iov[3];
        struct ypbind_resp ybr;
        char path[PATH_MAX];
+       u_short ypserv_tcp, ypserv_udp;
        int fd;
 
        if (strchr(dom, '/'))
@@ -1012,6 +1013,18 @@ rpc_received(char *dom, struct sockaddr_in *raddrp, int force)
                return;
        }
 
+       /* syncronously ask for the matching ypserv TCP port number */
+       ypserv_udp = raddrp->sin_port;
+       ypserv_tcp = pmap_getport(raddrp, YPPROG,
+           YPVERS, IPPROTO_TCP);
+       if (ypserv_tcp == 0) {
+               clnt_pcreateerror("pmap_getport");
+               return;
+       }
+       if (ypserv_tcp >= IPPORT_RESERVED || ypserv_tcp == 20)
+               return;
+       ypserv_tcp = htons(ypserv_tcp);
+
        memcpy(&ypdb->dom_server_addr, raddrp, sizeof ypdb->dom_server_addr);
        /* recheck binding in 60 seconds */
        ypdb->dom_check_t = time(NULL) + 60;
@@ -1052,6 +1065,8 @@ rpc_received(char *dom, struct sockaddr_in *raddrp, int force)
        iov[0].iov_len = sizeof udptransp->xp_port;
        iov[1].iov_base = (caddr_t)&ybr;
        iov[1].iov_len = sizeof ybr;
+       iov[2].iov_base = (caddr_t)&ypserv_tcp;
+       iov[2].iov_len = sizeof ypserv_tcp;
 
        memset(&ybr, 0, sizeof ybr);
        ybr.ypbind_status = YPBIND_SUCC_VAL;
@@ -1059,10 +1074,11 @@ rpc_received(char *dom, struct sockaddr_in *raddrp, int force)
            &raddrp->sin_addr,
            sizeof(ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr));
        memmove(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
-           &raddrp->sin_port,
+           &ypserv_udp,
            sizeof(ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port));
 
-       if (writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) {
+       if (writev(ypdb->dom_lockfd, iov, sizeof(iov)/sizeof(iov[0])) !=
+           iov[0].iov_len + iov[1].iov_len + iov[2].iov_len) {
                perror("write");
                close(ypdb->dom_lockfd);
                unlink(path);