* Various changes to allow channel bindings to work with both UDP
authorBarry Jaspan <bjaspan@mit.edu>
Wed, 4 Dec 1996 17:47:19 +0000 (17:47 +0000)
committerBarry Jaspan <bjaspan@mit.edu>
Wed, 4 Dec 1996 17:47:19 +0000 (17:47 +0000)
  and TCP cleanly [krb5-libs/180]:

* auth_gssapi.c: remove the special-case exception to channel
  bindings failure added in the previous revision, since we now
  solve the problem by making channel bindings not fail

* clnt_udp.c: use a connected socket so that the client can
  determine its own source address with getsockname

* svc.h: add xp_laddr and xp_laddrlen fields to SVCXPRT structure

* svc_tcp.c: set xp_laddr and xp_laddrlen when a connection is
  established

* svc_udp.c (svcudp_recv): use recvmsg with MSG_PEEK followed by
  recvfrom in order to determine both source and dest address on
  unconnected UDP socket, set xp_laddr and xp_laddrlen

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@9600 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/rpc/ChangeLog
src/lib/rpc/auth_gssapi.c
src/lib/rpc/clnt_udp.c
src/lib/rpc/svc.h
src/lib/rpc/svc_auth_gssapi.c
src/lib/rpc/svc_tcp.c
src/lib/rpc/svc_udp.c

index b4e0eb723a338702c0b9cb41c5678cf5df6bd005..1f815211b11dbae62e23203eca192c8eb3ae422d 100644 (file)
@@ -1,3 +1,24 @@
+Wed Dec  4 12:42:49 1996  Barry Jaspan  <bjaspan@mit.edu>
+
+       * Various changes to allow channel bindings to work with both UDP
+       and TCP cleanly [krb5-libs/180]:
+
+       * auth_gssapi.c: remove the special-case exception to channel
+       bindings failure added in the previous revision, since we now
+       solve the problem by making channel bindings not fail
+
+       * clnt_udp.c: use a connected socket so that the client can
+       determine its own source address with getsockname
+
+       * svc.h: add xp_laddr and xp_laddrlen fields to SVCXPRT structure
+
+       * svc_tcp.c: set xp_laddr and xp_laddrlen when a connection is
+       established
+
+       * svc_udp.c (svcudp_recv): use recvmsg with MSG_PEEK followed by
+       recvfrom in order to determine both source and dest address on
+       unconnected UDP socket, set xp_laddr and xp_laddrlen
+
 Tue Nov 12 16:27:27 1996  Barry Jaspan  <bjaspan@mit.edu>
 
        * auth_gssapi.c (auth_gssapi_create): handle channel bindings
index 7d51d3dce60880db73bc824b7cfbfa36c8a97084..455856cc250b75dcdd19632d2f21c00f2fbb2ffe 100644 (file)
@@ -338,11 +338,6 @@ next_token:
               AUTH_GSSAPI_DISPLAY_STATUS(("in response from server",
                                           call_res.gss_major,
                                           call_res.gss_minor));
-              if (GSS_ERROR(call_res.gss_major) == GSS_S_BAD_BINDINGS
-                  && call_arg.version > 2) {
-                   call_arg.version = 2;
-                   goto try_new_version;
-              }
               goto cleanup;
          }
          
index 6a5cf5f11418505a5d3db4d4b81575cbe0fa7161..9e1d563af32df68c520e33f2c58ea4214b2b253b 100644 (file)
@@ -77,6 +77,8 @@ struct cu_data {
        bool_t             cu_closeit;
        struct sockaddr_in cu_raddr;
        int                cu_rlen;
+       struct sockaddr_in cu_laddr;
+       int                cu_llen;
        struct timeval     cu_wait;
        struct timeval     cu_total;
        struct rpc_err     cu_error;
@@ -183,6 +185,12 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
        } else {
                cu->cu_closeit = FALSE;
        }
