#include #include #include #include #include #include #include // auto zombie reaping #include #include #include void doprocessing(int sock); char *cmds[10]; void set_raw(int fd) { struct termios tio_raw; tcgetattr(fd, &tio_raw); cfmakeraw(&tio_raw); tcsetattr(fd, TCSANOW, &tio_raw); } int drain(int fd) { struct timeval tv; fd_set set; int ret; char buffer[21]; int total = 0; printf("draining... \n"); do { FD_ZERO(&set); FD_SET(fd, &set); tv.tv_sec = 0; // 50,000 works for syncterm tv.tv_usec = 50000; ret = select(fd + 1, &set, NULL, NULL, &tv); if (ret == 1) { total += read(fd, buffer, 20); } } while (ret != 0); printf(" [%d]\n", total); return total; } int main(int argc, char *argv[]) { int sockfd, newsockfd, portno, clilen; char buffer[256]; struct sockaddr_in serv_addr, cli_addr; int n, pid; // Automatically reap zombies. if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { perror(0); exit(1); } /* First call to socket() function */ sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("ERROR opening socket"); exit(1); } if (argc != 3) { printf("I need a listening port number, and command/door to call.\n"); exit(2); } int listen_port = atoi(argv[1]); char *command = strdup(argv[2]); printf("Port %d Cmd [%s]\n", listen_port, command); char *cp; int cmd_count = 0; cp = command; cmds[cmd_count] = cp; cmd_count++; while (*cp != 0) { if (*cp == ' ') { *cp = 0; cp++; cmds[cmd_count] = cp; cmd_count++; continue; } cp++; } cmds[cmd_count] = (char *)NULL; if (listen_port == 0) { printf("I need a listening port number as a parameter.\n"); exit(2); } /* Initialize socket structure */ bzero((char *)&serv_addr, sizeof(serv_addr)); portno = listen_port; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); int flag = 1; if (-1 == setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag))) { perror("setsockopt fail"); } /* Now bind the host address using bind() call.*/ if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("ERROR on binding"); exit(1); } /* Now start listening for the clients, here * process will go in sleep mode and will wait * for the incoming connection */ printf("Listening for connections on %d\n", listen_port); listen(sockfd, 5); clilen = sizeof(cli_addr); while (1) { newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); if (newsockfd < 0) { perror("ERROR on accept"); exit(1); } set_raw(newsockfd); /* Create child process */ pid = fork(); if (pid < 0) { perror("ERROR on fork"); exit(1); } if (pid == 0) { /* This is the client process */ close(sockfd); doprocessing(newsockfd); exit(0); } else { close(newsockfd); } } /* end of while */ free((void *)command); } #define CRNL "\r\n" void doprocessing(int sock) { int n; char buffer[256]; // raw mode // set_raw(sock); /* std::string ayt = std::string((const char *)"\x00\xff\xfd\xf6", 4); std::string ayt_resp = std::string((const char *)"\xff\xfb\x00", 3); std::string ayt2 = std::string((const char *)"\xff\xfb\x00", 3); std::string ayt2_resp = std::string((const char *)"\xff\xfd\x00", 3); */ // write(sock, "\x00\xff\xfd\xf6", 4); // write(sock, "\xff\xfb\x00", 3); /* https://www.rfc-editor.org/rfc/rfc658.html https://www.rfc-editor.org/rfc/rfc652.html https://www.iana.org/assignments/telnet-options/telnet-options.xhtml https://stackoverflow.com/questions/273261/force-telnet-client-into-character-mode https://www.omnisecu.com/tcpip/telnet-modes-of-operation.php https://www.omnisecu.com/tcpip/iac-interpret-as-command-telnet.php https://www.omnisecu.com/tcpip/telnet-negotiation.php https://stackoverflow.com/questions/10413963/telnet-iac-command-answering http://ryobbs.com/doku.php/terminal_iac https://www.omnisecu.com/tcpip/telnet-commands-and-options.php */ write(sock, "\xff\xfb\x01", 3); // drain(sock); write(sock, "\xff\xfb\x03", 3); // drain(sock); write(sock, "\xff\xfd\x10", 3); // write(sock, "\xff\xfc\x22", 3); // syncterm is slow. It needs time to drain. :() drain(sock); // drain(sock); /* struct termios tio_raw; tcgetattr(sock, &tio_raw); cfmakeraw(&tio_raw); tcsetattr(sock, TCSANOW, &tio_raw); */ // telnet client into character mode // sprintf(buffer, "\377\375\042\377\373\001Welcome socket %d\n\r", sock); sprintf(buffer, "Welcome socket %d" CRNL, sock); write(sock, buffer, strlen(buffer)); // can I read the buffer until empty, maybe? FILE *fp; fp = fopen("door32.sys", "w"); if (fp == NULL) { return; } fprintf(fp, "%d\n", 2); fprintf(fp, "%d\n", sock); fprintf(fp, "38400\n"); fprintf(fp, "Fake Door32 BBS\n"); fprintf(fp, "1\n"); fprintf(fp, "%s\n%s\n", "Bugz Laundry", "Bugz"); fprintf(fp, "%d\n", 100); fprintf(fp, "%d\n", 120); fprintf(fp, "1\n1\n"); fclose(fp); // This resets the termios ?? // execl("./testdoor", "testdoor", "-d", "door32.sys", (const char *)NULL); execv(cmds[0], cmds); // step1: write out door32.sys file // exec / replace this with our door /* bzero(buffer,256); n = read(sock,buffer,255); if (n < 0) { perror("ERROR reading from socket"); exit(1); } printf("Here is the message: %s\n",buffer); n = write(sock,"I got your message",18); if (n < 0) { perror("ERROR writing to socket"); exit(1); } */ }