From: Pekka Riikonen Date: Sun, 11 Feb 2001 16:13:01 +0000 (+0000) Subject: Added [Identity] config entry and forking support to server. X-Git-Tag: SILC.0.1~257 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=9741406048f9adcb2a47b1ec489b025f398ea554 Added [Identity] config entry and forking support to server. A patch from Bostik. --- diff --git a/CHANGES b/CHANGES index c61205c7..7de0d269 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +Sun Feb 11 18:19:51 EET 2001 Pekka Riikonen + + * Added new config entry [Identity] to fork the server and run + it as specific user and group. A patch from Bostik. + Sat Feb 10 21:13:45 EET 2001 Pekka Riikonen * A big code auditing weekend happening. Auditing code for diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 26b214fd..34cf7d97 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -349,6 +349,95 @@ int silc_server_init(SilcServer server) return FALSE; } +/* Fork server to background and set gid+uid to non-root. + Silcd will not run as root, so trying to set either user or group to + root will cause silcd to exit. */ + +void silc_server_daemonise(SilcServer server) +{ + /* Are we executing silcd as root or a regular user? */ + if (geteuid()==0) { + + struct passwd *pw; + struct group *gr; + char *user, *group; + + if (!server->config->identity->user || + !server->config->identity->group) { + SILC_LOG_DEBUG(("User and/or group not set")); + fprintf(stderr, "User and/or group not set, exiting\n"); + exit(1); + } + + /* Get the values given for user and group in configuration file */ + user=server->config->identity->user; + group=server->config->identity->group; + + /* Check whether the user/group information is text */ + if (atoi(user)!=0 || atoi(group)!=0) { + SILC_LOG_DEBUG(("Invalid user and/or group information")); + SILC_LOG_DEBUG(("User and/or group given as number")); + fprintf(stderr, "Invalid user and/or group information\n"); + fprintf(stderr, "Please assign them as names, not numbers\n"); + exit(1); + } + + /* Catch the nasty incident of string "0" returning 0 from atoi */ + if (strcmp("0", user)==0 || strcmp("0", group)==0) { + SILC_LOG_DEBUG(("User and/or group configured to 0. Unacceptable")); + fprintf(stderr, "User and/or group configured to 0. Exiting\n"); + exit(1); + } + + pw=getpwnam(user); + gr=getgrnam(group); + + /* Check whether user and/or group is set to root. If yes, exit + immediately. Otherwise, setgid and setuid server to user.group */ + if (gr->gr_gid==0 || pw->pw_uid==0) { + SILC_LOG_DEBUG(("FATAL: silcd will not run at root privileges")); + fprintf(stderr, "User and/or group not set. Please set them\n"); + exit(1); + } else { + /* Fork server to background, making it a daemon */ + if (fork()) { + SILC_LOG_DEBUG(("Server started as root. Dropping privileges.")); + SILC_LOG_DEBUG(("Forking SILC server to background")); + exit(0); + } + setsid(); + + SILC_LOG_DEBUG(("Changing to group %s", group)); + if(setgid(gr->gr_gid)==0) { + SILC_LOG_DEBUG(("Setgid to %s", group)); + } else { + SILC_LOG_DEBUG(("Setgid to %s failed", group)); + fprintf(stderr, "Tried to setgid %s but no such group. Exiting\n", + group); + exit(1); + } + SILC_LOG_DEBUG(("Changing to user nobody")); + if(setuid(pw->pw_uid)==0) { + SILC_LOG_DEBUG(("Setuid to %s", user)); + } else { + SILC_LOG_DEBUG(("Setuid to %s failed", user)); + fprintf(stderr, "Tried to setuid %s but no such user. Exiting\n", + user); + exit(1); + } + } + } else { + /* Fork server to background, making it a daemon */ + if (fork()) { + SILC_LOG_DEBUG(("Server started as user")); + SILC_LOG_DEBUG(("Forking SILC server to background")); + exit(0); + } + setsid(); + } +} + + /* Stops the SILC server. This function is used to shutdown the server. This is usually called after the scheduler has returned. After stopping the server one should call silc_server_free. */ diff --git a/apps/silcd/server.h b/apps/silcd/server.h index 719c2728..24cb37c6 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -79,6 +79,7 @@ do { \ int silc_server_alloc(SilcServer *new_server); void silc_server_free(SilcServer server); int silc_server_init(SilcServer server); +void silc_server_daemonise(SilcServer server); void silc_server_run(SilcServer server); void silc_server_stop(SilcServer server); void silc_server_packet_parse(SilcPacketParserContext *parser_context); diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index ffc7e118..4e42c445 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -67,6 +67,15 @@ +:: + + + This section is used to set both the user and group which silcd + sets itself upon starting. + + Format: + + : + This section is used to set various logging files, their paths @@ -161,6 +170,8 @@ SilcConfigServerSection silc_config_server_sections[] = { SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO, 4 }, { "[ListenPort]", SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT, 3 }, + { "[Identity]", + SILC_CONFIG_SERVER_SECTION_TYPE_IDENTITY, 2 }, { "[Logging]", SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING, 3 }, { "[ConnectionClass]", @@ -232,6 +243,7 @@ void silc_config_server_free(SilcConfigServer config) silc_free(config->server_info); silc_free(config->admin_info); silc_free(config->listen_port); + silc_free(config->identity); silc_free(config->conn_class); silc_free(config->clients); silc_free(config->admins); @@ -627,6 +639,23 @@ int silc_config_server_parse_lines(SilcConfigServer config, checkmask |= (1L << pc->section->type); break; + case SILC_CONFIG_SERVER_SECTION_TYPE_IDENTITY: + + if (!config->identity) + config->identity = silc_calloc(1, sizeof(*config->identity)); + + /* Get user */ + ret = silc_config_get_token(line, &config->identity->user); + if (ret < 0) + break; + /* Get group */ + ret = silc_config_get_token(line, &config->identity->group); + if (ret < 0) + break; + + check = TRUE; + checkmask |= (1L << pc->section->type); + case SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS: SILC_SERVER_CONFIG_LIST_ALLOC(config->conn_class); diff --git a/apps/silcd/serverconfig.h b/apps/silcd/serverconfig.h index e4c76d66..0b045fa1 100644 --- a/apps/silcd/serverconfig.h +++ b/apps/silcd/serverconfig.h @@ -57,6 +57,13 @@ typedef struct SilcConfigServerSectionListenPortStruct { struct SilcConfigServerSectionListenPortStruct *prev; } SilcConfigServerSectionListenPort; +/* Holds server's execution identity, or the user and group which + to change from root when server starts */ +typedef struct { + char *user; + char *group; +} SilcConfigServerSectionIdentity; + /* Holds all the configured log files. */ typedef struct SilcConfigServerSectionLoggingStruct { char *logtype; @@ -160,6 +167,7 @@ typedef struct { SilcConfigServerSectionServerInfo *server_info; SilcConfigServerSectionAdminInfo *admin_info; SilcConfigServerSectionListenPort *listen_port; + SilcConfigServerSectionIdentity *identity; SilcConfigServerSectionLogging *logging; SilcConfigServerSectionConnectionClass *conn_class; SilcConfigServerSectionClientConnection *clients; @@ -182,6 +190,7 @@ typedef enum { SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO, SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO, SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT, + SILC_CONFIG_SERVER_SECTION_TYPE_IDENTITY, SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING, SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS, SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION, diff --git a/apps/silcd/silcd.c b/apps/silcd/silcd.c index 3732bb14..214fa344 100644 --- a/apps/silcd/silcd.c +++ b/apps/silcd/silcd.c @@ -34,6 +34,7 @@ static struct option long_opts[] = { { "config-file", 1, NULL, 'f' }, { "generate-config-file", 0, NULL, 'c' }, + { "debug", 0, NULL, 'd' }, { "help", 0, NULL, 'h' }, { "version", 0, NULL,'V' }, { NULL, 0, NULL, 0 } @@ -48,6 +49,7 @@ void silc_usage() printf(" -f --config-file=FILE Alternate configuration file\n"); printf(" -c --generate-config-file Generate example configuration " "file\n"); + printf(" -d --debug Enable debugging (no daemon)\n"); printf(" -h --help Display this message\n"); printf(" -V --version Display version\n"); exit(0); @@ -60,11 +62,11 @@ int main(int argc, char **argv) char *config_file = NULL; SilcServer silcd; - silc_debug = TRUE; + silc_debug = FALSE; /* Parse command line arguments */ if (argc > 1) { - while ((opt = getopt_long(argc, argv, "cf:hV", + while ((opt = getopt_long(argc, argv, "cf:dhV", long_opts, &option_index)) != EOF) { switch(opt) { @@ -83,6 +85,8 @@ int main(int argc, char **argv) silc_config_server_print(); exit(0); break; + case 'd': + silc_debug = TRUE; case 'f': config_file = strdup(optarg); break; @@ -111,6 +115,11 @@ int main(int argc, char **argv) ret = silc_server_init(silcd); if (ret == FALSE) goto fail; + + if (silc_debug == FALSE) + /* Before running the server, fork to background and set + both user and group no non-root */ + silc_server_daemonise(silcd); /* Run the server. When this returns the server has been stopped and we will exit. */ diff --git a/doc/example_silcd.conf b/doc/example_silcd.conf index b08f0563..53d05e1c 100644 --- a/doc/example_silcd.conf +++ b/doc/example_silcd.conf @@ -33,6 +33,15 @@ sha1::64:20 #rsa::1024 #dss::1024 +# +# Run SILC server as specific user and group. The server must be initially +# run as root. +# +# Format: : +# +[Identity] +nobody:nobody + # # Server's administrative information. # diff --git a/includes/clientincludes.h b/includes/clientincludes.h index d579b127..b1dd3aca 100644 --- a/includes/clientincludes.h +++ b/includes/clientincludes.h @@ -25,7 +25,6 @@ #include #include -#include #ifdef HAVE_PATHS_H #include diff --git a/includes/silcincludes.h b/includes/silcincludes.h index b3c3fc70..80f27486 100644 --- a/includes/silcincludes.h +++ b/includes/silcincludes.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include