+       if (connect(*sockp, raddr, sizeof(*raddr)) < 0)
+            goto fooy;
+            cu->cu_llen = sizeof(cu->cu_laddr);
+       if (getsockname(*sockp, &cu->cu_laddr, &cu->cu_llen) < 0)
+            goto fooy;
+       
        cu->cu_sock = *sockp;
        cl->cl_auth = authnone_create();
        return (cl);
@@ -261,9 +269,7 @@ call_again:
        outlen = (int)XDR_GETPOS(xdrs);
 
 send_again:
-       if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
-           (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
-           != outlen) {
+       if (send(cu->cu_sock, cu->cu_outbuf, outlen, 0) != outlen) {
                cu->cu_error.re_errno = errno;
                return (cu->cu_error.re_status = RPC_CANTSEND);
        }
@@ -434,11 +440,8 @@ clntudp_control(cl, request, info)
                *(struct sockaddr_in *)info = cu->cu_raddr;
                break;
        case CLGET_LOCAL_ADDR:
-               len = sizeof(struct sockaddr);
-               if (getsockname(cu->cu_sock, (struct sockaddr*)info, &len) < 0)
-                    return FALSE;
-               else
-                    return TRUE;
+               *(struct sockaddr_in *)info = cu->cu_laddr;
+               break;
        default:
                return (FALSE);
        }
index 2114d6249e52099c2a08227138c76209d9eae175..80595738305399a99c49abfeb7358f7e4e675431 100644 (file)
@@ -85,6 +85,8 @@ typedef struct {
        SVCAUTH         *xp_auth;        /* auth flavor of current req */
        caddr_t         xp_p1;           /* private */
        caddr_t         xp_p2;           /* private */
+       int             xp_laddrlen;     /* lenght of local address */
+       struct sockaddr_in xp_laddr;     /* local address */
 } SVCXPRT;
 
 /*
index 1e204e0e33914ec5d30aa980826be13dac8fedd9..20bf95a741a605ea4c232abacd1a85cb71a29f69 100644 (file)
@@ -5,6 +5,26 @@
  * $Source$
  * 
  * $Log$
+ * Revision 1.42  1996/12/04 17:47:18  bjaspan
+ *     * Various changes to allow channel bindings to work with both UDP
+ *     and TCP cleanly [krb5-libs/180]:
+ *
+ *     * auth_gssapi.c: remove the special-case exception to channel
+ *     bindings failure added in the previous revision, since we now
+ *     solve the problem by making channel bindings not fail
+ *
+ *     * clnt_udp.c: use a connected socket so that the client can
+ *     determine its own source address with getsockname
+ *
+ *     * svc.h: add xp_laddr and xp_laddrlen fields to SVCXPRT structure
+ *
+ *     * svc_tcp.c: set xp_laddr and xp_laddrlen when a connection is
+ *     established
+ *
+ *     * svc_udp.c (svcudp_recv): use recvmsg with MSG_PEEK followed by
+ *     recvfrom in order to determine both source and dest address on
+ *     unconnected UDP socket, set xp_laddr and xp_laddrlen
+ *
  * Revision 1.41  1996/10/16 20:16:10  bjaspan
  * * svc_auth_gssapi.c (_svcauth_gssapi): accept add call_arg version 4
  *
@@ -310,7 +330,6 @@ enum auth_stat _svcauth_gssapi(rqst, msg, no_dispatch)
      gss_buffer_desc output_token, in_buf, out_buf;
      gss_cred_id_t server_creds;
      struct gss_channel_bindings_struct bindings, *bindp;
-     struct sockaddr_in sockname;
      OM_uint32 gssstat, minor_stat, time_rec;
      struct opaque_auth *cred, *verf;
      svc_auth_gssapi_data *client_data;
@@ -497,19 +516,17 @@ enum auth_stat _svcauth_gssapi(rqst, msg, no_dispatch)
               bindings.initiator_address.value =
                    &svc_getcaller(rqst->rq_xprt)->sin_addr.s_addr;
 
-              len = sizeof(sockname);
-              if (getsockname(rqst->rq_xprt->xp_sock, 
-                              (struct sockaddr *) &sockname, &len) < 0) {
+              if (rqst->rq_xprt->xp_laddrlen > 0) {
+                   bindings.acceptor_addrtype = GSS_C_AF_INET;
+                   bindings.acceptor_address.length = 4;
+                   bindings.acceptor_address.value =
+                        &rqst->rq_xprt->xp_laddr.sin_addr.s_addr;
+              } else {
                    LOG_MISCERR("cannot get local address");
-                   PRINTF(("svcauth_gssapi: errno %d while getting address",
-                           errno));
                    ret = AUTH_FAILED;
                    goto error;
               }
 
-              bindings.acceptor_addrtype = GSS_C_AF_INET;
-              bindings.acceptor_address.length = 4;
-              bindings.acceptor_address.value = &sockname.sin_addr.s_addr;
 
               bindp = &bindings;
          } else {
index e20a29b192ff807152fb9a9ddc1dfa9f1442b559..fe9b87fa6ab76a620bd396aad0837bb3e2bb4d36 100644 (file)
@@ -174,6 +174,7 @@ svctcp_create(sock, sendsize, recvsize)
        xprt->xp_ops = &svctcp_rendezvous_op;
        xprt->xp_port = ntohs(addr.sin_port);
        xprt->xp_sock = sock;
+       xprt->xp_laddrlen = 0;
        xprt_register(xprt);
        return (xprt);
 }
@@ -220,6 +221,7 @@ makefd_xprt(fd, sendsize, recvsize)
        xprt->xp_p1 = (caddr_t)cd;
        xprt->xp_verf.oa_base = cd->verf_body;
        xprt->xp_addrlen = 0;
+       xprt->xp_laddrlen = 0;
        xprt->xp_ops = &svctcp_op;  /* truely deals with calls */
        xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */
        xprt->xp_sock = fd;
