static void s_failConnection(iWritable* writable, string reason) { pack(writable, kFailedGreeting); s_flush(writable); throw eRuntimeError(reason); }
/*! * \brief Transmit a redirection page. */ int HttpSendRedirection(HTTPD_SESSION *hs, int code, ...) { va_list ap; int len; char *cp; char *loc; va_start(ap, code); for (len = 0; (cp = va_arg(ap, char *)) != NULL; len += strlen(cp)); va_end(ap); loc = malloc(len + 1); if (loc) { static const char body[] = "<html><body><a href=\"%s\">Continue</a></body></html>\r\n"; HTTP_STREAM *sp = hs->s_stream; HttpSendHeaderTop(hs, code); va_start(ap, code); for (*loc = '\0'; (cp = va_arg(ap, char *)) != NULL; strcat(loc, cp)); va_end(ap); #if HTTP_VERSION >= 0x10 s_vputs(sp, ct_Location, ": ", loc, "\r\n", NULL); HttpSendHeaderBottom(hs, "text", "html", sizeof(body) - 1 + strlen(loc) - 2); #endif s_printf(sp, body, loc); s_flush(sp); free(loc); } return 0; }
static int CgiClock(HTTPD_SESSION *hs) { time_t now; const struct tm *ltm; #if defined(NUT_OS) NutSleep(1000); #elif defined(_WIN32) Sleep(1000); #else #warning Unknown OS, sleep missing #endif HttpSendHeaderTop(hs, 200); s_puts("Cache-Control: no-cache, must-revalidate\r\n", hs->s_stream); s_puts("Content-Type: text/html; charset=iso-8859-1\r\n", hs->s_stream); s_puts("Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n", hs->s_stream); chprintf((BaseSequentialStream *)&itm_port, "%s\n", "****CgiClock****"); HttpSendHeaderBottom(hs, "text", "html", -1); time(&now); ltm = localtime(&now); s_printf(hs->s_stream, "{\"time\": \"%02d:%02d:%02d\"}\r\n", ltm->tm_hour, ltm->tm_min, ltm->tm_sec); s_flush(hs->s_stream); return 0; }
/*! * \brief Send device description. * * This uHTTP CGI function will be registered when UpnpRegisterDeviceTree() * is called for the first time. */ static int UpnpCgiDeviceDescription(HTTPD_SESSION *hs) { HTTP_STREAM *stream = hs->s_stream; SSDP_DEVICE *sdev = NULL; SSDP_SERVICE *ssvc; char *type; type = HttpArgParseFirst(&hs->s_req); if (type) { for (sdev = device_registration; sdev; sdev = sdev->sdev_next) { if (strcmp(sdev->sdev_type, type) == 0) { break; } } } if (sdev) { UPNP_DEVICE_INFO *udev = sdev->sdev_info; XmlHead(hs->s_stream); s_puts("<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\r\n", hs->s_stream); SpecVersion(stream); s_puts("<device>\r\n", stream); s_printf(stream, "<deviceType>urn:%s:device:%s:1</deviceType>\r\n", sdev->sdev_domain, sdev->sdev_type); WriteTag(stream, "friendlyName", udev->udev_name); WriteTag(stream, "manufacturer", udev->udev_mnf->umnf_name); WritePrepTag(stream, "manufacturerURL", udev->udev_mnf->umnf_url, "http://"); WriteTag(stream, "modelDescription", udev->udev_mdl->umdl_desc); WriteTag(stream, "modelName", udev->udev_mdl->umdl_name); WriteTag(stream, "modelNumber", udev->udev_mdl->umdl_num); WritePrepTag(stream, "modelURL", udev->udev_mdl->umdl_url, "http://"); WriteTag(stream, "UDN", sdev->sdev_uuid); if (sdev->sdev_svc) { s_puts("<serviceList>\r\n", stream); for (ssvc = sdev->sdev_svc; ssvc; ssvc = ssvc->ssvc_next) { UPNP_SERVICE_INFO *usvc = sdev->sdev_svc->ssvc_info; s_puts("<service>\r\n", stream); s_printf(stream, "<serviceType>urn:schemas-upnp-org:service:%s:1</serviceType>\r\n", sdev->sdev_svc->ssvc_type); s_printf(stream, "<serviceId>urn:upnp-org:serviceId:%s:1</serviceId>\r\n", sdev->sdev_svc->ssvc_type); s_printf(stream, "<SCPDURL>%s?%s=%s</SCPDURL>", usvc->usvc_url_scpd, sdev->sdev_type, ssvc->ssvc_type); s_printf(stream, "<controlURL>%s?%s=%s</controlURL>", usvc->usvc_url_ctrl, sdev->sdev_type, ssvc->ssvc_type); s_printf(stream, "<eventSubURL>%s?%s=%s</eventSubURL>", usvc->usvc_url_event, sdev->sdev_type, ssvc->ssvc_type); s_puts("</service>\r\n", stream); } s_puts("</serviceList>\r\n", stream); } WriteTag(stream, "presentationURL", udev->udev_presentation); s_puts("</device>\r\n", stream); s_puts("</root>\r\n", stream); } s_flush(stream); return 0; }
void HttpSendStreamError(HTTP_STREAM *stream, int status, const char *realm) { static const char body[] = "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD><BODY>%d %s</BODY></HTML>\r\n"; const char *text = HttpResponseText(status); HttpSendStreamHeaderTop(stream, status); #if HTTP_VERSION >= 0x10 if (realm) { static const char auth_fmt_P[] = "WWW-Authenticate: Basic realm=\"%s\"\r\n"; s_printf(stream, auth_fmt_P, realm); } HttpSendStreamHeaderBottom(stream, "text", "html", HTTP_CONN_CLOSE, sizeof(body) - 1 + 2 * (1 + strlen(text) - 2)); #endif s_printf(stream, body, status, text, status, text); s_flush(stream); }
/* * Send 'string' to the NNTP server, terminating it with CR and LF, as per * ARPA standard. * * Returns: Nothing. * * Side effects: Talks to the server. * Closes connection if things are not right. * * Note: This routine flushes the buffer each time it is called. For large * transmissions (i.e., posting news) don't use it. Instead, do the * fprintf's yourself, and then a final fflush. * Only cache commands, don't cache data transmissions. * */ void put_server( const char *string) { if (*string && strlen(string)) { DEBUG_IO((stderr, "put_server(%s)\n", string)); s_puts(string, nntp_wr_fp); s_puts("\r\n", nntp_wr_fp); # ifdef DEBUG debug_nntp(">>>", string); # endif /* DEBUG */ /* * remember the last command we wrote to be able to resend it after a * reconnect. reconnection is handled by get_server() */ strcpy(last_put, string); } (void) s_flush(nntp_wr_fp); }
static int SendResult(HTTPD_SESSION *hs, char *first, char *last) { static const char head[] = "<html>" "<head>" "<title>Form Result</title>" "</head>"; static const char body[] = "<body>" "<p>Hello %s %s!</p>" "<a href=\"/index.html\">back</a>" "</body>" "<html>"; HttpSendHeaderTop(hs, 200); HttpSendHeaderBottom(hs, "text", "html", -1); s_puts(head, hs->s_stream); s_printf(hs->s_stream, body, first, last); s_flush(hs->s_stream); return 0; }
/*! * \brief Send service description. * * This uHTTP CGI function will be registered when UpnpRegisterDeviceTree() * is called for the first time. */ static int UpnpCgiServiceDescription(HTTPD_SESSION *hs) { SSDP_SERVICE *ssvc = NULL; SSDP_DEVICE *sdev = NULL; HTTP_STREAM *stream = hs->s_stream; const char *dev_type; dev_type = HttpArgParseFirst(&hs->s_req); if (dev_type) { const char *svc_type = HttpArgValue(&hs->s_req); if (dev_type) { for (sdev = device_registration; sdev; sdev = sdev->sdev_next) { if (strcmp(sdev->sdev_type, dev_type) == 0) { for (ssvc = sdev->sdev_svc; ssvc; ssvc = ssvc->ssvc_next) { if (strcmp(ssvc->ssvc_type, svc_type) == 0) { break; } } break; } } } } if (ssvc) { SOAP_PROCEDURE *act; UPNP_VARIABLE *stv; UPNP_SERVICE_INFO *usvc = ssvc->ssvc_info; XmlHead(hs->s_stream); s_puts("<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">\r\n", stream); SpecVersion(stream); act = usvc->usvc_proc; if (act) { s_puts("<actionList>\r\n", stream); do { s_puts("<action>\r\n", stream); WriteTag(stream, "name", act->proc_name); if (act->proc_argi || act->proc_argo) { SOAP_ARG *arg; s_puts("<argumentList>\r\n", stream); for (arg = act->proc_argi; arg; arg = arg->arg_next) { s_puts("<argument>\r\n", stream); WriteTag(stream, "name", arg->arg_name); WriteTag(stream, "relatedStateVariable", ((UPNP_VARIABLE *) arg->arg_info)->ustv_name); WriteTag(stream, "direction", "in"); s_puts("</argument>\r\n", stream); } for (arg = act->proc_argo; arg; arg = (SOAP_ARG *) arg->arg_next) { s_puts("<argument>\r\n", stream); WriteTag(stream, "name", arg->arg_name); WriteTag(stream, "relatedStateVariable", ((UPNP_VARIABLE *) arg->arg_info)->ustv_name); WriteTag(stream, "direction", "out"); s_puts("</argument>\r\n", stream); } s_puts("</argumentList>\r\n", stream); } s_puts("</action>\r\n", stream); } while ((act = act->proc_next) != NULL); s_puts("</actionList>\r\n", stream); } stv = usvc->usvc_stv; if (stv) { s_puts("<serviceStateTable>\r\n", stream); do { s_printf(stream, "<stateVariable sendEvents=\"%s\">\r\n", stv->ustv_events ? "yes" : "no"); WriteTag(stream, "name", stv->ustv_name); WriteTag(stream, "dataType", UpnpVarTypeString(stv->ustv_type)); WriteTag(stream, "defaultValue", stv->ustv_default); s_puts("</stateVariable>\r\n", stream); } while((stv = stv->ustv_next) != NULL); s_puts("</serviceStateTable>\r\n", stream); } s_puts("</scpd>\r\n", stream); } s_flush(stream); return 0; }
void tSecureStream::m_setupClient(const tRSA& rsa, string appGreeting) { // This block is protected by constant timing in case // there is a man-in-the-middle who is causing the client // connection to fail over-and-over and analysing the time // it takes for the client to re-start the connection. // This block prevents info from being leaked about the // particular pre_secret that is being used by the current // connection attempt. vector<u8> rand_c, pre_secret, enc; { tConstTimeBlock ctb(&gClientInitTimingHistory); // Generate the client random vector. rand_c = s_genRand(kRandVectLen); // Generate the pre-secret random vector. pre_secret = s_genRand(kPreSecretLen); // Encrypt the pre-secret under the server's RSA public key. enc = rsa.encrypt(pre_secret); } // Send all this to the server. pack(m_internal_writable, kLibrhoGreeting); pack(m_internal_writable, appGreeting); pack(m_internal_writable, rand_c); pack(m_internal_writable, enc); s_flush(m_internal_writable); // Read the greeting from the server. // We don't care if timing info is leaked here // because 'kSuccessfulGreeting' is not a secret. string greetingResponse; try { unpack(m_internal_readable, greetingResponse, (u32)(std::max(kSuccessfulGreeting.length(), kFailedGreeting.length()))); } catch (ebObject& e) { throw eRuntimeError("The secure server didn't reply with its greeting."); } if (greetingResponse != kSuccessfulGreeting) throw eRuntimeError("The secure server sent a failure greeting."); // Read the random server bytes. // Again, we don't care about leaking timing info here. vector<u8> rand_s; try { unpack(m_internal_readable, rand_s, kRandVectLen); } catch (ebObject& e) { throw eRuntimeError("The secure server sent a random vector of the wrong length."); } if (rand_s.size() != kRandVectLen) throw eRuntimeError("The secure server sent a random vector of the wrong length."); // Another const timing block. vector<u8> secret, fPrime, g; { tConstTimeBlock ctb(&gClientProcessResponseTimingHistory); // Calculated the shared secret (from the pre-secret). secret = H1(pre_secret, rand_c, rand_s); // Calculate the correct response from the server. fPrime = H2(secret, rand_c, rand_s); // Calculate the proof-of-client. g = H3(secret, rand_c, rand_s); } // Read the proof-of-server hash. vector<u8> f; try { unpack(m_internal_readable, f, (u32)fPrime.size()); } catch (ebObject& e) { throw eRuntimeError("The secure server failed to verify itself."); } if (!s_constTimeIsEqual(f, fPrime)) throw eRuntimeError("The secure server failed to verify itself."); // Send the proof-of-client. (That is, prove we are not just replaying some other connection.) pack(m_internal_writable, g); s_flush(m_internal_writable); // Setup secure streams with the server. vector<u8> ksw = H4(pre_secret, secret, rand_c, rand_s); // <-- the Key for the Server Writer vector<u8> kcw = H5(pre_secret, secret, rand_c, rand_s); // <-- the Key for the Client Writer m_readable = new tReadableAES(m_internal_readable, kOpModeCBC, &ksw[0], s_toKeyLen(ksw.size())); m_writable = new tWritableAES(m_internal_writable, kOpModeCBC, &kcw[0], s_toKeyLen(kcw.size())); }
void tSecureStream::m_setupServer(const tRSA& rsa, string appGreeting) { // Read the greeting (part 1) from the client. // Note: The following DOES leak timing information, but we don't // care because 'kLibrhoGreeting' isn't a secret. string receivedLibrhoGreeting; try { unpack(m_internal_readable, receivedLibrhoGreeting, (u32)kLibrhoGreeting.size()); } catch (ebObject& e) { s_failConnection(m_internal_writable, "The secure client did not greet me properly."); } if (receivedLibrhoGreeting != kLibrhoGreeting) s_failConnection(m_internal_writable, "The secure client did not greet me properly."); // Read the greeting (part 2) from the client. // Note: The following DOES leak timing information, but we don't // care because 'appGreeting' isn't a secret. string receivedAppGreeting; try { unpack(m_internal_readable, receivedAppGreeting, (u32)appGreeting.size()); } catch (ebObject& e) { s_failConnection(m_internal_writable, "The secure client requested a different application."); } if (receivedAppGreeting != appGreeting) s_failConnection(m_internal_writable, "The secure client requested a different application."); // Read the client's random bytes. // Again, we don't care about the leaked info here because the correct // random vector length is not a secret. vector<u8> rand_c; try { unpack(m_internal_readable, rand_c, kRandVectLen); } catch (ebObject& e) { s_failConnection(m_internal_writable, "The secure client sent a random byte vector of the wrong length."); } if (rand_c.size() != kRandVectLen) s_failConnection(m_internal_writable, "The secure client sent a random byte vector of the wrong length."); // Read the encrypted pre-secret from the client. // (No info is leaked by this section.) vector<u8> enc; try { unpack(m_internal_readable, enc, rsa.maxMessageLength()+5); } catch (ebObject& e) { s_failConnection(m_internal_writable, "The secure client failed to send an encrypted pre-secret."); } // Now that the server has read everything from the client, it // will do some calculations. // We will protect this section with a const time block to // protect against timing side-channel attacks. vector<u8> pre_secret, rand_s, secret, f, gPrime; { // This object is constructed in this code block, and it // will be destructed when this block ends. The d'tor of // this class calls sleep() in order to enforce consistent // timing of the execution of this block. tConstTimeBlock ctb(&gServerProcessGreetingTimingHistory); // Decrypt the pre-secret and make sure it looks okay. pre_secret = rsa.decrypt(enc); if (pre_secret.size() != kPreSecretLen) s_failConnection(m_internal_writable, "The secure client gave a pre-secret that is the wrong length."); // Generate the server random byte vector. rand_s = s_genRand(kRandVectLen); // Calculated the shared secret (from the pre-secret). secret = H1(pre_secret, rand_c, rand_s); // Calculate the proof-of-server hash. (The convinces the client that we are the actual server.) f = H2(secret, rand_c, rand_s); // Calculate what the client correct response would be. gPrime = H3(secret, rand_c, rand_s); } // Write back to the client all this stuff. pack(m_internal_writable, kSuccessfulGreeting); pack(m_internal_writable, rand_s); pack(m_internal_writable, f); s_flush(m_internal_writable); // Have the client prove that it is a real client, not a reply attack. vector<u8> g; try { unpack(m_internal_readable, g, (u32)gPrime.size()); } catch (ebObject& e) { throw eRuntimeError("The secure client failed to show proof that it is real."); } if (!s_constTimeIsEqual(g, gPrime)) throw eRuntimeError("The secure client failed to show proof that it is real."); // Setup secure streams with the client. vector<u8> ksw = H4(pre_secret, secret, rand_c, rand_s); // <-- the Key for the Server Writer vector<u8> kcw = H5(pre_secret, secret, rand_c, rand_s); // <-- the Key for the Client Writer m_readable = new tReadableAES(m_internal_readable, kOpModeCBC, &kcw[0], s_toKeyLen(kcw.size())); m_writable = new tWritableAES(m_internal_writable, kOpModeCBC, &ksw[0], s_toKeyLen(ksw.size())); }