00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00024 #include "common.h"
00025
00026 #include <errno.h>
00027
00028
00029 #include <sys/types.h>
00030
00031 #include <sys/socket.h>
00032 #include <netinet/in.h>
00033
00034 #include <pwd.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <time.h>
00038 #include <sys/time.h>
00039 #include <unistd.h>
00040 #include <grp.h>
00041
00042 #include "server.h"
00043
00044 #include "conftable.h"
00045 #include "conn_handler.h"
00046 #include "connhandlerlist.h"
00047 #include "logger.h"
00048 #include "signal_handler.h"
00049 #include "xmalloc.h"
00050
00051 int changeUserGroupID();
00052
00053
00055
00057 fd_set sock_recv_set;
00059 fd_set sock_send_set;
00061 fd_set sock_recv_ready_set, sock_send_ready_set;
00062
00064 ConnHandlerList ch_list;
00065
00066
00077 int newServerSocket(unsigned short int port_num) {
00078 int server_sock;
00079 struct sockaddr_in local_addr;
00080
00081 if ((server_sock = socket(PF_INET, SOCK_STREAM, 0)) == 0)
00082 return -1;
00083
00084 local_addr.sin_family = AF_INET;
00085 local_addr.sin_port = htons((unsigned short) port_num);
00086 local_addr.sin_addr.s_addr = INADDR_ANY;
00087
00088 if (bind(server_sock, (struct sockaddr *) &local_addr,
00089 sizeof(local_addr)) != 0)
00090 return -1;
00091
00092 if (listen(server_sock, 10) != 0)
00093 return -1;
00094
00095 return server_sock;
00096 }
00097
00100 int svCloseConnection(ConnHandler ch)
00101 {
00102 int socket = chGetSocket(ch);
00103 if (FD_ISSET(socket, &sock_recv_set)) FD_CLR(socket, &sock_recv_set);
00104 if (FD_ISSET(socket, &sock_recv_ready_set)) FD_CLR(socket, &sock_recv_ready_set);
00105 if (FD_ISSET(socket, &sock_send_set)) FD_CLR(socket, &sock_send_set);
00106 if (FD_ISSET(socket, &sock_send_ready_set)) FD_CLR(socket, &sock_send_ready_set);
00107
00108 chTerminate(ch);
00109 logger(PDEPP_CORE, NOTICE, "client connection closed");
00110 return 0;
00111 }
00112
00116 int svMain(const int port)
00117 {
00118 int server_sock, sock_max, conn_count;
00119 time_t conn_timeout = getEntryDeflI(CONFENTRY_KEY_CONNTIMEOUT, STD_CONFENTRY_VAL_CONNTIMEOUT);
00120 int conn_maxcount = getEntryDeflI(CONFENTRY_KEY_CONNMAXCOUNT, STD_CONFENTRY_VAL_CONNMAXCOUNT);
00121
00123 int err, sock_num, conn_sock;
00124
00125 running = true;
00126
00127 if (port < 1 || port > 65535)
00128 {
00129 logger(PDEPP_CORE, CRITICAL, "svMain: Invalid port range!");
00130 return -1;
00131 }
00132
00133 logger(PDEPP_CORE, NOTICE, "server starting...");
00134
00135 if (conn_maxcount > FD_SETSIZE)
00136 {
00137 logger(PDEPP_CORE, ERROR, "configured maximum number of concurrent connections is too high, "
00138 "maxmimum number supported on this platform is %u", FD_SETSIZE);
00139 conn_maxcount = FD_SETSIZE;
00140 }
00141
00142 server_sock = newServerSocket(port);
00143 if (server_sock < 0)
00144 {
00145 logerr(PDEPP_CORE, CRITICAL, errno,
00146 "svMain: could not initialize server socket");
00147 return -1;
00148 }
00149
00150 logger(PDEPP_CORE, NOTICE, "server initialized");
00151
00152
00153 if (changeUserGroupID() < 0)
00154 return -1;
00155
00156 printf("server running at port %d\n", port);
00157
00158 FD_ZERO(&sock_recv_set);
00159 FD_SET(server_sock, &sock_recv_set);
00160
00161 FD_ZERO(&sock_send_set);
00162
00163 ch_list = chListInit();
00164
00165 sock_max = server_sock;
00166 conn_count = 1;
00167
00168 while (running)
00169 {
00170
00171
00172 sock_recv_ready_set = sock_recv_set;
00173 sock_send_ready_set = sock_send_set;
00174
00175 errno = 0;
00176
00177 sock_num = select(sock_max+1, &sock_recv_ready_set, &sock_send_ready_set, NULL, NULL);
00178
00179 if (sock_num == -1)
00180 switch(errno)
00181 {
00182 #ifndef NDEBUG
00183 case EINVAL:
00184 case EBADF:
00185 logerr(PDEPP_CORE, CRITICAL, errno,
00186 "svMain: internaol server error during select");
00187 abort();
00188 #endif
00189 case EINTR:
00190
00191
00192 continue;
00193 case ENOMEM:
00194 logerr(PDEPP_CORE, CRITICAL, errno,
00195 "svMain: select ran out of memory");
00196 return -1;
00197 default:
00198 logerr(PDEPP_CORE, WARNING, errno,
00199 "svMain: select failed, retrying");
00200 continue;
00201
00202 }
00203 #ifndef NDEBUG
00204 else
00205 if (sock_num == 0)
00206 {
00207 logerr(PDEPP_CORE, CRITICAL, errno, "svMain: select returned 0!!!");
00208 continue;
00209 }
00210 #endif
00211
00212 FD_ZERO(&sock_send_set);
00213
00214 if (FD_ISSET(server_sock, &sock_recv_ready_set))
00215 {
00216 ConnHandler new_ch;
00217
00218 new_ch = chInit(server_sock);
00219 if (new_ch != NULL)
00220 {
00221 int new_sock = chGetSocket(new_ch);
00222 if(conn_count < conn_maxcount) {
00223 FD_SET(new_sock, &sock_recv_set);
00224 chListAppend(ch_list, new_ch);
00225 sock_max = (new_sock > sock_max) ? new_sock : sock_max;
00226 ++conn_count;
00227 } else {
00228
00229 chTerminate(new_ch);
00230 logger(PDEPP_CORE, WARNING, "rejected client: too many connections");
00231 }
00232 }
00233 }
00234
00235 chListFirst(ch_list);
00236 while (!chListIsTail(ch_list))
00237 {
00238
00239 ConnHandler ch = chListGetPayload(ch_list);
00240 err = 0;
00241 conn_sock = chGetSocket(ch);
00242
00243 if (FD_ISSET(conn_sock, &sock_recv_ready_set))
00244 err = chReceive(ch);
00245 if (err == 0)
00246 err = chProcess(ch);
00247 if (err == 0 && FD_ISSET(conn_sock, &sock_send_ready_set))
00248 err = chSend(ch);
00249
00250 if ((time(NULL) - chGetStamp(ch)) > conn_timeout)
00251 {
00252 logger(PDEPP_CORE, WARNING, "%u: client connection timed out", conn_sock);
00253 err = -1;
00254 }
00255
00256
00257 if (err == 0)
00258 if (chIsDataPending(ch))
00259 FD_SET(conn_sock, &sock_send_set);
00260
00261 if (err != 0)
00262 {
00263 if (err != 1)
00264 logerr(PDEPP_CORE, NOTICE, chGetError(ch), "client connection error");
00265 svCloseConnection(ch);
00266 chListDelete(ch_list);
00267 --conn_count;
00268 } else
00269 chListNext(ch_list);
00270 }
00271 }
00272
00273
00274
00275
00276 if (caught_signal != 0)
00277 {
00278 #ifdef HAVE_STRSIGNAL
00279 logger(PDEPP_CORE, CRITICAL,
00280 "caught signal \"%s\", server terminating", strsignal(caught_signal));
00281 #else
00282 logger(PDEPP_CORE, CRITICAL,
00283 "caught signal %d, server terminating", caught_signal);
00284 #endif
00285 }
00286
00287
00288 chListFirst(ch_list);
00289 while(!chListIsTail(ch_list))
00290 {
00291 chTerminate(chListGetPayload(ch_list));
00292 chListDelete(ch_list);
00293 }
00294 chListTerminate(ch_list);
00295
00296
00297 return 0;
00298 }
00299
00300
00308 int changeUserGroupID()
00309 {
00310 uid_t euid = geteuid();
00311 const char* new_user = getEntryDefl(CONFENTRY_KEY_USER, STD_CONFENTRY_VAL_USER);
00312 const char* new_group = getEntryDefl(CONFENTRY_KEY_GROUP, STD_CONFENTRY_VAL_GROUP);
00313 struct passwd* pswd;
00314 struct group* grp;
00315
00316
00317 if (strcmp(new_user, STD_CONFENTRY_VAL_USER) == 0
00318 && strcmp(new_group, STD_CONFENTRY_VAL_GROUP) == 0)
00319 return 0;
00320
00321
00322 if (euid != 0)
00323 {
00324 logger(PDEPP_CORE, CRITICAL, "Error changing user: You need to be root (check user/group settings in configfile)");
00325 return -1;
00326 }
00327
00328
00329 pswd = getpwnam(new_user);
00330 grp = getgrnam(new_group);
00331
00332 if (pswd == NULL)
00333 {
00334 logger(PDEPP_CORE, CRITICAL, "Error: Invalid user \"%s\" given!", new_user);
00335 return -1;
00336 }
00337 if (grp == NULL)
00338 {
00339 logger(PDEPP_CORE, CRITICAL, "Error: Invalid group \"%s\" given!", new_group);
00340 return -1;
00341 }
00342
00343
00344 errno = 0;
00345
00346 if (setgid(grp->gr_gid) < 0)
00347 {
00348 logger(PDEPP_CORE, CRITICAL,
00349 "Error: Could not change to given group \"%s\"!", new_group);
00350 return -1;
00351 }
00352 else if (setuid(pswd->pw_uid) < 0)
00353 {
00354 logger(PDEPP_CORE, CRITICAL,
00355 "Error: Could not change to given user \"%s\"!", new_user);
00356 return -1;
00357 }
00358 else
00359 {
00360 logger(PDEPP_CORE, INFO,
00361 "Successfully changed to user \"%s\" and group \"%s\"!"
00362 , new_user, new_group);
00363 }
00364
00365 return 0;
00366 }