mirror of
				https://github.com/optim-enterprises-bv/nDPId.git
				synced 2025-10-30 17:57:48 +00:00 
			
		
		
		
	nDPIsrvd: Change user/group, allow listening on UNIX socket for incoming distributor connections
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
This commit is contained in:
		
							
								
								
									
										1
									
								
								config.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								config.h
									
									
									
									
									
								
							| @@ -3,6 +3,7 @@ | |||||||
|  |  | ||||||
| /* macros shared across multiple executables */ | /* macros shared across multiple executables */ | ||||||
| #define COLLECTOR_UNIX_SOCKET "/tmp/ndpid-collector.sock" | #define COLLECTOR_UNIX_SOCKET "/tmp/ndpid-collector.sock" | ||||||
|  | #define DISTRIBUTOR_UNIX_SOCKET "/tmp/npid-distributor.sock" | ||||||
| #define DISTRIBUTOR_HOST "127.0.0.1" | #define DISTRIBUTOR_HOST "127.0.0.1" | ||||||
| #define DISTRIBUTOR_PORT 7000 | #define DISTRIBUTOR_PORT 7000 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										134
									
								
								nDPIsrvd.c
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								nDPIsrvd.c
									
									
									
									
									
								
							| @@ -62,15 +62,19 @@ static int main_thread_shutdown = 0; | |||||||
