From b087cbcdbc1d2c76b73f4a7b426fc54103abd27e Mon Sep 17 00:00:00 2001 From: Giovanni Giacobbi Date: Fri, 29 Mar 2002 02:38:54 +0000 Subject: [PATCH] Added checking for prv/pub keys in serverconfig. Moved functions silc_server_drop and silc_server_daemonise to silcd.c. Added some .cvsignore files Reverted a small part of the automatic ref/unref code, it was causing double unref in some situations. --- CHANGES | 16 +++++ apps/silcd/server.c | 148 +++----------------------------------- apps/silcd/server.h | 2 - apps/silcd/serverconfig.c | 29 +++++--- apps/silcd/silcd.c | 125 ++++++++++++++++++++++++++++++-- lib/.cvsignore | 3 + lib/silcclient/.cvsignore | 2 + lib/silccore/.cvsignore | 2 + lib/silccrypt/.cvsignore | 2 + lib/silcmath/.cvsignore | 2 + lib/silcsftp/.cvsignore | 2 + lib/silcsim/.cvsignore | 2 + 12 files changed, 176 insertions(+), 159 deletions(-) create mode 100644 lib/.cvsignore create mode 100644 lib/silcclient/.cvsignore create mode 100644 lib/silccore/.cvsignore create mode 100644 lib/silccrypt/.cvsignore create mode 100644 lib/silcmath/.cvsignore create mode 100644 lib/silcsftp/.cvsignore create mode 100644 lib/silcsim/.cvsignore diff --git a/CHANGES b/CHANGES index aaacac4e..e0bf6491 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,19 @@ +Fri Mar 29 03:26:12 CET 2002 Johnny Mnemonic + + * Added preliminary checking during config parsing for a valid + public/private key and removed further checks in the code. + Affected files are silcd/serverconfig.[ch], server.c. + + * Moved functions silc_server_drop() and silc_server_daemonise() + from server.c to silcd.c since they are stricly related to + the application activity. + + * Reverted a small part of the automatic ref/unref since + it caused a double unref in some situations. Affected + files are silcd/silcd.[ch], server.c, serverconfig.c. + + * Added some .cvsignore files in the lib directory. + Thu Mar 28 22:51:15 EET 2002 Pekka Riikonen * Fixed silc_net_gethostbyaddr to correctly resolve by diff --git a/apps/silcd/server.c b/apps/silcd/server.c index b785c518..6db5a87c 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -147,19 +147,6 @@ bool silc_server_init(SilcServer server) SilcSocketConnection newsocket = NULL; SILC_LOG_DEBUG(("Initializing server")); - assert(server); - assert(server->config); - - silc_server_config_ref(&server->config_ref, server->config, - server->config); - - /* Set public and private keys */ - if (!server->config->server_info || - !server->config->server_info->public_key || - !server->config->server_info->private_key) { - SILC_LOG_ERROR(("Server public key and/or private key does not exist")); - return FALSE; - } /* Steal public and private key from the config object */ server->public_key = server->config->server_info->public_key; @@ -277,7 +264,7 @@ bool silc_server_init(SilcServer server) goto err; } id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED; - + /* Put the allocated socket pointer also to the entry allocated above for fast back-referencing to the socket list. */ newsocket->user_data = (void *)id_entry; @@ -366,36 +353,26 @@ bool silc_server_rehash(SilcServer server) { SilcServerConfig newconfig; - /* Our old config is gone now. We'll unreference our reference made in - silc_server_init and then destroy it since we are destroying it - underneath the application (layer which called silc_server_init). */ - silc_server_config_unref(&server->config_ref); - silc_server_config_destroy(server->config); + SILC_LOG_INFO(("Rehashing server")); /* Reset the logging system */ silc_log_quick = TRUE; silc_log_flush_all(); /* Start the main rehash phase (read again the config file) */ - SILC_LOG_INFO(("Rehashing server")); newconfig = silc_server_config_alloc(server->config_file); if (!newconfig) { SILC_LOG_ERROR(("Rehash FAILED.")); return FALSE; } - /* Take new config context */ + /* Config file parsing went fine, so our old config is gone now. We + unreference the basic pointer and it should be destroyed as soon + as all other references are released. */ + silc_server_config_unref(&server->config_ref); server->config = newconfig; silc_server_config_ref(&server->config_ref, server->config, server->config); - /* Set public and private keys */ - if (!server->config->server_info || - !server->config->server_info->public_key || - !server->config->server_info->private_key) { - SILC_LOG_ERROR(("Server public key and/or private key does not exist")); - return FALSE; - } - /* Fix the server_name field */ if (!strcmp(server->server_name, newconfig->server_info->server_name)) { /* We don't need any update */ @@ -410,7 +387,7 @@ bool silc_server_rehash(SilcServer server) silc_free(server->id_entry->server_name); server->id_entry->server_name = strdup(server->server_name); silc_idcache_del_by_context(server->local_list->servers, server->id_entry); - silc_idcache_add(server->local_list->servers, + silc_idcache_add(server->local_list->servers, server->id_entry->server_name, server->id_entry->id, server->id_entry, 0, NULL); } @@ -418,9 +395,9 @@ bool silc_server_rehash(SilcServer server) silc_server_config_setlogfiles(server); /* Change new key pair if necessary */ - if (server->config->server_info->public_key && + if (newconfig->server_info->public_key && !silc_pkcs_public_key_compare(server->public_key, - server->config->server_info->public_key)) { + newconfig->server_info->public_key)) { silc_pkcs_public_key_free(server->public_key); silc_pkcs_private_key_free(server->private_key); server->public_key = server->config->server_info->public_key; @@ -439,113 +416,6 @@ bool silc_server_rehash(SilcServer server) return TRUE; } -/* Drop root privileges. If some system call fails, die. */ - -void silc_server_drop(SilcServer server) -{ - /* Are we executing silcd as root or a regular user? */ - if (geteuid()) { - SILC_LOG_DEBUG(("Server started as user")); - } - else { - struct passwd *pw; - struct group *gr; - char *user, *group; - - SILC_LOG_DEBUG(("Server started as root. Dropping privileges.")); - - /* Get the values given for user and group in configuration file */ - user = server->config->server_info->user; - group = server->config->server_info->group; - - if (!user || !group) { - fprintf(stderr, "Error:" - "\tSILC server must not be run as root. For the security of your\n" - "\tsystem it is strongly suggested that you run SILC under dedicated\n" - "\tuser account. Modify the ServerInfo configuration section to run\n" - "\tthe server as non-root user.\n"); - exit(1); - } - - /* Check whether the user/group does not begin with a number */ - if (isdigit(user[0]) || isdigit(group[0])) { - SILC_LOG_DEBUG(("User and/or group starts with a number")); - fprintf(stderr, "Invalid user and/or group information\n"); - fprintf(stderr, "Please assign them as names, not numbers\n"); - exit(1); - } - - if (!(pw = getpwnam(user))) { - fprintf(stderr, "Error: No such user %s found.\n", user); - exit(1); - } - if (!(gr = getgrnam(group))) { - fprintf(stderr, "Error: No such group %s found.\n", group); - exit(1); - } - - /* 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)) { - fprintf(stderr, "Error:" - "\tSILC server must not be run as root. For the security of your\n" - "\tsystem it is strongly suggested that you run SILC under dedicated\n" - "\tuser account. Modify the ServerInfo configuration section to run\n" - "\tthe server as non-root user.\n"); - exit(1); - } - - SILC_LOG_DEBUG(("Changing to group %s (gid=%u)", group, gr->gr_gid)); - if (setgid(gr->gr_gid) != 0) { - fprintf(stderr, "Error: Failed setgid() to %s (gid=%u). Exiting.\n", - group, gr->gr_gid); - exit(1); - } -#if defined HAVE_SETGROUPS && defined HAVE_INITGROUPS - SILC_LOG_DEBUG(("Removing supplementary groups")); - if (setgroups(0, NULL) != 0) { - fprintf(stderr, "Error: Failed setgroups() to NULL. Exiting.\n"); - exit(1); - } - SILC_LOG_DEBUG(("Setting supplementary groups for user %s", user)); - if (initgroups(user, gr->gr_gid) != 0) { - fprintf(stderr, "Error: Failed initgroups() for user %s (gid=%u). " - "Exiting.\n", user, gr->gr_gid); - exit(1); - } -#endif - SILC_LOG_DEBUG(("Changing to user %s (uid=%u)", user, pw->pw_uid)); - if (setuid(pw->pw_uid) != 0) { - fprintf(stderr, "Error: Failed to setuid() to %s (gid=%u). Exiting.\n", - user, pw->pw_uid); - exit(1); - } - } -} - -/* Fork server to background */ - -void silc_server_daemonise(SilcServer server) -{ - int i; - - SILC_LOG_DEBUG(("Forking SILC server to background")); - - if ((i = fork()) < 0) { - fprintf(stderr, "Error: fork() failed: %s\n", strerror(errno)); - exit(1); - } - - if (i) /* Kill the parent */ - exit(0); - - server->background = TRUE; - setsid(); - - /* XXX close stdin, stdout, stderr -- before this, check that all writes - to stderr are changed to SILC_SERVER_LOG_ERROR() */ -} - /* The heart of the server. This runs the scheduler thus runs the server. When this returns the server has been stopped and the program will be terminated. */ diff --git a/apps/silcd/server.h b/apps/silcd/server.h index bd35441e..a3b2e45d 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -114,8 +114,6 @@ int silc_server_alloc(SilcServer *new_server); void silc_server_free(SilcServer server); bool silc_server_init(SilcServer server); bool silc_server_rehash(SilcServer server); -void silc_server_drop(SilcServer server); -void silc_server_daemonise(SilcServer server); void silc_server_run(SilcServer server); void silc_server_stop(SilcServer server); void silc_server_start_key_exchange(SilcServer server, diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index 8a8aea50..0d217e7c 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -430,6 +430,10 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo) if (type == SILC_CONFIG_ARG_BLOCK) { /* check for mandatory inputs */ + if (!server_info->public_key || !server_info->private_key) { + got_errno = SILC_CONFIG_EMISSFIELDS; + goto got_err; + } return SILC_CONFIG_OK; } if (!strcmp(name, "hostname")) { @@ -1215,7 +1219,7 @@ SilcServerConfig silc_server_config_alloc(const char *filename) /* obtain a config file object */ file = silc_config_open(filename); if (!file) { - SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n", + SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n", filename)); return NULL; } @@ -1241,7 +1245,7 @@ SilcServerConfig silc_server_config_alloc(const char *filename) SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n", silc_config_strerror(ret))); linebuf = silc_config_read_line(file, line); - SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename, + SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename, line, linebuf)); silc_free(linebuf); } @@ -1265,7 +1269,6 @@ SilcServerConfig silc_server_config_alloc(const char *filename) /* Set default to configuration parameters */ silc_server_config_set_defaults(config_new); - config_new->refcount = 1; return config_new; } @@ -1288,8 +1291,16 @@ void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config, void silc_server_config_unref(SilcServerConfigRef *ref) { - if (ref->ref_ptr) - silc_server_config_destroy(ref->config); + SilcServerConfig config = ref->config; + + if (ref->ref_ptr) { + config->refcount--; + SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config, + config->refcount + 1, config->refcount)); + if (!config->refcount) + silc_server_config_destroy(config); + ref->ref_ptr = NULL; + } } /* Destroy a config object with all his children lists */ @@ -1298,12 +1309,6 @@ void silc_server_config_destroy(SilcServerConfig config) { void *tmp; - config->refcount--; - SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config, - config->refcount + 1, config->refcount)); - if (config->refcount > 0) - return; - SILC_LOG_DEBUG(("Freeing config context")); silc_free(config->module_path); @@ -1331,6 +1336,8 @@ void silc_server_config_destroy(SilcServerConfig config) silc_free(si->group); silc_free(si->motd_file); silc_free(si->pid_file); + silc_pkcs_public_key_free(si->public_key); + silc_pkcs_private_key_free(si->private_key); } /* Now let's destroy the lists */ diff --git a/apps/silcd/silcd.c b/apps/silcd/silcd.c index ee328f93..2ad30724 100644 --- a/apps/silcd/silcd.c +++ b/apps/silcd/silcd.c @@ -60,7 +60,6 @@ static struct option long_opts[] = }; /* Command line option variables */ -static bool opt_create_keypair = FALSE; static char *opt_keypath = NULL; static char *opt_pkcs = "rsa"; static char *opt_identifier = NULL; @@ -102,7 +101,7 @@ static void silc_usage(void) exit(0); } -/* Dies if a *valid* pid file exists already */ +/* Die if a *valid* pid file exists already */ static void silc_server_checkpid(SilcServer silcd) { @@ -130,6 +129,113 @@ static void silc_server_checkpid(SilcServer silcd) } } +/* Drop root privileges. If some system call fails, die. */ + +static void silc_server_drop(SilcServer server) +{ + /* Are we executing silcd as root or a regular user? */ + if (geteuid()) { + SILC_LOG_DEBUG(("Server started as user")); + } + else { + struct passwd *pw; + struct group *gr; + char *user, *group; + + SILC_LOG_DEBUG(("Server started as root. Dropping privileges.")); + + /* Get the values given for user and group in configuration file */ + user = server->config->server_info->user; + group = server->config->server_info->group; + + if (!user || !group) { + fprintf(stderr, "Error:" + "\tSILC server must not be run as root. For the security of your\n" + "\tsystem it is strongly suggested that you run SILC under dedicated\n" + "\tuser account. Modify the ServerInfo configuration section to run\n" + "\tthe server as non-root user.\n"); + exit(1); + } + + /* Check whether the user/group does not begin with a number */ + if (isdigit(user[0]) || isdigit(group[0])) { + SILC_LOG_DEBUG(("User and/or group starts with a number")); + fprintf(stderr, "Invalid user and/or group information\n"); + fprintf(stderr, "Please assign them as names, not numbers\n"); + exit(1); + } + + if (!(pw = getpwnam(user))) { + fprintf(stderr, "Error: No such user %s found.\n", user); + exit(1); + } + if (!(gr = getgrnam(group))) { + fprintf(stderr, "Error: No such group %s found.\n", group); + exit(1); + } + + /* 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)) { + fprintf(stderr, "Error:" + "\tSILC server must not be run as root. For the security of your\n" + "\tsystem it is strongly suggested that you run SILC under dedicated\n" + "\tuser account. Modify the ServerInfo configuration section to run\n" + "\tthe server as non-root user.\n"); + exit(1); + } + + SILC_LOG_DEBUG(("Changing to group %s (gid=%u)", group, gr->gr_gid)); + if (setgid(gr->gr_gid) != 0) { + fprintf(stderr, "Error: Failed setgid() to %s (gid=%u). Exiting.\n", + group, gr->gr_gid); + exit(1); + } +#if defined HAVE_SETGROUPS && defined HAVE_INITGROUPS + SILC_LOG_DEBUG(("Removing supplementary groups")); + if (setgroups(0, NULL) != 0) { + fprintf(stderr, "Error: Failed setgroups() to NULL. Exiting.\n"); + exit(1); + } + SILC_LOG_DEBUG(("Setting supplementary groups for user %s", user)); + if (initgroups(user, gr->gr_gid) != 0) { + fprintf(stderr, "Error: Failed initgroups() for user %s (gid=%u). " + "Exiting.\n", user, gr->gr_gid); + exit(1); + } +#endif + SILC_LOG_DEBUG(("Changing to user %s (uid=%u)", user, pw->pw_uid)); + if (setuid(pw->pw_uid) != 0) { + fprintf(stderr, "Error: Failed to setuid() to %s (gid=%u). Exiting.\n", + user, pw->pw_uid); + exit(1); + } + } +} + +/* Fork server to background */ + +static void silc_server_daemonise(SilcServer server) +{ + int i; + + SILC_LOG_DEBUG(("Forking SILC server to background")); + + if ((i = fork()) < 0) { + fprintf(stderr, "Error: fork() failed: %s\n", strerror(errno)); + exit(1); + } + + if (i) /* Kill the parent */ + exit(0); + + server->background = TRUE; + setsid(); + + /* XXX close stdin, stdout, stderr -- before this, check that all writes + to stderr are changed to SILC_SERVER_LOG_ERROR() */ +} + static void signal_handler(int sig) { /* Mark the signal to be caller after this signal is over. */ @@ -153,6 +259,9 @@ SILC_TASK_CALLBACK(stop_server) silc_schedule_stop(silcd->schedule); } +/* This function should not be called directly but throught the wrapper + macro SILC_SERVER_LOG_STDERR() */ + void silc_server_stderr(char *message) { if (silcd->background) @@ -167,6 +276,7 @@ int main(int argc, char **argv) { int ret, opt, option_index; bool foreground = FALSE; + bool opt_create_keypair = FALSE; char *silcd_config_file = NULL; struct sigaction sa; @@ -174,15 +284,14 @@ int main(int argc, char **argv) if (argc > 1) { while ((opt = getopt_long(argc, argv, "f:p:d::xhFVC:", long_opts, &option_index)) != EOF) { - switch(opt) - { + switch(opt) { case 'h': silc_usage(); break; case 'V': printf("SILCd Secure Internet Live Conferencing daemon, " "version %s (base: SILC Toolkit %s)\n", - silc_dist_version, silc_version); + silc_dist_version, silc_version); printf("(c) 1997 - 2002 Pekka Riikonen " "\n"); exit(0); @@ -243,7 +352,7 @@ int main(int argc, char **argv) default: silc_usage(); break; - } + } } } @@ -272,6 +381,9 @@ int main(int argc, char **argv) if (silcd->config == NULL) goto fail; silcd->config_file = silcd_config_file; + /* Since silc_server_config_alloc returns an unreferenced config object + we must immediately increment it. */ + silc_server_config_ref(&silcd->config_ref, silcd->config, silcd->config); /* Check for another silcd running */ silc_server_checkpid(silcd); @@ -316,7 +428,6 @@ int main(int argc, char **argv) /* Stop the server and free it. */ silc_server_stop(silcd); silc_server_free(silcd); - silc_server_config_destroy(silcd->config); /* Flush the logging system */ silc_log_flush_all(); diff --git a/lib/.cvsignore b/lib/.cvsignore new file mode 100644 index 00000000..a324157c --- /dev/null +++ b/lib/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in +Makefile.am diff --git a/lib/silcclient/.cvsignore b/lib/silcclient/.cvsignore new file mode 100644 index 00000000..282522db --- /dev/null +++ b/lib/silcclient/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/lib/silccore/.cvsignore b/lib/silccore/.cvsignore new file mode 100644 index 00000000..282522db --- /dev/null +++ b/lib/silccore/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/lib/silccrypt/.cvsignore b/lib/silccrypt/.cvsignore new file mode 100644 index 00000000..282522db --- /dev/null +++ b/lib/silccrypt/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/lib/silcmath/.cvsignore b/lib/silcmath/.cvsignore new file mode 100644 index 00000000..282522db --- /dev/null +++ b/lib/silcmath/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/lib/silcsftp/.cvsignore b/lib/silcsftp/.cvsignore new file mode 100644 index 00000000..282522db --- /dev/null +++ b/lib/silcsftp/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/lib/silcsim/.cvsignore b/lib/silcsim/.cvsignore new file mode 100644 index 00000000..282522db --- /dev/null +++ b/lib/silcsim/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in -- 2.24.0