silc_net_set_socket_nonblock(sock[i]);
server->sock = sock[i];
+ /* Add ourselves also to the socket table. The entry allocated above
+ is sent as argument for fast referencing in the future. */
+ silc_socket_alloc(sock[i], SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
+ server->sockets[sock[i]] = newsocket;
+
+ /* Perform name and address lookups to resolve the listenning address
+ and port. */
+ if (!silc_net_check_local_by_sock(sock[i], &newsocket->hostname,
+ &newsocket->ip)) {
+ if ((server->params->require_reverse_mapping && !newsocket->hostname) ||
+ !newsocket->ip) {
+ SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
+ newsocket->hostname ? newsocket->hostname :
+ newsocket->ip ? newsocket->ip : ""));
+ server->stat.conn_failures++;
+ goto err0;
+ }
+ if (!newsocket->hostname)
+ newsocket->hostname = strdup(newsocket->ip);
+ }
+ newsocket->port = silc_net_get_local_port(sock[i]);
+
/* Create a Server ID for the server. */
- silc_id_create_server_id(sock[i], server->rng, &id);
- if (!id) {
+ silc_id_create_server_id(newsocket->ip, newsocket->port, server->rng, &id);
+ if (!id)
goto err0;
- }
server->id = id;
server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
}
id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
- /* Add ourselves also to the socket table. The entry allocated above
- is sent as argument for fast referencing in the future. */
- silc_socket_alloc(sock[i], SILC_SOCKET_TYPE_SERVER, id_entry,
- &newsocket);
-
- server->sockets[sock[i]] = newsocket;
-
- /* Perform name and address lookups to resolve the listenning address
- and port. */
- if (!silc_net_check_local_by_sock(sock[i], &newsocket->hostname,
- &newsocket->ip)) {
- if ((server->params->require_reverse_mapping && !newsocket->hostname) ||
- !newsocket->ip) {
- SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
- newsocket->hostname ? newsocket->hostname :
- newsocket->ip ? newsocket->ip : ""));
- server->stat.conn_failures++;
- goto err0;
- }
- if (!newsocket->hostname)
- newsocket->hostname = strdup(newsocket->ip);
- }
- newsocket->port = silc_net_get_local_port(sock[i]);
-
/* Put the allocated socket pointer also to the entry allocated above
for fast back-referencing to the socket list. */
- id_entry->connection = (void *)server->sockets[sock[i]];
+ newsocket->user_data = (void *)id_entry;
+ id_entry->connection = (void *)newsocket;
server->id_entry = id_entry;
}
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. */
+/* Fork server to background and set gid+uid to non-root */
void silc_server_daemonise(SilcServer server)
+{
+ int i;
+
+ i = fork ();
+
+ if (i) {
+ if (i > 0) {
+ if (geteuid())
+ SILC_LOG_DEBUG(("Server started as user"));
+ else
+ SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
+
+ SILC_LOG_DEBUG(("Forking SILC server to background"));
+ exit(0);
+ } else {
+ SILC_LOG_DEBUG(("fork() failed, cannot proceed"));
+ exit(1);
+ }
+ }
+ setsid();
+}
+
+/* Drop root privligies. If this cannot be done, die. */
+
+void silc_server_drop(SilcServer server)
{
/* Are we executing silcd as root or a regular user? */
- if (geteuid()==0) {
-
+ if (!geteuid()) {
+
struct passwd *pw;
struct group *gr;
char *user, *group;
-
+
if (!server->config->identity || !server->config->identity->user ||
!server->config->identity->group) {
fprintf(stderr, "Error:"
"\tthe server as non-root user.\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"));
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);
- if (!pw) {
+ if (!(pw=getpwnam(user))) {
fprintf(stderr, "No such user %s found\n", user);
exit(1);
}
- if (!gr) {
+ if (!(gr=getgrnam(group))) {
fprintf(stderr, "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) {
"\tthe server as non-root user.\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) {
+ if (setgid(gr->gr_gid)==0) {
SILC_LOG_DEBUG(("Setgid to %s", group));
} else {
SILC_LOG_DEBUG(("Setgid to %s failed", group));
group);
exit(1);
}
- SILC_LOG_DEBUG(("Changing to user nobody"));
- if(setuid(pw->pw_uid)==0) {
+#if defined HAVE_SETGROUPS && defined HAVE_INITGROUPS
+ if (setgroups(0, NULL)!=0) {
+ SILC_LOG_DEBUG(("Setgroups to NULL failed"));
+ fprintf(stderr, "Tried to setgroups NULL but failed. Exiting\n");
+ exit(1);
+ }
+ if (initgroups(user, gr->gr_gid)!=0) {
+ SILC_LOG_DEBUG(("Initgroups to user %s (gid=%d) failed", user, gr->gr_gid));
+ fprintf(stderr, "Tried to initgroups %s (gid=%d) but no such user. Exiting\n",
+ user, gr->gr_gid);
+ exit(1);
+ }
+#endif
+ SILC_LOG_DEBUG(("Changing to user %s", user));
+ if (setuid(pw->pw_uid)==0) {
SILC_LOG_DEBUG(("Setuid to %s", user));
} else {
SILC_LOG_DEBUG(("Setuid to %s failed", 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();
}
}
SILC_LOG_DEBUG(("Start"));
/* Decode channel key payload */
- payload = silc_channel_key_payload_parse(key_payload);
+ payload = silc_channel_key_payload_parse(key_payload->data,
+ key_payload->len);
if (!payload) {
SILC_LOG_ERROR(("Bad channel key payload, dropped"));
channel = NULL;