| static int log_to_stderr = 0; | static int log_to_stderr = 0; | ||||||
| static char pidfile[UNIX_PATH_MAX] = nDPIsrvd_PIDFILE; | static char pidfile[UNIX_PATH_MAX] = nDPIsrvd_PIDFILE; | ||||||
| static char json_sockpath[UNIX_PATH_MAX] = COLLECTOR_UNIX_SOCKET; | static char json_sockpath[UNIX_PATH_MAX] = COLLECTOR_UNIX_SOCKET; | ||||||
|  | static enum { SERV_LISTEN_NONE, SERV_LISTEN_TCP, SERV_LISTEN_UNIX } serv_type = SERV_LISTEN_NONE; | ||||||
| static char serv_listen_addr[INET_ADDRSTRLEN] = DISTRIBUTOR_HOST; | static char serv_listen_addr[INET_ADDRSTRLEN] = DISTRIBUTOR_HOST; | ||||||
|  | static char serv_listen_path[UNIX_PATH_MAX] = DISTRIBUTOR_UNIX_SOCKET; | ||||||
| static uint16_t serv_listen_port = DISTRIBUTOR_PORT; | static uint16_t serv_listen_port = DISTRIBUTOR_PORT; | ||||||
| static int json_sockfd; | static int json_sockfd; | ||||||
| static int serv_sockfd; | static int serv_sockfd; | ||||||
|  | static char * user = NULL; | ||||||
|  | static char * group = NULL; | ||||||
|  |  | ||||||
| static int create_listen_sockets(void) | static int create_listen_sockets(void) | ||||||
| { | { | ||||||
|     json_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); |     json_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); | ||||||
|     serv_sockfd = socket(AF_INET, SOCK_STREAM, 0); |     serv_sockfd = socket((serv_type == SERV_LISTEN_UNIX ? AF_UNIX : AF_INET), SOCK_STREAM, 0); | ||||||
|     if (json_sockfd < 0 || serv_sockfd < 0) |     if (json_sockfd < 0 || serv_sockfd < 0) | ||||||
|     { |     { | ||||||
|         syslog(LOG_DAEMON | LOG_ERR, "Error opening socket: %s", strerror(errno)); |         syslog(LOG_DAEMON | LOG_ERR, "Error opening socket: %s", strerror(errno)); | ||||||
| @@ -93,27 +97,66 @@ static int create_listen_sockets(void) | |||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     struct sockaddr_in serv_addr; |     struct sockaddr * addr; | ||||||
|     memset(&serv_addr, 0, sizeof(serv_addr)); |     socklen_t addrlen; | ||||||
|     serv_addr.sin_family = AF_INET; |     struct sockaddr_in serv_addr_in; | ||||||
|     if (inet_pton(AF_INET, &serv_listen_addr[0], &serv_addr.sin_addr) != 1) |     struct sockaddr_un serv_addr_un; | ||||||
|  |  | ||||||
|  |     switch (serv_type) | ||||||
|     { |     { | ||||||
|         syslog(LOG_DAEMON | LOG_ERR, "Error converting an internet address: %s", strerror(errno)); |         case SERV_LISTEN_NONE: | ||||||
|         return 1; |         case SERV_LISTEN_TCP: | ||||||
|  |             memset(&serv_addr_in, 0, sizeof(serv_addr_in)); | ||||||
|  |             serv_addr_in.sin_family = AF_INET; | ||||||
|  |             if (inet_pton(AF_INET, &serv_listen_addr[0], &serv_addr_in.sin_addr) != 1) | ||||||
|  |             { | ||||||
|  |                 syslog(LOG_DAEMON | LOG_ERR, "Error converting an internet address: %s", strerror(errno)); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             serv_addr_in.sin_port = htons(serv_listen_port); | ||||||
|  |             addr = (struct sockaddr *)&serv_addr_in; | ||||||
|  |             addrlen = sizeof(serv_addr_in); | ||||||
|  |             break; | ||||||
|  |         case SERV_LISTEN_UNIX: | ||||||
|  |             memset(&serv_addr_un, 0, sizeof(serv_addr_un)); | ||||||
|  |             serv_addr_un.sun_family = AF_UNIX; | ||||||
|  |             if (snprintf(serv_addr_un.sun_path, sizeof(serv_addr_un.sun_path), "%s", serv_listen_path) <= 0) | ||||||
|  |             { | ||||||
|  |                 syslog(LOG_DAEMON | LOG_ERR, "snprintf failed: %s", strerror(errno)); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             addr = (struct sockaddr *)&serv_addr_un; | ||||||
|  |             addrlen = sizeof(serv_addr_un); | ||||||
|  |             break; | ||||||
|     } |     } | ||||||
|     serv_addr.sin_port = htons(serv_listen_port); |  | ||||||
|  |  | ||||||
|     if (bind(json_sockfd, (struct sockaddr *)&json_addr, sizeof(json_addr)) < 0) |     if (bind(json_sockfd, (struct sockaddr *)&json_addr, sizeof(json_addr)) < 0) | ||||||
|     { |     { | ||||||
|         unlink(json_sockpath); |         unlink(json_sockpath); | ||||||
|         syslog(LOG_DAEMON | LOG_ERR, "Error on binding the UNIX socket: %s", strerror(errno)); |         syslog(LOG_DAEMON | LOG_ERR, "Error on binding the UNIX socket to %s: %s", json_sockpath, strerror(errno)); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (bind(serv_sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) |     if (bind(serv_sockfd, addr, addrlen) < 0) | ||||||
|     { |     { | ||||||
|         unlink(json_sockpath); |         unlink(json_sockpath); | ||||||
|         syslog(LOG_DAEMON | LOG_ERR, "Error on binding the INET socket: %s", strerror(errno)); |         switch (serv_type) | ||||||
|  |         { | ||||||
|  |             case SERV_LISTEN_NONE: | ||||||
|  |             case SERV_LISTEN_TCP: | ||||||
|  |                 syslog(LOG_DAEMON | LOG_ERR, | ||||||
|  |                        "Error on binding the INET socket to %s:%u: %s", | ||||||
|  |                        serv_listen_addr, | ||||||
|  |                        serv_listen_port, | ||||||
|  |                        strerror(errno)); | ||||||
|  |                 break; | ||||||
|  |             case SERV_LISTEN_UNIX: | ||||||
|  |                 syslog(LOG_DAEMON | LOG_ERR, | ||||||
|  |                        "Error on binding the UNIX socket to %s: %s", | ||||||
|  |                        serv_listen_path, | ||||||
|  |                        strerror(errno)); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -200,7 +243,7 @@ static int parse_options(int argc, char ** argv) | |||||||
| { | { | ||||||
|     int opt; |     int opt; | ||||||
|  |  | ||||||
|     while ((opt = getopt(argc, argv, "hlc:dp:s:")) != -1) |     while ((opt = getopt(argc, argv, "hlc:dp:s:S:u:g:")) != -1) | ||||||
|     { |     { | ||||||
|         switch (opt) |         switch (opt) | ||||||
|         { |         { | ||||||
| @@ -208,18 +251,22 @@ static int parse_options(int argc, char ** argv) | |||||||
|                 log_to_stderr = 1; |                 log_to_stderr = 1; | ||||||
|                 break; |                 break; | ||||||
|             case 'c': |             case 'c': | ||||||
|                 strncpy(json_sockpath, optarg, sizeof(json_sockpath) - 1); |                 snprintf(json_sockpath, sizeof(json_sockpath), "%s", optarg); | ||||||
|                 json_sockpath[sizeof(json_sockpath) - 1] = '\0'; |  | ||||||
|                 break; |                 break; | ||||||
|             case 'd': |             case 'd': | ||||||
|                 daemonize_enable(); |                 daemonize_enable(); | ||||||
|                 break; |                 break; | ||||||
|             case 'p': |             case 'p': | ||||||
|                 strncpy(pidfile, optarg, sizeof(pidfile) - 1); |                 snprintf(pidfile, sizeof(pidfile), "%s", optarg); | ||||||
|                 pidfile[sizeof(pidfile) - 1] = '\0'; |  | ||||||
|                 break; |                 break; | ||||||
|             case 's': |             case 's': | ||||||
|             { |             { | ||||||
|  |                 if (serv_type != SERV_LISTEN_NONE) | ||||||
|  |                 { | ||||||
|  |                     fprintf(stderr, "%s: -s / -S already set\n", argv[0]); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 char * delim = strchr(optarg, ':'); |                 char * delim = strchr(optarg, ':'); | ||||||
|                 if (delim != NULL) |                 if (delim != NULL) | ||||||
|                 { |                 { | ||||||
| @@ -232,13 +279,36 @@ static int parse_options(int argc, char ** argv) | |||||||
|                         return 1; |                         return 1; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 size_t len = (delim != NULL ? (size_t)(delim - optarg) : strlen(optarg)); |                 size_t len = (delim != NULL ? (size_t)(delim - optarg) : strlen(optarg)) + 1; | ||||||
|                 strncpy(serv_listen_addr, optarg, (len < sizeof(serv_listen_addr) ? len : sizeof(serv_listen_addr))); |                 snprintf(serv_listen_addr, (len < sizeof(serv_listen_addr) ? len : sizeof(serv_listen_addr)), | ||||||
|  |                          "%s", optarg); | ||||||
|  |                 serv_type = SERV_LISTEN_TCP; | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|  |             case 'S': | ||||||
|  |             { | ||||||
|  |                 if (serv_type != SERV_LISTEN_NONE) | ||||||
|  |                 { | ||||||
|  |                     fprintf(stderr, "%s: -s / -S already set\n", argv[0]); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 size_t len = strlen(optarg) + 1; | ||||||
|  |                 snprintf(serv_listen_path, (len < sizeof(serv_listen_path) ? len : sizeof(serv_listen_path)), | ||||||
|  |                          "%s", optarg); | ||||||
|  |                 serv_type = SERV_LISTEN_UNIX; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             case 'u': | ||||||
|  |                 user = strdup(optarg); | ||||||
|  |                 break; | ||||||
|  |             case 'g': | ||||||
|  |                 group = strdup(optarg); | ||||||
|  |                 break; | ||||||
|             default: |             default: | ||||||
|                 fprintf(stderr, |                 fprintf(stderr, | ||||||
|                         "Usage: %s [-l] [-c path-to-unix-sock] [-d] [-p pidfile] -s [distributor-host:port]\n", |                         "Usage: %s [-l] [-c path-to-unix-sock] [-d] [-p pidfile] [-s distributor-host:port] " | ||||||
|  |                         "[-S path-to-unix-socket] [-u user] [-g group]\n", | ||||||
|                         argv[0]); |                         argv[0]); | ||||||
|                 return 1; |                 return 1; | ||||||
|         } |         } | ||||||
| @@ -296,8 +366,30 @@ int main(int argc, char ** argv) | |||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|     syslog(LOG_DAEMON, "collector listen on %s", json_sockpath); |     syslog(LOG_DAEMON, "collector listen on %s", json_sockpath); | ||||||
|     syslog( |     switch (serv_type) { | ||||||
|         LOG_DAEMON, "distributor listen on %.*s:%u", (int)sizeof(serv_listen_addr), serv_listen_addr, serv_listen_port); |         case SERV_LISTEN_NONE: | ||||||
|  |         case SERV_LISTEN_TCP: | ||||||
|  |             syslog(LOG_DAEMON, "distributor listen on %.*s:%u", (int)sizeof(serv_listen_addr), | ||||||
|  |                    serv_listen_addr, serv_listen_port); | ||||||
|  |             break; | ||||||
|  |         case SERV_LISTEN_UNIX: | ||||||
|  |             syslog(LOG_DAEMON, "distributor listen on %s", serv_listen_path); | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     errno = 0; | ||||||
|  |     if (change_user_group(user, group) != 0) | ||||||
|  |     { | ||||||
|  |         if (errno != 0) | ||||||
|  |         { | ||||||
|  |             syslog(LOG_DAEMON | LOG_ERR, "Change user/group failed: %s", strerror(errno)); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             syslog(LOG_DAEMON | LOG_ERR, "Change user/group failed."); | ||||||
|  |         } | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     signal(SIGINT, sighandler); |     signal(SIGINT, sighandler); | ||||||
|     signal(SIGTERM, sighandler); |     signal(SIGTERM, sighandler); | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								utils.c
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								utils.c
									
									
									
									
									
								
							| @@ -1,8 +1,11 @@ | |||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
|  | #include <grp.h> | ||||||
|  | #include <pwd.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <syslog.h> | #include <syslog.h> | ||||||
|  | #include <sys/types.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  |  | ||||||
| #include "utils.h" | #include "utils.h" | ||||||
| @@ -110,3 +113,35 @@ int daemonize_shutdown(char const * const pidfile) | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int change_user_group(char const * const user, char const * const group) | ||||||
|  | { | ||||||
|  |     struct passwd * pwd; | ||||||
|  |     struct group * grp; | ||||||
|  |     gid_t gid; | ||||||
|  |  | ||||||
|  |     if (getuid() != 0) { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (user == NULL) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pwd = getpwnam(user); | ||||||
|  |     if (pwd == NULL) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (group != NULL) { | ||||||
|  |         grp = getgrnam(group); | ||||||
|  |         if (grp == NULL)  { | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |         gid = grp->gr_gid; | ||||||
|  |     } else { | ||||||
|  |         gid = pwd->pw_gid; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return setregid(gid, gid) != 0 || setreuid(pwd->pw_uid, pwd->pw_uid); | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Toni Uhlig
					Toni Uhlig