@@ -234,24 +236,29 @@ rendezvous_request(xprt)
 {
        int sock;
        struct tcp_rendezvous *r;
-       struct sockaddr_in addr;
-       int len;
+       struct sockaddr_in addr, laddr;
+       int len, llen;
 
        r = (struct tcp_rendezvous *)xprt->xp_p1;
     again:
-       len = sizeof(struct sockaddr_in);
+       len = llen = sizeof(struct sockaddr_in);
        if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
            &len)) < 0) {
                if (errno == EINTR)
                        goto again;
               return (FALSE);
        }
+       if (getsockname(sock, &laddr, &llen) < 0)
+            return (FALSE);
+       
        /*
         * make a new transporter (re-uses xprt)
         */
        xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
        xprt->xp_raddr = addr;
        xprt->xp_addrlen = len;
+       xprt->xp_laddr = laddr;
+       xprt->xp_laddrlen = llen;
        return (FALSE); /* there is never an rpc msg to be processed */
 }
 
index d44c7f5d881e935de9f4355acb519e425f924fd4..142293facd3fe9562a69a6ac4cc798842748bbf6 100644 (file)
@@ -174,6 +174,7 @@ svcudp_recv(xprt, msg)
        register SVCXPRT *xprt;
        struct rpc_msg *msg;
 {
+        struct msghdr dummy;
        register struct svcudp_data *su = su_data(xprt);
        register XDR *xdrs = &(su->su_xdrs);
        register int rlen;
@@ -181,6 +182,17 @@ svcudp_recv(xprt, msg)
        rpc_u_int32 replylen;
 
     again:
+       memset((char *) &dummy, 0, sizeof(dummy));
+       dummy.msg_namelen = xprt->xp_laddrlen = sizeof(struct sockaddr_in);
+       dummy.msg_name = (char *) &xprt->xp_laddr;
+       rlen = recvmsg(xprt->xp_sock, &dummy, MSG_PEEK);
+       if (rlen == -1) {
+            if (errno == EINTR)
+                 goto again;
+            else
+                 return (FALSE);
+       }
+       
        xprt->xp_addrlen = sizeof(struct sockaddr_in);
        rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
            0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));