Пример #1
0
static
void s_failConnection(iWritable* writable, string reason)
{
    pack(writable, kFailedGreeting);
    s_flush(writable);
    throw eRuntimeError(reason);
}
Пример #2
0
/*!
 * \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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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);
}
Пример #6
0
/*
 * 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);
}
Пример #7
0
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;
}
Пример #8
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;
}
Пример #9
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()));
}
Пример #10
0
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()));
}