@@ -51,7 +51,10 @@ struct ipc_auth_ugp {
5151struct ipc_auth_data {
5252 int32_t sock ;
5353 struct qb_ipcs_service * s ;
54- struct qb_ipc_connection_request msg ;
54+ union {
55+ struct qb_ipc_connection_request req ;
56+ struct qb_ipc_connection_response res ;
57+ } msg ;
5558 struct msghdr msg_recv ;
5659 struct iovec iov_recv ;
5760 struct ipc_auth_ugp ugp ;
@@ -311,12 +314,138 @@ qb_ipcc_us_sock_close(int32_t sock)
311314 close (sock );
312315}
313316
317+ static int32_t
318+ qb_ipc_auth_creds (struct ipc_auth_data * data )
319+ {
320+ int32_t res = 0 ;
321+
322+ /*
323+ * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
324+ * retrieval mechanisms for various Platforms
325+ */
326+ #ifdef HAVE_GETPEERUCRED
327+ /*
328+ * Solaris and some BSD systems
329+ */
330+ {
331+ ucred_t * uc = NULL ;
332+
333+ if (getpeerucred (data -> sock , & uc ) == 0 ) {
334+ res = 0 ;
335+ data -> ugp .uid = ucred_geteuid (uc );
336+ data -> ugp .gid = ucred_getegid (uc );
337+ data -> ugp .pid = ucred_getpid (uc );
338+ ucred_free (uc );
339+ } else {
340+ res = - errno ;
341+ }
342+ }
343+ #elif defined(HAVE_GETPEEREID )
344+ /*
345+ * Usually MacOSX systems
346+ */
347+ {
348+ /*
349+ * TODO get the peer's pid.
350+ * c->pid = ?;
351+ */
352+ if (getpeereid (data -> sock , & data -> ugp .uid , & data -> ugp .gid ) == 0 ) {
353+ res = 0 ;
354+ } else {
355+ res = - errno ;
356+ }
357+ }
358+
359+ #elif defined(SO_PASSCRED )
360+ /*
361+ * Usually Linux systems
362+ */
363+ {
364+ struct ucred cred ;
365+ struct cmsghdr * cmsg ;
366+
367+ res = - EINVAL ;
368+ for (cmsg = CMSG_FIRSTHDR (& data -> msg_recv ); cmsg != NULL ;
369+ cmsg = CMSG_NXTHDR (& data -> msg_recv , cmsg )) {
370+ if (cmsg -> cmsg_type != SCM_CREDENTIALS )
371+ continue ;
372+
373+ memcpy (& cred , CMSG_DATA (cmsg ), sizeof (struct ucred ));
374+ res = 0 ;
375+ data -> ugp .pid = cred .pid ;
376+ data -> ugp .uid = cred .uid ;
377+ data -> ugp .gid = cred .gid ;
378+ break ;
379+ }
380+ }
381+ #else /* no credentials */
382+ data -> ugp .pid = 0 ;
383+ data -> ugp .uid = 0 ;
384+ data -> ugp .gid = 0 ;
385+ res = - ENOTSUP ;
386+ #endif /* no credentials */
387+
388+ return res ;
389+ }
390+
391+ static void
392+ destroy_ipc_auth_data (struct ipc_auth_data * data )
393+ {
394+ if (data -> s ) {
395+ qb_ipcs_unref (data -> s );
396+ }
397+
398+ #ifdef SO_PASSCRED
399+ free (data -> cmsg_cred );
400+ #endif
401+ free (data );
402+ }
403+
404+ static struct ipc_auth_data *
405+ init_ipc_auth_data (int sock , size_t len )
406+ {
407+ struct ipc_auth_data * data = calloc (1 , sizeof (struct ipc_auth_data ));
408+
409+ if (data == NULL ) {
410+ return NULL ;
411+ }
412+
413+ data -> msg_recv .msg_iov = & data -> iov_recv ;
414+ data -> msg_recv .msg_iovlen = 1 ;
415+ data -> msg_recv .msg_name = 0 ;
416+ data -> msg_recv .msg_namelen = 0 ;
417+
418+ #ifdef SO_PASSCRED
419+ data -> cmsg_cred = calloc (1 , CMSG_SPACE (sizeof (struct ucred )));
420+ if (data -> cmsg_cred == NULL ) {
421+ destroy_ipc_auth_data (data );
422+ return NULL ;
423+ }
424+ data -> msg_recv .msg_control = (void * )data -> cmsg_cred ;
425+ data -> msg_recv .msg_controllen = CMSG_SPACE (sizeof (struct ucred ));
426+ #endif
427+ #ifdef QB_SOLARIS
428+ data -> msg_recv .msg_accrights = 0 ;
429+ data -> msg_recv .msg_accrightslen = 0 ;
430+ #else
431+ data -> msg_recv .msg_flags = 0 ;
432+ #endif /* QB_SOLARIS */
433+
434+ data -> len = len ;
435+ data -> iov_recv .iov_base = & data -> msg ;
436+ data -> iov_recv .iov_len = data -> len ;
437+ data -> sock = sock ;
438+
439+ return data ;
440+ }
441+
314442int32_t
315443qb_ipcc_us_setup_connect (struct qb_ipcc_connection * c ,
316444 struct qb_ipc_connection_response * r )
317445{
318446 int32_t res ;
319447 struct qb_ipc_connection_request request ;
448+ struct ipc_auth_data * data ;
320449#ifdef QB_LINUX
321450 int off = 0 ;
322451 int on = 1 ;
@@ -340,22 +469,33 @@ qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
340469 qb_ipcc_us_sock_close (c -> setup .u .us .sock );
341470 return res ;
342471 }
472+
473+ data = init_ipc_auth_data (c -> setup .u .us .sock , sizeof (struct qb_ipc_connection_response ));
474+ if (data == NULL ) {
475+ qb_ipcc_us_sock_close (c -> setup .u .us .sock );
476+ return - ENOMEM ;
477+ }
478+
479+ qb_ipc_us_ready (& c -> setup , NULL , -1 , POLLIN );
480+ res = qb_ipc_us_recv_msghdr (data );
481+
343482#ifdef QB_LINUX
344483 setsockopt (c -> setup .u .us .sock , SOL_SOCKET , SO_PASSCRED , & off ,
345484 sizeof (off ));
346485#endif
347486
348- res =
349- qb_ipc_us_recv (& c -> setup , r ,
350- sizeof (struct qb_ipc_connection_response ), -1 );
351- if (res < 0 ) {
487+ if (res != data -> len ) {
488+ destroy_ipc_auth_data (data );
352489 return res ;
353490 }
354491
355- if (r -> hdr .error != 0 ) {
356- return r -> hdr .error ;
357- }
358- return 0 ;
492+ memcpy (r , & data -> msg .res , sizeof (struct qb_ipc_connection_response ));
493+
494+ qb_ipc_auth_creds (data );
495+ c -> egid = data -> ugp .gid ;
496+
497+ destroy_ipc_auth_data (data );
498+ return r -> hdr .error ;
359499}
360500
361501/*
@@ -568,19 +708,6 @@ handle_new_connection(struct qb_ipcs_service *s,
568708 return res ;
569709}
570710
571- static void
572- destroy_ipc_auth_data (struct ipc_auth_data * data )
573- {
574- if (data -> s ) {
575- qb_ipcs_unref (data -> s );
576- }
577-
578- #ifdef SO_PASSCRED
579- free (data -> cmsg_cred );
580- #endif
581- free (data );
582- }
583-
584711static int32_t
585712process_auth (int32_t fd , int32_t revents , void * d )
586713{
@@ -622,71 +749,7 @@ process_auth(int32_t fd, int32_t revents, void *d)
622749 goto cleanup_and_return ;
623750 }
624751
625- /*
626- * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
627- * retrieval mechanisms for various Platforms
628- */
629- #ifdef HAVE_GETPEERUCRED
630- /*
631- * Solaris and some BSD systems
632- */
633- {
634- ucred_t * uc = NULL ;
635-
636- if (getpeerucred (data -> sock , & uc ) == 0 ) {
637- res = 0 ;
638- data -> ugp .uid = ucred_geteuid (uc );
639- data -> ugp .gid = ucred_getegid (uc );
640- data -> ugp .pid = ucred_getpid (uc );
641- ucred_free (uc );
642- } else {
643- res = - errno ;
644- }
645- }
646- #elif HAVE_GETPEEREID
647- /*
648- * Usually MacOSX systems
649- */
650- {
651- /*
652- * TODO get the peer's pid.
653- * c->pid = ?;
654- */
655- if (getpeereid (data -> sock , & data -> ugp .uid , & data -> ugp .gid ) == 0 ) {
656- res = 0 ;
657- } else {
658- res = - errno ;
659- }
660- }
661-
662- #elif SO_PASSCRED
663- /*
664- * Usually Linux systems
665- */
666- {
667- struct ucred cred ;
668- struct cmsghdr * cmsg ;
669-
670- res = - EINVAL ;
671- for (cmsg = CMSG_FIRSTHDR (& data -> msg_recv ); cmsg != NULL ;
672- cmsg = CMSG_NXTHDR (& data -> msg_recv , cmsg )) {
673- if (cmsg -> cmsg_type != SCM_CREDENTIALS )
674- continue ;
675-
676- memcpy (& cred , CMSG_DATA (cmsg ), sizeof (struct ucred ));
677- res = 0 ;
678- data -> ugp .pid = cred .pid ;
679- data -> ugp .uid = cred .uid ;
680- data -> ugp .gid = cred .gid ;
681- break ;
682- }
683- }
684- #else /* no credentials */
685- data -> ugp .pid = 0 ;
686- data -> ugp .uid = 0 ;
687- data -> ugp .gid = 0 ;
688- res = - ENOTSUP ;
689- #endif /* no credentials */
752+ res = qb_ipc_auth_creds (data );
690753
691754cleanup_and_return :
692755#ifdef SO_PASSCRED
@@ -697,7 +760,7 @@ process_auth(int32_t fd, int32_t revents, void *d)
697760
698761 if (res < 0 ) {
699762 close (data -> sock );
700- } else if (data -> msg .hdr .id == QB_IPC_MSG_AUTHENTICATE ) {
763+ } else if (data -> msg .req . hdr .id == QB_IPC_MSG_AUTHENTICATE ) {
701764 (void )handle_new_connection (data -> s , res , data -> sock , & data -> msg , data -> len , & data -> ugp );
702765 } else {
703766 close (data -> sock );
@@ -716,7 +779,7 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, struct qb_ipcs_service *s)
716779 int on = 1 ;
717780#endif
718781
719- data = calloc ( 1 , sizeof (struct ipc_auth_data ));
782+ data = init_ipc_auth_data ( sock , sizeof (struct qb_ipc_connection_request ));
720783 if (data == NULL ) {
721784 close (sock );
722785 /* -ENOMEM */
@@ -726,34 +789,6 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, struct qb_ipcs_service *s)
726789 data -> s = s ;
727790 qb_ipcs_ref (data -> s );
728791
729- data -> msg_recv .msg_iov = & data -> iov_recv ;
730- data -> msg_recv .msg_iovlen = 1 ;
731- data -> msg_recv .msg_name = 0 ;
732- data -> msg_recv .msg_namelen = 0 ;
733-
734- #ifdef SO_PASSCRED
735- data -> cmsg_cred = calloc (1 ,CMSG_SPACE (sizeof (struct ucred )));
736- if (data -> cmsg_cred == NULL ) {
737- close (sock );
738- destroy_ipc_auth_data (data );
739- /* -ENOMEM */
740- return ;
741- }
742- data -> msg_recv .msg_control = (void * )data -> cmsg_cred ;
743- data -> msg_recv .msg_controllen = CMSG_SPACE (sizeof (struct ucred ));
744- #endif
745- #ifdef QB_SOLARIS
746- data -> msg_recv .msg_accrights = 0 ;
747- data -> msg_recv .msg_accrightslen = 0 ;
748- #else
749- data -> msg_recv .msg_flags = 0 ;
750- #endif /* QB_SOLARIS */
751-
752- data -> len = sizeof (struct qb_ipc_connection_request );
753- data -> iov_recv .iov_base = & data -> msg ;
754- data -> iov_recv .iov_len = data -> len ;
755- data -> sock = sock ;
756-
757792#ifdef SO_PASSCRED
758793 setsockopt (sock , SOL_SOCKET , SO_PASSCRED , & on , sizeof (on ));
759794#endif
0 commit comments