diff --git a/lib/asl/antd.c b/lib/asl/antd.c index ef3bfb9..7f0fd37 100644 --- a/lib/asl/antd.c +++ b/lib/asl/antd.c @@ -1,5 +1,15 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../lualib.h" // add a length field, and void lua_new_byte_array(lua_State *L, int n) @@ -724,6 +734,148 @@ static int l_is_dir(lua_State *L) return 1; } +static int l_pfork(lua_State* L) +{ + antd_client_t* client = (antd_client_t*)lua_touserdata(L,1); + int sock = client->sock; + // create domain socket + struct sockaddr_un address; + address.sun_family = AF_UNIX; + (void)snprintf(address.sun_path, sizeof(address.sun_path), "/tmp/antd_pfork_%d.sock",sock); + unlink(address.sun_path); + int pfd = socket(AF_UNIX, SOCK_STREAM, 0); + if(pfd == -1) + { + ERROR( "Unable to create Unix domain socket: %s", strerror(errno)); + lua_pushnumber(L, -1); + return 1; + } + if (bind(pfd, (struct sockaddr *)(&address), sizeof(address)) == -1) + { + ERROR("Unable to bind name: %s to a socket: %s", address.sun_path, strerror(errno)); + lua_pushnumber(L, -1); + return 1; + } + // mark the socket as passive mode + if (listen(pfd, 10) == -1) + { + ERROR("Unable to listen to socket: %d (%s): %s", pfd, address.sun_path, strerror(errno)); + lua_pushnumber(L, -1); + close(pfd); + return 1; + } + LOG( "Socket %s is created successfully", address.sun_path); + set_nonblock(pfd); + + int pid = fork(); + if(pid == 0) + { + int child = socket(AF_UNIX, SOCK_STREAM, 0); + if(child == -1) + { + ERROR( "Unable to create Unix domain socket: %s", strerror(errno)); + lua_pushnumber(L, -1); + return -1; + } + if(connect(child, (struct sockaddr*)(&address), sizeof(address)) == -1) + { + ERROR( "Unable to connect to socket '%s': %s", address.sun_path, strerror(errno)); + lua_pushnumber(L, -1); + close(child); + return -1; + } + client->sock = child; + client->z_level = ANTD_CNONE; + lua_pushnumber(L, 0); + } + else + { + int ret, status; + struct pollfd pfds[2]; + pfds[0].fd = pfd; + pfds[0].events = POLLIN; + ret = poll(pfds, 1, -1); + if(ret < 0 || (pfds[0].revents & (POLLERR | POLLHUP))) + { + ERROR("Unable to wait for child process"); + lua_pushnumber(L, -1); + close(pfd); + return 1; + } + // now wait for child process + int cfd = accept(pfd, NULL, NULL); + if(cfd == -1) + { + ERROR("Unable to connect to child process"); + lua_pushnumber(L, -1); + close(pfd); + return 1; + } + LOG("Child process %d is accessible from %d", pid, cfd); + set_nonblock(cfd); + uint8_t buff[BUFFLEN]; + pfds[0].fd = sock; + pfds[0].events = POLLIN; + pfds[1].fd = cfd; + pfds[1].events = POLLIN; + memset(buff, 0, sizeof(buff)); + while((ret = poll(pfds, 2, 200)) != -1) + { + if(waitpid(pid, &status, WNOHANG) != 0) + { + break; + } + if(ret == 0) + { + continue; + } + if(pfds[0].revents & POLLIN) + { + ret = read(client->sock,buff, BUFFLEN); + if(ret <= 0) + { + LOG("antd_recv_upto() on %d: %s",sock, strerror(errno)); + break; + } + // write data to the other side + if(write(cfd,buff, ret) != ret) + { + ERROR("Error on send(): %s", strerror(errno)); + break; + } + } + else if (pfds[0].revents &(POLLERR | POLLHUP)) + { + break; + } + + if(pfds[1].revents & POLLIN) + { + ret = read(cfd, buff, sizeof(buff)); + if(ret <= 0) + { + ERROR("error read() on %d: %s",cfd, strerror(errno)); + break; + } + if(antd_send(client,buff, ret) != ret) + { + ERROR("Error atnd_send(): %s", strerror(errno)); + break; + } + } + else if (pfds[1].revents &(POLLERR | POLLHUP)) + { + break; + } + } + close(cfd); + } + close(pfd); + unlink(address.sun_path); + lua_pushnumber(L, pid); + return 1; +} + static int l_std_error(lua_State *L) { void *client = lua_touserdata(L, 1); @@ -804,6 +956,7 @@ static const struct luaL_Reg standard[] = { {"ws_b", l_ws_bin}, {"ws_close", l_ws_close}, {"is_dir", l_is_dir}, + {"pfork", l_pfork}, {NULL, NULL}}; int luaopen_std(lua_State *L) diff --git a/lib/asl/ulib.c b/lib/asl/ulib.c index de9eec0..800c994 100644 --- a/lib/asl/ulib.c +++ b/lib/asl/ulib.c @@ -37,7 +37,7 @@ static int l_check_login (lua_State *L) { if (pwd == NULL) { lua_pushboolean(L,0); - printf("Cannot find pwd record of %s\n", username ); + ERROR("Cannot find pwd record of %s", username ); return 1; } spwd = getspnam(username); @@ -63,25 +63,23 @@ static int l_check_login (lua_State *L) { if (encrypted == NULL) { lua_pushboolean(L,0); - printf("Cant crypt \n" ); + ERROR("Cant crypt %s", strerror(errno) ); return 1; } if(strcmp(encrypted, pwd->pw_passwd) == 0) { lua_pushboolean(L,1); - printf("%s\n","Successful login" ); return 1; } else { lua_pushboolean(L,0); - printf("Password incorrect \n" ); return 1; } #else // macos // just pass the check, for test only - lua_pushboolean(L,1); - printf("%s\n","Successful login" ); + lua_pushboolean(L,0); + ERROR("Login by shadow passd is not supported on this system"); return 1; #endif } @@ -117,6 +115,7 @@ static int l_fork(lua_State* L) lua_pushnumber(L, pid); return 1; } + static int l_waitpid(lua_State* L) { int pid = luaL_checknumber(L,1); @@ -138,7 +137,7 @@ static int l_kill(lua_State* L) { int pid = luaL_checknumber(L,1); if(pid == -1) pid = getpid(); - int status = kill(pid, SIGKILL); + int status = kill(pid, SIGHUP); lua_pushnumber(L, status); return 1; } @@ -149,7 +148,7 @@ static int l_setuid(lua_State* L) { if(setuid(uid) < 0) { - printf("UID set problem: %s\n", strerror(errno)); + ERROR("UID set problem: %s", strerror(errno)); lua_pushboolean(L,0); } else @@ -169,7 +168,7 @@ static int l_setgid(lua_State* L) { if(setgid(gid) < 0) { - printf("GID set problem: %s\n", strerror(errno)); + ERROR("GID set problem: %s", strerror(errno)); lua_pushboolean(L,0); } else @@ -214,12 +213,12 @@ static int l_getuid(lua_State* L) /* Retrieve group list */ groups = malloc(ngroups * sizeof (gid_t)); if (groups == NULL) { - LOG("malloc eror \n"); + LOG("malloc eror"); return 1; } if (getgrouplist(name, gid, groups, &ngroups) == -1) { free(groups); - LOG("getgrouplist() returned -1; ngroups = %d\n", ngroups); + LOG("getgrouplist() returned -1; ngroups = %d", ngroups); return 1; } /* retrieved groups, along with group names */ diff --git a/lua-api.c b/lua-api.c index b64ff62..878e5c3 100644 --- a/lua-api.c +++ b/lua-api.c @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -25,7 +25,6 @@ #define MAX_SOCK_NAME 64 #define SOCKET_NAME "lua.sock" -#define MAX_SESSION_TIMEOUT (15u * 60u) //15 min #define PING_INTERVAL 10u // 10s #define PROCESS_TIMEOUT 200u //100ms @@ -72,12 +71,14 @@ static int mk_socket() if (bind(fd, (struct sockaddr *)(&address), sizeof(address)) == -1) { ERROR("Unable to bind name: %s to a socket: %s", address.sun_path, strerror(errno)); + close(fd); return -1; } // mark the socket as passive mode if (listen(fd, 500) == -1) { ERROR("Unable to listen to socket: %d (%s): %s", fd, sock_path, strerror(errno)); + close(fd); return -1; } LOG("Socket %s is created successfully: %d", sock_path, fd); @@ -123,25 +124,25 @@ static void lua_serve() ERROR("Unable to set reuse address on %d - setsockopt: %s", socket, strerror(errno)); } LOG("LUA server online"); - /*set log level*/ - const char * enable_debug = getenv("ANTD_DEBUG"); - int log_level = LOG_ERR; - if(enable_debug) - { - if(atoi(enable_debug)) - { - LOG("LUA Debug is enabled"); - log_level = LOG_NOTICE; - } - } - setlogmask(LOG_UPTO(log_level)); + /*set log level*/ + const char * enable_debug = getenv("ANTD_DEBUG"); + int log_level = LOG_ERR; + if(enable_debug) + { + if(atoi(enable_debug)) + { + LOG("LUA Debug is enabled"); + log_level = LOG_NOTICE; + } + } + setlogmask(LOG_UPTO(log_level)); while((fd = accept(socket, NULL, NULL)) > 0) { pthread_t thread; lua_thread_data_t* data = (lua_thread_data_t*)malloc(sizeof(lua_thread_data_t)); data->__plugin__ = &__plugin__; data->fd = fd; - set_nonblock(fd); + //set_nonblock(fd); if (pthread_create(&thread, NULL, (void *(*)(void*))handle_fn, (void *)data) != 0) { ERROR("pthread_create: cannot create lua thread: %s", strerror(errno)); @@ -168,7 +169,7 @@ static void lua_serve() void init() { - (void)snprintf(sock_path, sizeof(sock_path), "%s/%s", __plugin__.tmpdir, SOCKET_NAME); + (void)snprintf(sock_path, sizeof(sock_path), "%s/%s", __plugin__.tmpdir, SOCKET_NAME); LOG("Lua socket will be stored in %s", sock_path); pid = fork(); if (pid == 0) @@ -203,26 +204,24 @@ static void push_dict_to_socket(antd_client_t* cl, char* name, char* parent_name static void *process(void *data) { - fd_set fd_in; antd_request_t *rq = (antd_request_t *)data; antd_client_t* cl = (antd_client_t* ) dvalue(rq->request, "LUA_CL_DATA"); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = PROCESS_TIMEOUT; - FD_ZERO(&fd_in); - FD_SET(rq->client->sock, &fd_in); - FD_SET(cl->sock, &fd_in); - int max_fdm = rq->client->sock > cl->sock ? rq->client->sock : cl->sock; - int rc = select(max_fdm + 1, &fd_in, NULL, NULL, &timeout); + struct pollfd pfds[2]; + pfds[0].fd = rq->client->sock; + pfds[0].events = POLLIN; + pfds[1].fd = cl->sock; + pfds[1].events = POLLIN; + + int rc = poll(pfds, 2, PROCESS_TIMEOUT); antd_task_t* task; uint8_t buff[BUFFLEN]; int ret; switch (rc) { case -1: - ERROR("Error on select(): %s", strerror(errno)); + ERROR("Error on poll(): %s", strerror(errno)); antd_close(cl); - dput(rq->request, "LUA_CL_DATA", NULL); + dput(rq->request, "LUA_CL_DATA", NULL); return antd_create_task(NULL, data, NULL, rq->client->last_io); case 0: // time out @@ -233,7 +232,7 @@ static void *process(void *data) // we have data default: // If data is on webserver - if (FD_ISSET(rq->client->sock, &fd_in)) + if (pfds[0].revents & POLLIN) { while((ret = antd_recv_upto(rq->client,buff, BUFFLEN)) > 0) { @@ -242,7 +241,7 @@ static void *process(void *data) { ERROR("Error on atnd_send(): %s", strerror(errno)); antd_close(cl); - dput(rq->request, "LUA_CL_DATA", NULL); + dput(rq->request, "LUA_CL_DATA", NULL); return antd_create_task(NULL, data, NULL, rq->client->last_io); } } @@ -250,11 +249,18 @@ static void *process(void *data) { LOG("antd_recv_upto() on %d: %s",rq->client->sock, strerror(errno)); antd_close(cl); - dput(rq->request, "LUA_CL_DATA", NULL); + dput(rq->request, "LUA_CL_DATA", NULL); return antd_create_task(NULL, data, NULL, rq->client->last_io); } } - else if(FD_ISSET(cl->sock, &fd_in)) + else if(pfds[0].revents &(POLLERR | POLLHUP)) + { + ERROR("POLLERR or POLLHUP received on %d", rq->client->sock); + antd_close(cl); + dput(rq->request, "LUA_CL_DATA", NULL); + return antd_create_task(NULL, data, NULL, rq->client->last_io); + } + if(pfds[1].revents & POLLIN) { while((ret = antd_recv_upto(cl,buff, BUFFLEN)) > 0) { @@ -263,7 +269,7 @@ static void *process(void *data) { ERROR("Error atnd_send(): %s", strerror(errno)); antd_close(cl); - dput(rq->request, "LUA_CL_DATA", NULL); + dput(rq->request, "LUA_CL_DATA", NULL); return antd_create_task(NULL, data, NULL, rq->client->last_io); } } @@ -271,10 +277,17 @@ static void *process(void *data) { LOG("antd_recv_upto() on %d: %s", cl->sock, strerror(errno)); antd_close(cl); - dput(rq->request, "LUA_CL_DATA", NULL); + dput(rq->request, "LUA_CL_DATA", NULL); return antd_create_task(NULL, data, NULL, rq->client->last_io); } } + else if(pfds[1].revents &(POLLERR | POLLHUP)) + { + ERROR("POLLERR or POLLHUP received on %d", cl->sock); + antd_close(cl); + dput(rq->request, "LUA_CL_DATA", NULL); + return antd_create_task(NULL, data, NULL, rq->client->last_io); + } task = antd_create_task(process, (void *)rq, NULL, time(NULL)); antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); antd_task_bind_event(task, cl->sock, 0, TASK_EVT_ON_READABLE); @@ -304,7 +317,7 @@ void* handle(void* data) cl->z_status = 0; cl->z_level = ANTD_CNONE; cl->zstream = NULL; - rq->client->z_level = ANTD_CNONE; + rq->client->z_level = ANTD_CNONE; push_dict_to_socket(cl, "request","HTTP_REQUEST", rq->request); antd_send(cl,"\r\n", 2); dput(rq->request, "LUA_CL_DATA", cl);