/***************************************************************************** * * $Id: door.c,v 1.26 2007/02/25 20:28:09 mbse Exp $ * Purpose ...............: Run external door * ***************************************************************************** * Copyright (C) 1997-2007 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 * 1971 BV IJmuiden * the Netherlands * * This file is part of MBSE BBS. * * This BBS 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, or (at your option) any * later version. * * MBSE BBS 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 MBSE BBS; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ #include "../config.h" #include "../lib/mbselib.h" #include "../lib/mbse.h" #include "../lib/users.h" #include "language.h" #include "input.h" #include "timeout.h" #include "exitinfo.h" #include "whoson.h" #include "door.h" #include "term.h" #include "ttyio.h" #include "openport.h" extern time_t t_start; extern int e_pid; extern char **environ; extern int cols; extern int rows; char *Gdate(time_t, int); char *Gdate(time_t tt, int Y2K) { static char GLC[15]; struct tm *tm; tm = localtime(&tt); if (Y2K) snprintf(GLC, 15, "%02d-%02d-%04d", tm->tm_mon +1, tm->tm_mday, tm->tm_year + 1900); else snprintf(GLC, 15, "%02d-%02d-%02d", tm->tm_mon +1, tm->tm_mday, tm->tm_year % 100); return (GLC); } char *Rdate(char *, int); char *Rdate(char *ind, int Y2K) { static char GLC[15]; memset(&GLC, 0, sizeof(GLC)); GLC[0] = ind[3]; GLC[1] = ind[4]; GLC[2] = '-'; GLC[3] = ind[0]; GLC[4] = ind[1]; GLC[5] = '-'; if (Y2K) { GLC[6] = ind[6]; GLC[7] = ind[7]; GLC[8] = ind[8]; GLC[9] = ind[9]; } else { GLC[6] = ind[8]; GLC[7] = ind[9]; } return GLC; } /* * Function will run a external program or door */ void ExtDoor(char *Program, int NoDoorsys, int Y2Kdoorsys, int Comport, int NoSuid, int NoPrompt, int SingleUser, char *What) { char *String, *String1; int i, rc, Start; char *temp1, buf[128]; FILE *fp; temp1 = calloc(PATH_MAX, sizeof(char)); String = calloc(81, sizeof(char)); Start = TRUE; if (SingleUser && What) { /* * Check if the door is in use */ while (TRUE) { if (Start) snprintf(buf, 128, "GMON:1,1;"); else snprintf(buf, 128, "GMON:1,0;"); Start = FALSE; if (socket_send(buf) == 0) { strcpy(buf, socket_receive()); if (strncmp(buf, "100:0;", 6) == 0) break; /* No more data */ if (strstr(buf, "mbsebbs")) { strtok(buf, ","); /* Nr of parameters */ strtok(NULL, ","); /* Pid */ strtok(NULL, ","); /* tty */ strtok(NULL, ","); /* username */ strtok(NULL, ","); /* program name */ strtok(NULL, ","); /* location */ if (strcmp(strtok(NULL, ","), menus.DoorName) == 0) { Syslog('+', "User tried single user door %s, but door is in use", menus.DoorName); Enter(1); /* The door is in use by another user, try again later */ pout(LIGHTRED, BLACK, (char *) Language(20)); Enter(2); Pause(); free(temp1); free(String); return; } } } } } WhosDoingWhat(DOOR, What); if ((strstr(Program, "/N")) != NULL) { snprintf(temp1, 81, "%d", iNode); strreplace(Program, (char *)"/N", temp1); } if ((strstr(Program, "/U")) != NULL) { snprintf(temp1, PATH_MAX, "%s/%s", CFG.bbs_usersdir, exitinfo.Name); strreplace(Program, (char *)"/U", temp1); } if ((strstr(Program, "/A")) != NULL) { Enter(1); colour(CYAN, BLACK); if ((String = strstr(Program, "/T=")) != NULL) { String1 = String + 3; PUTSTR(String1); } else PUTSTR((char *)"Please enter filename: "); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(temp1, 80); strreplace(Program, (char *)"/A", temp1); for (i = 0; i < strlen(Program); i++) { if (*(Program + i) == '\0') break; if (*(Program + i) == '/') *(Program + i) = '\0'; } } free(String); Syslog('+', "Door: %s", Program); ReadExitinfo(); alarm_set((exitinfo.iTimeLeft * 60) - 10); Altime((exitinfo.iTimeLeft * 60)); /* * Always remove the old door.sys first. */ snprintf(temp1, PATH_MAX, "%s/%s/door.sys", CFG.bbs_usersdir, exitinfo.Name); unlink(temp1); /* * Write door.sys in users homedirectory */ if (!NoDoorsys) { if ((fp = fopen(temp1, "w+")) == NULL) { WriteError("$Can't create %s", temp1); } else { if (Comport) { fprintf(fp, "COM1:\r\n"); /* COM port */ fprintf(fp, "19200\r\n");/* Effective baudrate */ } else { fprintf(fp, "COM0:\r\n");/* COM port */ fprintf(fp, "0\r\n"); /* Effective baudrate */ } fprintf(fp, "8\r\n"); /* Databits */ fprintf(fp, "%d\r\n", iNode); /* Node number */ if (Comport) fprintf(fp, "19200\r\n");/* Locked baudrate */ else fprintf(fp, "%d\r\n", ttyinfo.portspeed); /* Locked baudrate */ fprintf(fp, "Y\r\n"); /* Screen snoop */ fprintf(fp, "N\r\n"); /* Printer on */ fprintf(fp, "Y\r\n"); /* Page bell */ fprintf(fp, "Y\r\n"); /* Caller alarm */ fprintf(fp, "%s\r\n", exitinfo.sUserName); fprintf(fp, "%s\r\n", exitinfo.sLocation); fprintf(fp, "%s\r\n", exitinfo.sVoicePhone); fprintf(fp, "%s\r\n", exitinfo.sDataPhone); fprintf(fp, "%s\r\n", exitinfo.Password); fprintf(fp, "%d\r\n", exitinfo.Security.level); fprintf(fp, "%d\r\n", exitinfo.iTotalCalls); fprintf(fp, "%s\r\n", Gdate(exitinfo.tLastLoginDate, Y2Kdoorsys)); fprintf(fp, "%d\r\n", exitinfo.iTimeLeft * 60); /* Seconds */ fprintf(fp, "%d\r\n", exitinfo.iTimeLeft); /* Minutes */ fprintf(fp, "GR\r\n"); /* Graphics GR,RIP,NG */ fprintf(fp, "%d\r\n", rows); fprintf(fp, "N\r\n"); /* User mode, always N */ fprintf(fp, "\r\n"); /* Always blank */ fprintf(fp, "\r\n"); /* Always blank */ fprintf(fp, "%s\r\n", Rdate(exitinfo.sExpiryDate, Y2Kdoorsys)); fprintf(fp, "%d\r\n", grecno); /* Users recordnumber */ fprintf(fp, "%s\r\n", exitinfo.sProtocol); fprintf(fp, "%d\r\n", exitinfo.Uploads); fprintf(fp, "%d\r\n", exitinfo.Downloads); fprintf(fp, "%d\r\n", LIMIT.DownK); /* FIXME: Download Kb today */ fprintf(fp, "%d\r\n", LIMIT.DownK); fprintf(fp, "%s\r\n", Rdate(exitinfo.sDateOfBirth, Y2Kdoorsys)); fprintf(fp, "\r\n"); /* Path to userbase */ fprintf(fp, "\r\n"); /* Path to messagebase */ fprintf(fp, "%s\r\n", CFG.sysop_name); fprintf(fp, "%s\r\n", exitinfo.sHandle); fprintf(fp, "none\r\n"); /* Next event time */ fprintf(fp, "Y\r\n"); /* Error free connect. */ fprintf(fp, "N\r\n"); /* Always N */ fprintf(fp, "Y\r\n"); /* Always Y */ fprintf(fp, "7\r\n"); /* Default textcolor */ fprintf(fp, "0\r\n"); /* Always 0 */ fprintf(fp, "%s\r\n", Gdate(exitinfo.tLastLoginDate, Y2Kdoorsys)); /* Last newfiles scan date */ fprintf(fp, "%s\r\n", StrTimeHM(t_start)); /* Time of this call */ fprintf(fp, "%s\r\n", LastLoginTime); /* Time of last call */ fprintf(fp, "32768\r\n"); /* Always 32768 */ fprintf(fp, "%d\r\n", exitinfo.DownloadsToday); fprintf(fp, "%d\r\n", exitinfo.UploadK); fprintf(fp, "%d\r\n", exitinfo.DownloadK); fprintf(fp, "%s\r\n", exitinfo.sComment); fprintf(fp, "0\r\n"); /* Always 0 */ fprintf(fp, "%d\r\n\032", exitinfo.iPosted); fclose(fp); } } /* * Always remove the old door32.sys first. */ snprintf(temp1, PATH_MAX, "%s/%s/door32.sys", CFG.bbs_usersdir, exitinfo.Name); unlink(temp1); /* * Write door32.sys in users homedirectory */ if (!NoDoorsys) { if ((fp = fopen(temp1, "w+")) == NULL) { WriteError("$Can't create %s", temp1); } else { if (Comport) { fprintf(fp, "1\r\n"); /* COM type, 1=serial, 2=telnet */ fprintf(fp, "1\r\n"); /* COM port number */ fprintf(fp, "19200\r\n"); /* Effective baudrate */ } else { fprintf(fp, "0\r\n"); /* COM type, 0=local */ fprintf(fp, "0\r\n"); /* COM port */ fprintf(fp, "0\r\n"); /* Effective baudrate */ } fprintf(fp, "%s\r\n", CFG.bbs_name); /* BBS name */ fprintf(fp, "%d\r\n", grecno); /* User record */ fprintf(fp, "%s\r\n", exitinfo.sUserName); /* User's real name */ fprintf(fp, "%s\r\n", exitinfo.sHandle); /* User's handle */ fprintf(fp, "%d\r\n", exitinfo.Security.level); /* User's security level */ fprintf(fp, "%d\r\n", exitinfo.iTimeLeft); /* User's time left in minutes */ fprintf(fp, "1\r\n"); /* User's graphic mode */ fprintf(fp, "%d\r\n\032", iNode); /* Node number */ fclose(fp); } } clear(); PUTSTR((char *)"Loading, please wait ..."); Enter(2); /* * Put terminal back in cooked mode, prefered by some doors. */ cookedport(); if (NoSuid) rc = exec_nosuid(Program); else rc = execute_str((char *)"/bin/sh", (char *)"-c", Program, NULL, NULL, NULL); /* * First set cookedport again, this will load our original saved * termios values. This way it doesn't matter what the door might * have done with the original termios. */ cookedport(); rawport(); Altime(0); alarm_off(); alarm_on(); Syslog('+', "Door end, rc=%d", rc); free(temp1); Enter(2); if (!NoPrompt) Pause(); } /* * Execute a door as real user, not suid. */ int exec_nosuid(char *mandato) { int rc, status; pid_t pid; char *argv[4]; if (mandato == NULL) return 1; /* Prevent running a shell */ Syslog('+', "Execve: /bin/sh -c %s", mandato); pid = fork(); if (pid == -1) return 1; if (pid == 0) { msleep(150); argv[0] = (char *)"sh"; argv[1] = (char *)"-c"; argv[2] = mandato; argv[3] = 0; execve("/bin/sh", argv, environ); exit(MBERR_EXEC_FAILED); } e_pid = pid; do { rc = waitpid(pid, &status, 0); e_pid = 0; } while (((rc > 0) && (rc != pid)) || ((rc == -1) && (errno == EINTR))); switch(rc) { case -1: WriteError("$Waitpid returned %d, status %d,%d", rc,status>>8,status&0xff); return -1; case 0: return 0; default: if (WIFEXITED(status)) { rc = WEXITSTATUS(status); if (rc) { WriteError("Exec_nosuid: returned error %d", rc); return rc; } } if (WIFSIGNALED(status)) { rc = WTERMSIG(status); WriteError("Wait stopped on signal %d", rc); return rc; } if (rc) WriteError("Wait stopped unknown, rc=%d", rc); return rc; } return 0; }