/* * active port forwarder - software for secure forwarding * Copyright (C) 2003-2007 jeremian * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include "client_remoteadmin.h" /* * Function name: client_admin * Description: This function is responsible for client part of the admin panel. * Arguments: type - the type of the realm * master - pointer to the SslFd structure representing the connection with afserver * buff - buffer which will be used for communication * connectfd - the optional descriptor which can be used instead of the stdin * id - the realm's id * Returns: 0 - connection was closed normally, * 1 - something went bad. */ int client_admin(char type, SslFd* master, unsigned char* buff, int connectfd, char* id) { fd_set rset, allset; int maxfdp1, n, length, infd; FILE *outfp, *infp; buff[0] = AF_S_ADMIN_LOGIN; SslFd_send_message(type, master, buff, 5); buff[0] = 0; SslFd_get_message(type, master, buff, -5); if ( buff[0] == 0 ) { aflog(LOG_T_INIT, LOG_I_CRIT, "Wrong password"); return 1; } if ( buff[0] == AF_S_CANT_OPEN ) { aflog(LOG_T_INIT, LOG_I_CRIT, "Server is full"); return 1; } if ( buff[0] != AF_S_ADMIN_LOGIN ) { aflog(LOG_T_INIT, LOG_I_CRIT, "Incompatible server type or server full"); return 1; } aflog(LOG_T_MAIN, LOG_I_INFO, "CLIENT STARTED mode: remote administration"); if (connectfd > 0) { outfp = fdopen(connectfd, "w"); if (outfp == NULL) { aflog(LOG_T_INIT, LOG_I_CRIT, "Error in opening file descriptor for writing"); return 1; } infd = connectfd; } else { infd = STDIN_FILENO; outfp = stdout; } infp = fdopen(infd, "r"); if (infp == NULL) { aflog(LOG_T_INIT, LOG_I_CRIT, "Error in opening file descriptor for reading"); return 1; } length = buff[3]; length = length << 8; length += buff[4]; /* this is length of message */ n = SslFd_get_message(type, master, buff, length); buff[n] = 0; fprintf(outfp, "%s\n", (char*) buff); fflush(outfp); FD_ZERO(&allset); FD_SET(SslFd_get_fd(master), &allset); FD_SET(infd, &allset); maxfdp1 = (infd > SslFd_get_fd(master)) ? infd + 1 : SslFd_get_fd(master) + 1; if (id != NULL) { buff[0] = AF_S_LOGIN; buff[1] = buff[2] = 0; n = strlen(id); memcpy(&buff[5], id, n); buff[3] = n >> 8; /* high bits of message length */ buff[4] = n; /* low bits of message length */ SslFd_send_message(type, master, buff, n+5); aflog(LOG_T_MANAGE, LOG_I_INFO, "ID SENT: %s", id); } while (1) { rset = allset; select(maxfdp1, &rset, NULL, NULL, NULL); if (FD_ISSET(SslFd_get_fd(master), &rset)) { aflog(LOG_T_MANAGE, LOG_I_DEBUG, "masterfd: FD_ISSET"); n = SslFd_get_message(type, master, buff, 5); if (n != 5) { aflog(LOG_T_MANAGE, LOG_I_ERR, "FATAL ERROR! (%d)", n); if (n == -1) { if (TYPE_IS_SSL(type)) { get_ssl_error(master, "FE", n); continue; /* what happened? */ } } if (n != 0) return 1; } if (n == 0) { /* server quits -> we do the same... */ aflog(LOG_T_MANAGE, LOG_I_CRIT, "SERVER: premature quit --> exiting..."); return 1; } if (buff[0] == AF_S_CLOSING) { aflog(LOG_T_MANAGE, LOG_I_CRIT, "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); return 0; } if (buff[0] != AF_S_ADMIN_CMD) { aflog(LOG_T_MANAGE, LOG_I_CRIT, "SERVER: wrong message --> exiting"); return 1; } length = buff[3]; length = length << 8; length += buff[4]; /* this is length of message */ switch (buff[1]) { case AF_RA_STATUS_OK: { aflog(LOG_T_MANAGE, LOG_I_INFO, "SERVER: cmd successful"); } case AF_RA_FAILED: { if (buff[1] == AF_RA_FAILED) { aflog(LOG_T_MANAGE, LOG_I_INFO, "SERVER: cmd failed"); } } case AF_RA_UNDEFINED: { if (buff[1] == AF_RA_UNDEFINED) { aflog(LOG_T_MANAGE, LOG_I_WARNING, "SERVER: unknown cmd"); } n = SslFd_get_message(type, master, buff, length); buff[n] = 0; fprintf(outfp, "%s", (char*) buff); fflush(outfp); break; } case AF_RA_KICKED: { aflog(LOG_T_MANAGE, LOG_I_ERR, "SERVER: kicked us -> exiting... cg: %ld bytes", getcg()); return 1; break; } default: { aflog(LOG_T_MANAGE, LOG_I_ERR, "SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); return 1; } } } if (FD_ISSET(infd, &rset)) { aflog(LOG_T_MANAGE, LOG_I_DEBUG, "infd: FD_ISSET"); if (fgets((char*) &buff[5], 8091, infp) == NULL) { /* client quits --> exiting */ aflog(LOG_T_MANAGE, LOG_I_NOTICE, "CLIENT CLOSED cg: %ld bytes", getcg()); return 0; } n = strlen((char*) &buff[5]); if ((n > 0) && (buff[n+4] == '\n')) { --n; } buff[0] = AF_S_ADMIN_CMD; buff[1] = AF_RA_CMD; buff[2] = AF_RA_UNDEFINED; buff[3] = n >> 8; /* high bits of message length */ buff[4] = n; /* low bits of message length */ SslFd_send_message(type, master, buff, n+5); } } }