@@ -814,6 +814,7 @@ static void host_connected_info_free(struct host_connected_info *info)
814814struct accept_info {
815815 int fd ;
816816 int secure ; /* whether connection is routed from a secure pmux port */
817+ int pmuv ;
817818 int badrte ;
818819 struct evbuffer * buf ;
819820 int to_len ;
@@ -840,7 +841,7 @@ static void do_read(int, short, void *);
840841static void accept_info_free (struct accept_info * );
841842
842843static void accept_info_new (netinfo_type * netinfo_ptr , struct sockaddr_in * addr , int fd , int secure ,
843- int badrte )
844+ int badrte , int pmuv )
844845{
845846 check_base_thd ();
846847 ++ pending_connections ;
@@ -856,6 +857,7 @@ static void accept_info_new(netinfo_type *netinfo_ptr, struct sockaddr_in *addr,
856857 a -> fd = fd ;
857858 a -> secure = secure ;
858859 a -> badrte = badrte ;
860+ a -> pmuv = pmuv ;
859861 a -> ev = event_new (base , fd , EV_READ , do_read , a );
860862 event_add (a -> ev , NULL );
861863}
@@ -2928,6 +2930,75 @@ static int should_reject_request(uint8_t first_byte)
29282930 return check_appsock_limit (pending_connections , is_admin );
29292931}
29302932
2933+ /* PMUV REQUEST/RESPONSE */
2934+ enum request { V_WHO = 1 , V_NAK = 2 , V_ACK = 3 };
2935+ enum response { V_NONE = 0 , V_ID = 1 };
2936+
2937+ static int portmux_server_side_validation (struct accept_info * a , char request ) {
2938+ ssize_t rc ;
2939+ char response ;
2940+ switch (request ) {
2941+ case V_WHO :
2942+ response = V_ID ;
2943+ rc = write (a -> fd , & response , 1 );
2944+ if (rc != 1 ) {
2945+ logmsg (LOGMSG_ERROR , "%s:write failure fd:%d rc:%zd (%s)\n" , __func__ ,
2946+ a -> fd , rc , strerror (errno ));
2947+ return 1 ;
2948+ }
2949+
2950+ uint32_t size = 0 ;
2951+ uint32_t features = htonl (0 );
2952+ /* format the triplet into a string.
2953+ * snprintf returns the number of characters printed, excluding
2954+ * the null byte used to end output to strings - we want that too.
2955+ */
2956+ char buf [512 ];
2957+ netinfo_type * netinfo_ptr = a -> netinfo_ptr ;
2958+ uint32_t buflen = snprintf (buf , sizeof (buf ), "%s/%s/%s" , netinfo_ptr -> app ,
2959+ netinfo_ptr -> service , netinfo_ptr -> instance ) +
2960+ 1 ;
2961+ if (buflen > sizeof (buf )) {
2962+ return 1 ;
2963+ }
2964+ evbuffer_drain (a -> buf , 1 );
2965+ /* Logic from portmuxuser.c portmux_server_side_validation */
2966+ size_t total_len = 0 ;
2967+ struct evbuffer_iovec iov [3 ];
2968+ iov [0 ].iov_base = (void * )& size ;
2969+ iov [0 ].iov_len = sizeof (uint32_t );
2970+ iov [1 ].iov_base = (void * )& features ;
2971+ iov [1 ].iov_len = sizeof (uint32_t );
2972+ iov [2 ].iov_base = (void * )buf ;
2973+ iov [2 ].iov_len = buflen ;
2974+ size = iov [1 ].iov_len + iov [2 ].iov_len ;
2975+ total_len = size + iov [0 ].iov_len ;
2976+ size = htonl (size );
2977+ evbuffer_add_iovec (a -> buf , iov , 3 );
2978+ rc = evbuffer_write (a -> buf , a -> fd );
2979+ if (rc != total_len ) {
2980+ logmsg (LOGMSG_ERROR , "%s:unable to write fd:%d rc:%zd (%s)\n" , __func__ ,
2981+ a -> fd , rc , strerror (errno ));
2982+ return 1 ;
2983+ }
2984+ /* Still in pmuv validation mode, don't reset the flag */
2985+ a -> ev = event_new (base , a -> fd , EV_READ , do_read , a );
2986+ event_add (a -> ev , NULL );
2987+ return 0 ;
2988+ case V_NAK :
2989+ /* Validation failed */
2990+ return 1 ;
2991+ case V_ACK :
2992+ /* Validation done */
2993+ a -> pmuv = 0 ;
2994+ a -> ev = event_new (base , a -> fd , EV_READ , do_read , a );
2995+ event_add (a -> ev , NULL );
2996+ return 0 ;
2997+ default :
2998+ return 1 ;
2999+ }
3000+ }
3001+
29313002static void do_read (int fd , short what , void * data )
29323003{
29333004 check_base_thd ();
@@ -2941,6 +3012,18 @@ static void do_read(int fd, short what, void *data)
29413012 }
29423013 uint8_t first_byte ;
29433014 evbuffer_copyout (buf , & first_byte , 1 );
3015+ if (a -> pmuv ) {
3016+ a -> buf = buf ;
3017+ evbuffer_drain (buf , 1 );
3018+ if (portmux_server_side_validation (a , first_byte ) != 0 ) {
3019+ evbuffer_free (buf );
3020+ shutdown_close (fd );
3021+ } else {
3022+ evbuffer_free (buf );
3023+ a -> buf = NULL ;
3024+ }
3025+ return ;
3026+ }
29443027 if (first_byte == 0 ) { /* replication or offloadsql */
29453028 evbuffer_drain (buf , 1 );
29463029 a -> buf = buf ;
@@ -2967,7 +3050,7 @@ static void do_read(int fd, short what, void *data)
29673050 if (badrte ) {
29683051 // Failed to handle fd because of badrte
29693052 rem_appsock_connection_evbuffer ();
2970- accept_info_new (netinfo_ptr , & ss , fd , secure , 1 );
3053+ accept_info_new (netinfo_ptr , & ss , fd , secure , 1 , 0 );
29713054 return ;
29723055 }
29733056 if (handle_appsock (netinfo_ptr , & ss , first_byte , buf , fd ) != 0 ) {
@@ -2977,14 +3060,24 @@ static void do_read(int fd, short what, void *data)
29773060 }
29783061}
29793062
3063+ static void accept_pmuv (struct evconnlistener * listener , evutil_socket_t fd ,
3064+ struct sockaddr * addr , int len , void * data )
3065+ {
3066+ check_base_thd ();
3067+ struct net_info * n = data ;
3068+ netinfo_type * netinfo_ptr = n -> netinfo_ptr ;
3069+ netinfo_ptr -> num_accepts ++ ;
3070+ accept_info_new (netinfo_ptr , (struct sockaddr_in * )addr , fd , 0 , 0 , 1 );
3071+ }
3072+
29803073static void accept_cb (struct evconnlistener * listener , evutil_socket_t fd ,
29813074 struct sockaddr * addr , int len , void * data )
29823075{
29833076 check_base_thd ();
29843077 struct net_info * n = data ;
29853078 netinfo_type * netinfo_ptr = n -> netinfo_ptr ;
29863079 netinfo_ptr -> num_accepts ++ ;
2987- accept_info_new (netinfo_ptr , (struct sockaddr_in * )addr , fd , 0 , 0 );
3080+ accept_info_new (netinfo_ptr , (struct sockaddr_in * )addr , fd , 0 , 0 , 0 );
29883081}
29893082
29903083static void accept_secure (struct evconnlistener * listener , evutil_socket_t fd , struct sockaddr * addr , int len ,
@@ -2994,7 +3087,7 @@ static void accept_secure(struct evconnlistener *listener, evutil_socket_t fd, s
29943087 struct net_info * n = data ;
29953088 netinfo_type * netinfo_ptr = n -> netinfo_ptr ;
29963089 netinfo_ptr -> num_accepts ++ ;
2997- accept_info_new (netinfo_ptr , (struct sockaddr_in * )addr , fd , 1 , 0 );
3090+ accept_info_new (netinfo_ptr , (struct sockaddr_in * )addr , fd , 1 , 0 , 0 );
29983091}
29993092
30003093static void accept_error_cb (struct evconnlistener * listener , void * data )
@@ -3027,7 +3120,7 @@ static void reopen_unix(int fd, struct net_info *n)
30273120 (m)->cmsg_level == SOL_SOCKET && (m)->cmsg_type == SCM_RIGHTS)
30283121#endif
30293122
3030- static int recvfd (int pmux_fd , int * secure )
3123+ static int recvfd (int pmux_fd , int * secure , int * pmuv )
30313124{
30323125 int newfd = -1 ;
30333126 char buf [sizeof ("pmux" ) - 1 ];
@@ -3081,13 +3174,15 @@ static int recvfd(int pmux_fd, int *secure)
30813174 }
30823175 newfd = * (int * )CMSG_DATA (m );
30833176# endif
3084- if (memcmp (buf , "pmux" , sizeof (buf )) != 0 && memcmp (buf , "spmu" , sizeof (buf )) != 0 ) {
3177+ if (memcmp (buf , "pmux" , sizeof (buf )) != 0 && memcmp (buf , "spmu" , sizeof (buf )) != 0 &&
3178+ memcmp (buf , "pmuv" , sizeof (buf ))) {
30853179 shutdown_close (newfd );
30863180 logmsg (LOGMSG_ERROR , "%s:recvmsg pmux_fd:%d unexpected msg:%.*s\n" , __func__ ,
30873181 pmux_fd , (int )sizeof (buf ), buf );
30883182 return -1 ;
30893183 }
30903184 * secure = (memcmp (buf , "spmu" , sizeof (buf )) == 0 );
3185+ * pmuv = (memcmp (buf , "pmuv" , sizeof (buf )) == 0 );
30913186 return newfd ;
30923187}
30933188
@@ -3096,14 +3191,21 @@ static void do_recvfd(int pmux_fd, short what, void *data)
30963191 check_base_thd ();
30973192 struct net_info * n = data ;
30983193 int secure ;
3099- int newfd = recvfd (pmux_fd , & secure );
3194+ int pmuv ;
3195+ int newfd = recvfd (pmux_fd , & secure , & pmuv );
31003196 if (newfd == 0 ) return ;
31013197 if (newfd < 0 ) {
31023198 reopen_unix (pmux_fd , n );
31033199 return ;
31043200 }
31053201 make_server_socket (newfd );
3106- ssize_t rc = write (newfd , "0\n" , 2 );
3202+ ssize_t rc ;
3203+ if (pmuv ) {
3204+ /* Validate */
3205+ rc = write (newfd , "1\n" , 2 );
3206+ } else {
3207+ rc = write (newfd , "0\n" , 2 );
3208+ }
31073209 if (rc != 2 ) {
31083210 logmsg (LOGMSG_ERROR , "%s:write pmux_fd:%d rc:%zd (%s)\n" , __func__ , pmux_fd , rc , strerror (errno ));
31093211 shutdown_close (newfd );
@@ -3113,10 +3215,12 @@ static void do_recvfd(int pmux_fd, short what, void *data)
31133215 struct sockaddr * addr = (struct sockaddr * )& saddr ;
31143216 socklen_t addrlen = sizeof (saddr );
31153217 getpeername (newfd , addr , & addrlen );
3116- if (!secure )
3117- accept_cb (NULL , newfd , addr , addrlen , n );
3118- else
3218+ if (secure )
31193219 accept_secure (NULL , newfd , addr , addrlen , n );
3220+ else if (pmuv )
3221+ accept_pmuv (NULL , newfd , addr , addrlen , n );
3222+ else
3223+ accept_cb (NULL , newfd , addr , addrlen , n );
31203224}
31213225
31223226static int process_reg_reply (char * res , struct net_info * n , int unix_fd )
0 commit comments