Example #1
0
static PRFileDesc *PushNewLayers(PRFileDesc *stack)
{
	PRDescIdentity tmp_identity;
    PRFileDesc *layer;
    PRStatus rv;

	/* push a dummy layer */
    tmp_identity = PR_GetUniqueIdentity("Dummy 1");
    layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods());
    rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
    if (verbosity > quiet)
        PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
															stack);
    PR_ASSERT(PR_SUCCESS == rv);

	/* push a data procesing layer */
    layer = PR_CreateIOLayerStub(identity, &myMethods);
    rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
    if (verbosity > quiet)
        PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
													stack);
    PR_ASSERT(PR_SUCCESS == rv);

	/* push another dummy layer */
    tmp_identity = PR_GetUniqueIdentity("Dummy 2");
    layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods());
    rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
    if (verbosity > quiet)
        PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
															stack);
    PR_ASSERT(PR_SUCCESS == rv);
    return stack;
}  /* PushLayer */
Example #2
0
static bool _check_init(){
    if(PR_INVALID_IO_LAYER == _udpt_desc_identity) {
    	udt_startup();
        _udpt_desc_identity = PR_GetUniqueIdentity("udptransport");
    }
    return true;
}
static void
Initialize()
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  static bool initialized = false;
  if (initialized) {
    return;
  }

  nsNamedPipeLayerIdentity = PR_GetUniqueIdentity("Named Pipe layer");
  nsNamedPipeLayerMethods = *PR_GetDefaultIOMethods();
  nsNamedPipeLayerMethods.close = nsNamedPipeClose;
  nsNamedPipeLayerMethods.read = nsNamedPipeRead;
  nsNamedPipeLayerMethods.write = nsNamedPipeWrite;
  nsNamedPipeLayerMethods.available = nsNamedPipeAvailable;
  nsNamedPipeLayerMethods.available64 = nsNamedPipeAvailable64;
  nsNamedPipeLayerMethods.fsync = nsNamedPipeSync;
  nsNamedPipeLayerMethods.connect = nsNamedPipeConnect;
  nsNamedPipeLayerMethods.recv = nsNamedPipeRecv;
  nsNamedPipeLayerMethods.send = nsNamedPipeSend;
  nsNamedPipeLayerMethods.poll = nsNamedPipePoll;
  nsNamedPipeLayerMethods.getsocketoption = nsNamedPipeGetSocketOption;
  nsNamedPipeLayerMethods.setsocketoption = nsNamedPipeSetSocketOption;
  nsNamedPipeLayerMethods.connectcontinue = nsNamedPipeConnectContinue;

  initialized = true;
}
Example #4
0
static void
ssl_nss_init_nss(void)
{
#if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 )
	SSLVersionRange supported, enabled;
#endif /* NSS >= 3.14 */

	PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
	NSS_NoDB_Init(".");
	NSS_SetDomesticPolicy();

	SSL_CipherPrefSetDefault(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(TLS_DHE_DSS_WITH_AES_256_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(TLS_RSA_WITH_AES_256_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(TLS_DHE_DSS_WITH_RC4_128_SHA, 1);
	SSL_CipherPrefSetDefault(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(TLS_DHE_DSS_WITH_AES_128_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(SSL_RSA_WITH_RC4_128_SHA, 1);
	SSL_CipherPrefSetDefault(TLS_RSA_WITH_AES_128_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(SSL_DHE_RSA_WITH_DES_CBC_SHA, 1);
	SSL_CipherPrefSetDefault(SSL_DHE_DSS_WITH_DES_CBC_SHA, 1);

#if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 )
	/* Get the ranges of supported and enabled SSL versions */
	if ((SSL_VersionRangeGetSupported(ssl_variant_stream, &supported) == SECSuccess) &&
			(SSL_VersionRangeGetDefault(ssl_variant_stream, &enabled) == SECSuccess)) {
		purple_debug_info("nss", "TLS supported versions: "
				"0x%04hx through 0x%04hx\n", supported.min, supported.max);
		purple_debug_info("nss", "TLS versions allowed by default: "
				"0x%04hx through 0x%04hx\n", enabled.min, enabled.max);

		/* Make sure SSL 3.0 is disabled (it's old and everyone should be
		   using at least TLS 1.0 by now), and make sure all versions of TLS
		   supported by the local library are enabled (for some reason NSS
		   doesn't enable newer versions of TLS by default -- more context in
		   ticket #15909). */
		if (enabled.min != SSL_LIBRARY_VERSION_TLS_1_0 || supported.max > enabled.max) {
			enabled.max = supported.max;
			if (SSL_VersionRangeSetDefault(ssl_variant_stream, &enabled) == SECSuccess) {
				purple_debug_info("nss", "Changed allowed TLS versions to "
						"0x%04hx through 0x%04hx\n", enabled.min, enabled.max);
			} else {
				purple_debug_error("nss", "Error setting allowed TLS versions to "
						"0x%04hx through 0x%04hx\n", enabled.min, enabled.max);
			}
		}
	}
#endif /* NSS >= 3.14 */

	/** Disable OCSP Checking until we can make that use our HTTP & Proxy stuff */
	CERT_EnableOCSPChecking(PR_FALSE);

	_identity = PR_GetUniqueIdentity("Purple");
	_nss_methods = PR_GetDefaultIOMethods();
}
Example #5
0
static void LazyInitSocket()
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
  if (sPollableEventLayerMethodsPtr) {
    return;
  }
  sPollableEventLayerIdentity = PR_GetUniqueIdentity("PollableEvent Layer");
  sPollableEventLayerMethods = *PR_GetDefaultIOMethods();
  sPollableEventLayerMethodsPtr = &sPollableEventLayerMethods;
}
Example #6
0
void * tls_init(const struct tls_config *conf) {
    char *dir;

    tls_nss_ref_count++;
    if (tls_nss_ref_count > 1)
        return (void *) 1;

    PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);

    nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant");

    PK11_SetPasswordFunc(nss_password_cb);

    dir = getenv("SSL_DIR");
    if (dir) {
        if (NSS_Init(dir) != SECSuccess) {
            wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) "
                    "failed", dir);
            return NULL;
        }
    } else {
        if (NSS_NoDB_Init(NULL) != SECSuccess) {
            wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) "
                    "failed");
            return NULL;
        }
    }

    if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) !=
            SECSuccess ||
            SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess ||
            SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess ||
            SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) {
        wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed");
        return NULL;
    }

    if (NSS_SetDomesticPolicy() != SECSuccess) {
        wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed");
        return NULL;
    }

    return (void *) 1;
}
Example #7
0
// static
void
ClosingService::Start()
{
  if (!sTcpUdpPRCloseLayerMethodsPtr) {
    sTcpUdpPRCloseLayerId =  PR_GetUniqueIdentity("TCP and UDP PRClose layer");
    PR_ASSERT(PR_INVALID_IO_LAYER != sTcpUdpPRCloseLayerId);

    sTcpUdpPRCloseLayerMethods = *PR_GetDefaultIOMethods();
    sTcpUdpPRCloseLayerMethods.close = TcpUdpPRCloseLayerClose;
    sTcpUdpPRCloseLayerMethodsPtr = &sTcpUdpPRCloseLayerMethods;
  }

  if (!sInstance) {
    ClosingService* service = new ClosingService();
    if (NS_SUCCEEDED(service->StartInternal())) {
      NS_ADDREF(service);
      sInstance = service;
    } else {
      delete service;
    }
  }
}
NSAPI_PUBLIC int net_init(int security_on)
{
    _netlayer_identity = PR_GetUniqueIdentity("netlayer/" PRODUCT_FULL_VERSION_ID);

    const PRIOMethods *default_methods = PR_GetDefaultIOMethods();

    _netlayer_methods = *default_methods;
    _netlayer_methods.recv = _netlayer_method_recv;
    _netlayer_methods.read = _netlayer_method_read;
    _netlayer_methods.available = _netlayer_method_available;
    _netlayer_methods.available64 = _netlayer_method_available64;
    _netlayer_methods.seek = _netlayer_method_seek;
    _netlayer_methods.seek64 = _netlayer_method_seek64;
    _netlayer_methods.recvfrom = _netlayer_method_recvfrom;
    _netlayer_methods.poll = _netlayer_method_poll;
    _netlayer_methods.acceptread = _netlayer_method_acceptread;
    _netlayer_methods.close = _netlayer_method_close;

    _netlayer_default_close_method = default_methods->close;

    return 0;
}
Example #9
0
static PRStatus memio_InitializeLayerName(void)
{
    memio_identity = PR_GetUniqueIdentity("memio");
    return PR_SUCCESS;
}
Example #10
0
PRIntn main(PRIntn argc, char **argv)
{
    PRStatus rv;
    PRIntn mits;
    PLOptStatus os;
    PRFileDesc *client, *service;
    PRFileDesc *client_stack, *service_stack;
    PRNetAddr any_address;
    const char *server_name = NULL;
    const PRIOMethods *stubMethods;
    PRThread *client_thread, *server_thread;
    PRThreadScope thread_scope = PR_LOCAL_THREAD;
    PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:");
    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
    {
        if (PL_OPT_BAD == os) continue;
        switch (opt->option)
        {
        case 0:
            server_name = opt->value;
            break;
        case 'd':  /* debug mode */
            if (verbosity < noisy)
                verbosity = ChangeVerbosity(verbosity, 1);
            break;
        case 'q':  /* debug mode */
            if (verbosity > silent)
                verbosity = ChangeVerbosity(verbosity, -1);
            break;
        case 'G':  /* use global threads */
            thread_scope = PR_GLOBAL_THREAD;
            break;
        case 'C':  /* number of threads waiting */
            major_iterations = atoi(opt->value);
            break;
        case 'c':  /* number of client threads */
            minor_iterations = atoi(opt->value);
            break;
        case 'p':  /* default port */
            default_port = atoi(opt->value);
            break;
        default:
            break;
        }
    }
    PL_DestroyOptState(opt);
    PR_STDIO_INIT();

    logFile = PR_GetSpecialFD(PR_StandardError);

    identity = PR_GetUniqueIdentity("Dummy");
    stubMethods = PR_GetDefaultIOMethods();

    /*
    ** The protocol we're going to implement is one where in order to initiate
    ** a send, the sender must first solicit permission. Therefore, every
    ** send is really a send - receive - send sequence.
    */
    myMethods = *stubMethods;  /* first get the entire batch */
    myMethods.recv = MyRecv;  /* then override the ones we care about */
    myMethods.send = MySend;  /* then override the ones we care about */

    if (NULL == server_name)
        rv = PR_InitializeNetAddr(
            PR_IpAddrLoopback, default_port, &server_address);
    else
    {
        rv = PR_StringToNetAddr(server_name, &server_address);
        PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_InitializeNetAddr(
            PR_IpAddrNull, default_port, &server_address);
    }
    PR_ASSERT(PR_SUCCESS == rv);

    /* one type w/o layering */

    mits = minor_iterations;
    while (major_iterations-- > 0)
    {
        if (verbosity > silent)
            PR_fprintf(logFile, "Beginning non-layered test\n");
        client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
        service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
        rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
        PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);

        minor_iterations = mits;
        server_thread = PR_CreateThread(
            PR_USER_THREAD, Server, service,
            PR_PRIORITY_HIGH, thread_scope,
            PR_JOINABLE_THREAD, 16 * 1024);
        PR_ASSERT(NULL != server_thread);

        client_thread = PR_CreateThread(
            PR_USER_THREAD, Client, client,
            PR_PRIORITY_NORMAL, thread_scope,
            PR_JOINABLE_THREAD, 16 * 1024);
        PR_ASSERT(NULL != client_thread);

        rv = PR_JoinThread(client_thread);
        PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_JoinThread(server_thread);
        PR_ASSERT(PR_SUCCESS == rv);

        rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
        if (verbosity > silent)
            PR_fprintf(logFile, "Ending non-layered test\n");

        /* with layering */
        if (verbosity > silent)
            PR_fprintf(logFile, "Beginning layered test\n");
        client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
        PushLayer(client);
        service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
        PushLayer(service);
        rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
        PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);

        minor_iterations = mits;
        server_thread = PR_CreateThread(
            PR_USER_THREAD, Server, service,
            PR_PRIORITY_HIGH, thread_scope,
            PR_JOINABLE_THREAD, 16 * 1024);
        PR_ASSERT(NULL != server_thread);

        client_thread = PR_CreateThread(
            PR_USER_THREAD, Client, client,
            PR_PRIORITY_NORMAL, thread_scope,
            PR_JOINABLE_THREAD, 16 * 1024);
        PR_ASSERT(NULL != client_thread);

        rv = PR_JoinThread(client_thread);
        PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_JoinThread(server_thread);
        PR_ASSERT(PR_SUCCESS == rv);

        rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
        /* with layering, using new style stack */
        if (verbosity > silent)
            PR_fprintf(logFile,
							"Beginning layered test with new style stack\n");
        client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
    	client_stack = PR_CreateIOLayer(client);
        PushNewLayers(client_stack);
        service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
    	service_stack = PR_CreateIOLayer(service);
        PushNewLayers(service_stack);
        rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
        PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);

        minor_iterations = mits;
        server_thread = PR_CreateThread(
            PR_USER_THREAD, Server, service_stack,
            PR_PRIORITY_HIGH, thread_scope,
            PR_JOINABLE_THREAD, 16 * 1024);
        PR_ASSERT(NULL != server_thread);

        client_thread = PR_CreateThread(
            PR_USER_THREAD, Client, client_stack,
            PR_PRIORITY_NORMAL, thread_scope,
            PR_JOINABLE_THREAD, 16 * 1024);
        PR_ASSERT(NULL != client_thread);

        rv = PR_JoinThread(client_thread);
        PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_JoinThread(server_thread);
        PR_ASSERT(PR_SUCCESS == rv);

        rv = PR_Close(client_stack); PR_ASSERT(PR_SUCCESS == rv);
        rv = PR_Close(service_stack); PR_ASSERT(PR_SUCCESS == rv);
        if (verbosity > silent)
            PR_fprintf(logFile, "Ending layered test\n");
    }
    return 0;
}  /* main */
Example #11
0
int main(int argc, char **argv)
{
    PRHostEnt he;
    PRStatus status;
    PRIntn next_index;
    PRUint16 port_number;
    char netdb_buf[PR_NETDB_BUF_SIZE];
    PRNetAddr client_addr, server_addr;
    PRThread *client_thread, *server_thread;
    PRIntervalTime delta = PR_MillisecondsToInterval(500);

    err_out = PR_STDERR;
    std_out = PR_STDOUT;
    accept_timeout = PR_SecondsToInterval(2);
    emu_layer_ident = PR_GetUniqueIdentity("Emulated AcceptRead");
    emu_layer_methods = *PR_GetDefaultIOMethods();
    emu_layer_methods.acceptread = emu_AcceptRead;

    if (argc != 2 && argc != 3) port_number = DEFAULT_PORT;
    else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]);

    status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr);
    if (PR_SUCCESS != status)
    {
        PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
        PR_ProcessExit(1);
    }
    if (argc < 3)
    {
        status = PR_InitializeNetAddr(
            PR_IpAddrLoopback, port_number, &client_addr);
        if (PR_SUCCESS != status)
        {
            PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
            PR_ProcessExit(1);
        }
    }
    else
    {
        status = PR_GetHostByName(
            argv[1], netdb_buf, sizeof(netdb_buf), &he);
        if (status == PR_FAILURE)
        {
            PL_FPrintError(err_out, "PR_GetHostByName failed");
            PR_ProcessExit(1);
        }
        next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr);
        if (next_index == -1)
        {
            PL_FPrintError(err_out, "PR_EnumerateHostEnt failed");
            PR_ProcessExit(1);
        }
    }

    for (
        write_dally = 0;
        write_dally < accept_timeout + (2 * delta);
        write_dally += delta)
    {
        PR_fprintf(
            std_out, "Testing w/ write_dally = %d msec\n",
            PR_IntervalToMilliseconds(write_dally));
        server_thread = PR_CreateThread(
            PR_USER_THREAD, AcceptingThread, &server_addr,
            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
        if (server_thread == NULL)
        {
            PL_FPrintError(err_out, "PR_CreateThread (server) failed");
            PR_ProcessExit(1);
        }

        PR_Sleep(delta);  /* let the server pot thicken */

        client_thread = PR_CreateThread(
            PR_USER_THREAD, ConnectingThread, &client_addr,
            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
        if (client_thread == NULL)
        {
            PL_FPrintError(err_out, "PR_CreateThread (client) failed");
            PR_ProcessExit(1);
        }

        if (PR_JoinThread(client_thread) == PR_FAILURE)
            PL_FPrintError(err_out, "PR_JoinThread (client) failed");

        if (PR_JoinThread(server_thread) == PR_FAILURE)
            PL_FPrintError(err_out, "PR_JoinThread (server) failed");
    }

    return 0;
}
Example #12
0
// add SOCKS IO layer to an existing socket
nsresult
nsSOCKSIOLayerAddToSocket(int32_t family,
                          const char *host, 
                          int32_t port,
                          const char *proxyHost,
                          int32_t proxyPort,
                          int32_t socksVersion,
                          uint32_t flags,
                          PRFileDesc *fd, 
                          nsISupports** info)
{
    NS_ENSURE_TRUE((socksVersion == 4) || (socksVersion == 5), NS_ERROR_NOT_INITIALIZED);


    if (firstTime)
    {
        //XXX hack until NSPR provides an official way to detect system IPv6
        // support (bug 388519)
        PRFileDesc *tmpfd = PR_OpenTCPSocket(PR_AF_INET6);
        if (!tmpfd) {
            ipv6Supported = false;
        } else {
            // If the system does not support IPv6, NSPR will push
            // IPv6-to-IPv4 emulation layer onto the native layer
            ipv6Supported = PR_GetIdentitiesLayer(tmpfd, PR_NSPR_IO_LAYER) == tmpfd;
            PR_Close(tmpfd);
        }

        nsSOCKSIOLayerIdentity		= PR_GetUniqueIdentity("SOCKS layer");
        nsSOCKSIOLayerMethods		= *PR_GetDefaultIOMethods();

        nsSOCKSIOLayerMethods.connect	= nsSOCKSIOLayerConnect;
        nsSOCKSIOLayerMethods.connectcontinue	= nsSOCKSIOLayerConnectContinue;
        nsSOCKSIOLayerMethods.poll	= nsSOCKSIOLayerPoll;
        nsSOCKSIOLayerMethods.bind	= nsSOCKSIOLayerBind;
        nsSOCKSIOLayerMethods.acceptread = nsSOCKSIOLayerAcceptRead;
        nsSOCKSIOLayerMethods.getsockname = nsSOCKSIOLayerGetName;
        nsSOCKSIOLayerMethods.getpeername = nsSOCKSIOLayerGetPeerName;
        nsSOCKSIOLayerMethods.accept	= nsSOCKSIOLayerAccept;
        nsSOCKSIOLayerMethods.listen	= nsSOCKSIOLayerListen;
        nsSOCKSIOLayerMethods.close	= nsSOCKSIOLayerClose;

        firstTime			= false;

#if defined(PR_LOGGING)
        gSOCKSLog = PR_NewLogModule("SOCKS");
#endif

    }

    LOGDEBUG(("Entering nsSOCKSIOLayerAddToSocket()."));

    PRFileDesc *	layer;
    PRStatus	rv;

    layer = PR_CreateIOLayerStub(nsSOCKSIOLayerIdentity, &nsSOCKSIOLayerMethods);
    if (! layer)
    {
        LOGERROR(("PR_CreateIOLayerStub() failed."));
        return NS_ERROR_FAILURE;
    }

    nsSOCKSSocketInfo * infoObject = new nsSOCKSSocketInfo();
    if (!infoObject)
    {
        // clean up IOLayerStub
        LOGERROR(("Failed to create nsSOCKSSocketInfo()."));
        PR_DELETE(layer);
        return NS_ERROR_FAILURE;
    }

    NS_ADDREF(infoObject);
    infoObject->Init(socksVersion, family, proxyHost, proxyPort, host, flags);
    layer->secret = (PRFilePrivate*) infoObject;
    rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);

    if (rv == PR_FAILURE) {
        LOGERROR(("PR_PushIOLayer() failed. rv = %x.", rv));
        NS_RELEASE(infoObject);
        PR_DELETE(layer);
        return NS_ERROR_FAILURE;
    }

    *info = static_cast<nsISOCKSSocketInfo*>(infoObject);
    NS_ADDREF(*info);
    return NS_OK;
}
NSAPI_PUBLIC PRStatus filter_init(void)
{
    _filter_list_lock = PR_NewLock();

    // Get an IO layer identity for active NSAPI filters
    _filter_identity = PR_GetUniqueIdentity("NSAPI filter");

    // Figure out the NSS IO layer identity
    PRFileDesc *model = PR_NewTCPSocket();
    if (model) {
        model = SSL_ImportFD(NULL, model);
        _filter_ssl_identity = model->identity;
        PR_Close(model);
    }

    // Get an IO layer identity for our "null" (bottom of stack) IO layer
    _filter_null_identity = PR_GetUniqueIdentity("NSAPI filter stack");

    // Initialize the PRIOMethods for our "null" (bottom of stack) IO layer
    _filter_null_priomethods = *PR_GetDefaultIOMethods();
    _filter_null_priomethods.file_type = PR_DESC_PIPE; // Not socket/file/layer
    _filter_null_priomethods.close = &iolayer_null_close;
    _filter_null_priomethods.read = &iolayer_null_read;
    _filter_null_priomethods.write = &iolayer_null_write;
    _filter_null_priomethods.available = &iolayer_null_available;
    _filter_null_priomethods.available64 = &iolayer_null_available64;
    _filter_null_priomethods.fsync = &iolayer_null_fsync;
    _filter_null_priomethods.seek = &iolayer_null_seek;
    _filter_null_priomethods.seek64 = &iolayer_null_seek64;
    _filter_null_priomethods.fileInfo = &iolayer_null_fileinfo;
    _filter_null_priomethods.fileInfo64 = &iolayer_null_fileinfo64;
    _filter_null_priomethods.writev = &iolayer_null_writev;
    _filter_null_priomethods.connect = &iolayer_null_connect;
    _filter_null_priomethods.accept = &iolayer_null_accept;
    _filter_null_priomethods.bind = &iolayer_null_bind;
    _filter_null_priomethods.listen = &iolayer_null_listen;
    _filter_null_priomethods.shutdown = &iolayer_null_shutdown;
    _filter_null_priomethods.recv = &iolayer_null_recv;
    _filter_null_priomethods.send = &iolayer_null_send;
    _filter_null_priomethods.recvfrom = &iolayer_null_recvfrom;
    _filter_null_priomethods.sendto = &iolayer_null_sendto;
    _filter_null_priomethods.poll = &iolayer_null_poll;
    _filter_null_priomethods.acceptread = &iolayer_null_acceptread;
    _filter_null_priomethods.transmitfile = &iolayer_null_transmitfile;
    _filter_null_priomethods.getsockname = &iolayer_null_getsockname;
    _filter_null_priomethods.getpeername = &iolayer_null_getpeername;
    _filter_null_priomethods.getsocketoption = &iolayer_null_getsocketoption;
    _filter_null_priomethods.setsocketoption = &iolayer_null_setsocketoption;
    _filter_null_priomethods.sendfile = &iolayer_null_sendfile;
    _filter_null_priomethods.connectcontinue = &iolayer_null_connectcontinue;

    // Initialize pseudo-filters
    FilterMethods pseudo_methods = FILTER_METHODS_INITIALIZER;
    pseudo_methods.insert = &filtermethod_never_insert; // user can't insert these
    filter_fill(FILTER_NAME_TOP, 0x7fffffff /* top */, &pseudo_methods, 0, &_filter_top);
    filter_fill(FILTER_NAME_BOTTOM, 0 /* bottom */, &pseudo_methods, 0, &_filter_bottom);
    filter_fill(FILTER_NAME_NETWORK, FILTER_NETWORK, &pseudo_methods, 0, &_filter_network);
    filter_fill(FILTER_NAME_SSL, FILTER_TRANSPORT_CODING, &pseudo_methods, 0, &_filter_ssl);

    // Create a filter to call into Output stage and filter_set_request()
    FilterMethods callback_methods = FILTER_METHODS_INITIALIZER;
    callback_methods.insert = &filtermethod_always_insert;
    callback_methods.flush = &filtermethod_callback_flush;
    callback_methods.read = &filtermethod_callback_read;
    callback_methods.write = &filtermethod_callback_write;
    callback_methods.writev = (FilterWritevFunc*)&filtermethod_callback_writev;
    callback_methods.sendfile = (FilterSendfileFunc*)&filtermethod_callback_sendfile;
    _filter_callback = filter_create_internal("magnus-internal/callback",
                                              FILTER_TOPMOST,
                                              &callback_methods,
                                              FILTER_CALLS_CALLBACKS);
    if (!_filter_callback)
        return PR_FAILURE;

    // We'll use this per-DaemonSession slot to cache unused PRFileDescs
    _filter_prfiledesc_slot = session_alloc_thread_slot(NULL);

    // Will pass this empty pblock (instead of NULL) if filter_insert() is
    // called with a NULL pblock *
    _empty_pb = pblock_create(1);

    return PR_SUCCESS;
}
// TODO: make sure this is called from STS. Otherwise
// we have thread safety issues
bool TransportLayerDtls::Setup() {
  CheckThread();
  SECStatus rv;

  if (!downward_) {
    MOZ_MTLOG(ML_ERROR, "DTLS layer with nothing below. This is useless");
    return false;
  }
  nspr_io_adapter_ = new TransportLayerNSPRAdapter(downward_);

  if (!identity_) {
    MOZ_MTLOG(ML_ERROR, "Can't start DTLS without an identity");
    return false;
  }

  if (verification_mode_ == VERIFY_UNSET) {
    MOZ_MTLOG(ML_ERROR,
              "Can't start DTLS without specifying a verification mode");
    return false;
  }

  if (transport_layer_identity == PR_INVALID_IO_LAYER) {
    transport_layer_identity = PR_GetUniqueIdentity("nssstreamadapter");
  }

  ScopedPRFileDesc pr_fd(PR_CreateIOLayerStub(transport_layer_identity,
                                              &TransportLayerMethods));
  MOZ_ASSERT(pr_fd != nullptr);
  if (!pr_fd)
    return false;
  pr_fd->secret = reinterpret_cast<PRFilePrivate *>(nspr_io_adapter_.get());

  ScopedPRFileDesc ssl_fd(DTLS_ImportFD(nullptr, pr_fd));
  MOZ_ASSERT(ssl_fd != nullptr);  // This should never happen
  if (!ssl_fd) {
    return false;
  }

  pr_fd.forget(); // ownership transfered to ssl_fd;

  if (role_ == CLIENT) {
    MOZ_MTLOG(ML_DEBUG, "Setting up DTLS as client");
    rv = SSL_GetClientAuthDataHook(ssl_fd, GetClientAuthDataHook,
                                   this);
    if (rv != SECSuccess) {
      MOZ_MTLOG(ML_ERROR, "Couldn't set identity");
      return false;
    }
  } else {
    MOZ_MTLOG(ML_DEBUG, "Setting up DTLS as server");
    // Server side
    rv = SSL_ConfigSecureServer(ssl_fd, identity_->cert(),
                                identity_->privkey(),
                                kt_rsa);
    if (rv != SECSuccess) {
      MOZ_MTLOG(ML_ERROR, "Couldn't set identity");
      return false;
    }

    // Insist on a certificate from the client
    rv = SSL_OptionSet(ssl_fd, SSL_REQUEST_CERTIFICATE, PR_TRUE);
    if (rv != SECSuccess) {
      MOZ_MTLOG(ML_ERROR, "Couldn't request certificate");
      return false;
    }

    rv = SSL_OptionSet(ssl_fd, SSL_REQUIRE_CERTIFICATE, PR_TRUE);
    if (rv != SECSuccess) {
      MOZ_MTLOG(ML_ERROR, "Couldn't require certificate");
      return false;
    }
  }

  // Require TLS 1.1 or 1.2. Perhaps some day in the future we will allow TLS
  // 1.0 for stream modes.
  SSLVersionRange version_range = {
    SSL_LIBRARY_VERSION_TLS_1_1,
    SSL_LIBRARY_VERSION_TLS_1_2
  };

  rv = SSL_VersionRangeSet(ssl_fd, &version_range);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Can't disable SSLv3");
    return false;
  }

  rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't disable session tickets");
    return false;
  }

  rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't disable session caching");
    return false;
  }

  rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_DEFLATE, PR_FALSE);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't disable deflate");
    return false;
  }

  rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_NEVER);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't disable renegotiation");
    return false;
  }

  rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't disable false start");
    return false;
  }

  rv = SSL_OptionSet(ssl_fd, SSL_NO_LOCKS, PR_TRUE);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't disable locks");
    return false;
  }

  rv = SSL_OptionSet(ssl_fd, SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't disable ECDHE key reuse");
    return false;
  }

  if (!SetupCipherSuites(ssl_fd)) {
    return false;
  }

  // Certificate validation
  rv = SSL_AuthCertificateHook(ssl_fd, AuthCertificateHook,
                               reinterpret_cast<void *>(this));
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't set certificate validation hook");
    return false;
  }

  // Now start the handshake
  rv = SSL_ResetHandshake(ssl_fd, role_ == SERVER ? PR_TRUE : PR_FALSE);
  if (rv != SECSuccess) {
    MOZ_MTLOG(ML_ERROR, "Couldn't reset handshake");
    return false;
  }
  ssl_fd_ = ssl_fd.forget();

  // Finally, get ready to receive data
  downward_->SignalStateChange.connect(this, &TransportLayerDtls::StateChange);
  downward_->SignalPacketReceived.connect(this, &TransportLayerDtls::PacketReceived);

  if (downward_->state() == TS_OPEN) {
    Handshake();
  }

  return true;
}
NS_IMETHODIMP
nsWINCESSLSocketProvider::NewSocket(PRInt32 family,
                                    const char *host, 
                                    PRInt32 port,
                                    const char *proxyHost,
                                    PRInt32 proxyPort,
                                    PRUint32 flags,
                                    PRFileDesc **result, 
                                    nsISupports **socksInfo)
{
  static PRBool firstTime = PR_TRUE;
  if (firstTime)  {
    
    nsWINCESSLIOLayerIdentity		     = PR_GetUniqueIdentity("WINCESSL layer");
    nsWINCESSLIOLayerMethods		     = *PR_GetDefaultIOMethods();
    
    nsWINCESSLIOLayerMethods.connect   = nsWINCESSLIOLayerConnect;
    nsWINCESSLIOLayerMethods.close     = nsWINCESSLIOLayerClose;
    nsWINCESSLIOLayerMethods.available = nsWINCESSLIOLayerAvailable;
    nsWINCESSLIOLayerMethods.write     = nsWINCESSLIOLayerWrite;
    nsWINCESSLIOLayerMethods.read      = nsWINCESSLIOLayerRead;
    nsWINCESSLIOLayerMethods.poll      = nsWINCESSLIOLayerPoll;

    firstTime = PR_FALSE;
  }
  
  PRFileDesc *fd = PR_OpenTCPSocket(family);
  if (!fd)
    return NS_ERROR_OUT_OF_MEMORY;
  
  PRFileDesc *	layer;
  PRStatus	rv;
  
  layer = PR_CreateIOLayerStub(nsWINCESSLIOLayerIdentity, &nsWINCESSLIOLayerMethods);
  if (! layer)
    return NS_ERROR_UNEXPECTED;
  
  nsWINCESSLSocketInfo * infoObject = new nsWINCESSLSocketInfo();
  if (!infoObject)
    return NS_ERROR_OUT_OF_MEMORY;

  NS_ADDREF(infoObject);

  layer->secret = (PRFilePrivate*) infoObject;
  rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);
  if (NS_FAILED(rv))
    return NS_ERROR_UNEXPECTED;
  
  
  nsresult initrv = infoObject->Init(host, proxyHost, proxyPort);
  if (NS_FAILED(initrv))
  {
    MessageBox(0, "Can not create ssl socket.", "Can not create ssl socket.", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
    return NS_ERROR_FAILURE;
  }

  *result    = fd;
  *socksInfo = (nsISupports*) (nsITransportSecurityInfo*) infoObject;
  return NS_OK;

}