HRESULT Library_spot_net_native_Microsoft_SPOT_Net_NetworkInformation_NetworkInterface::IPAddressFromString___STATIC__U4__STRING( CLR_RT_StackFrame& stack ) { NATIVE_PROFILE_CLR_NETWORK(); TINYCLR_HEADER(); LPCSTR szName = stack.Arg0().RecoverString(); struct SOCK_addrinfo hints; struct SOCK_addrinfo* addr = NULL; struct SOCK_sockaddr_in* addr_in; int ret; memset( &hints, 0, sizeof(hints) ); ret = SOCK_getaddrinfo( szName, NULL, &hints, &addr ); // getaddrinfo returns a winsock error code rather than SOCK_SOCKET_ERROR, so pass this on to the exception handling if(ret != 0 || addr == NULL || addr->ai_family != SOCK_AF_INET) { TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); } _ASSERTE(addr->ai_addr != NULL); _ASSERTE(addr->ai_addrlen >= sizeof(SOCK_sockaddr_in)); addr_in = (struct SOCK_sockaddr_in*)addr->ai_addr; stack.PushValue().SetInteger( (CLR_UINT32)addr_in->sin_addr.S_un.S_addr ); TINYCLR_CLEANUP(); if( addr ) SOCK_freeaddrinfo( addr ); TINYCLR_CLEANUP_END(); }
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1( CLR_RT_StackFrame& stack ) { NATIVE_PROFILE_CLR_NETWORK(); TINYCLR_HEADER(); LPCSTR szName = stack.Arg0().RecoverString(); struct SOCK_addrinfo hints; struct SOCK_addrinfo* addr = NULL; struct SOCK_addrinfo* addrT; CLR_UINT32 cAddresses = 0; CLR_RT_HeapBlock* pAddress; CLR_INT32 timeout_ms = 30000; CLR_RT_HeapBlock hbTimeout; CLR_INT32 ret; bool fRes = true; CLR_INT64* timeout; hbTimeout.SetInteger( timeout_ms ); TINYCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout )); do { memset( &hints, 0, sizeof(hints) ); ret = SOCK_getaddrinfo( szName, NULL, &hints, &addr ); if(ret == SOCK_SOCKET_ERROR) { if(SOCK_getlasterror() == SOCK_EWOULDBLOCK) { // non-blocking - allow other threads to run while we wait for handle activity TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); } else { break; } } else { break; } } while(fRes); // timeout expired if(!fRes) { ret = SOCK_SOCKET_ERROR; ThrowError( stack, SOCK_ETIMEDOUT ); TINYCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); } // getaddrinfo returns a winsock error code rather than SOCK_SOCKET_ERROR, so pass this on to the exception handling if(ret != 0) { ThrowError( stack, ret ); TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); } { CLR_RT_HeapBlock hbCanonicalName; CLR_RT_HeapBlock hbAddresses; hbCanonicalName.SetObjectReference( NULL ); CLR_RT_ProtectFromGC gc( hbCanonicalName ); hbAddresses.SetObjectReference( NULL ); CLR_RT_ProtectFromGC gc2( hbAddresses ); for(int pass = 0; pass < 2; pass++) { cAddresses = 0; for(addrT = addr; addrT != NULL; addrT = addrT->ai_next) { if(pass == 1) { if(addrT->ai_canonname && addrT->ai_canonname[ 0 ]) { //allocate return string TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbCanonicalName, addrT->ai_canonname )); TINYCLR_CHECK_HRESULT(hbCanonicalName.StoreToReference( stack.Arg1(), 0 )); } //allocate address and store into array pAddress = (CLR_RT_HeapBlock*)hbAddresses.DereferenceArray()->GetElement( cAddresses ); TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( *pAddress, (CLR_UINT32)addrT->ai_addrlen, g_CLR_RT_WellKnownTypes.m_UInt8 )); //copy address. memcpy( pAddress->DereferenceArray()->GetFirstElement(), addrT->ai_addr, addrT->ai_addrlen ); } cAddresses++; } if(pass == 0) { //allocate array of byte arrays CLR_RT_ReflectionDef_Index idx; idx.m_kind = REFLECTION_TYPE; idx.m_levels = 2; idx.m_data.m_type.m_data = g_CLR_RT_WellKnownTypes.m_UInt8.m_data; TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( hbAddresses, cAddresses, idx )); TINYCLR_CHECK_HRESULT(hbAddresses.StoreToReference( stack.Arg2(), 0 )); } } } stack.PopValue(); // Timeout TINYCLR_CLEANUP(); if( addr ) SOCK_freeaddrinfo( addr ); TINYCLR_CLEANUP_END(); }
void Test_OpenSSL_ClientServerAuth() { LCD_Clear(); lcd_printf("Testing SSL Client/Server negotiations...\n"); int err; int client_numbytes, server_numbytes; int listen_sd; int server_sd; int client_sd; struct TINYCLR_SSL_SOCKADDR_IN sa_serv; struct TINYCLR_SSL_SOCKADDR_IN sa_cli; size_t client_len; SSL_CTX* server_ctx = NULL; SSL* server_ssl = NULL; X509* server_cert = NULL; SSL_CTX* client_ctx = NULL; SSL* client_ssl = NULL; X509* client_cert = NULL; char* str = NULL; char client_buf [256]; char server_buf [256]; SSL_METHOD *server_meth = NULL; SSL_METHOD *client_meth = NULL; BIO *cert = NULL; X509 *x = NULL; EVP_PKEY *pkey = NULL; // SSL preliminaries. // create client ssl client_meth = (SSL_METHOD*)SSLv3_client_method(); client_ctx = SSL_CTX_new (client_meth); if (!client_ctx) goto cleanup; server_meth = (SSL_METHOD*)SSLv3_server_method(); server_ctx = SSL_CTX_new (server_meth); if (!server_ctx) goto cleanup; if ((cert=BIO_new(BIO_s_mem())) == NULL) { TINYCLR_SSL_PRINTF("Unable to create new BIO"); goto cleanup; } BIO_puts(cert,server_pem); x=PEM_read_bio_X509_AUX(cert, NULL, 0, NULL); pkey=PEM_read_bio_PrivateKey(cert,NULL, server_ctx->default_passwd_callback,server_ctx->default_passwd_callback_userdata); //if (SSL_CTX_use_certificate_file(server_ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { if (SSL_CTX_use_certificate(server_ctx, x) <= 0) { TINYCLR_SSL_PRINTF("Use certifcate chain file failed"); goto cleanup; } if (SSL_CTX_use_PrivateKey(server_ctx, pkey) <= 0) { TINYCLR_SSL_PRINTF("Unable to use Private Key"); goto cleanup; } if (!SSL_CTX_check_private_key(server_ctx)) { TINYCLR_SSL_PRINTF("Private key does not match the certificate public key\n"); goto cleanup; } //if (SSL_CTX_set_cipher_list(server_ctx, ); // ----------------------------------------------- // Prepare TCP socket for receiving connections listen_sd = TINYCLR_SSL_SOCKET (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_sd < 0) goto cleanup; // set it to non-blocking int nonblock = 1; err = TINYCLR_SSL_IOCTL(listen_sd,SOCK_FIONBIO,&nonblock); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Nonblocking call failed for server: %d.\n", wsa); goto cleanup; } TINYCLR_SSL_MEMSET(&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); sa_serv.sin_port = TINYCLR_SSL_HTONS (1111); /* Server Port number */ TINYCLR_SSL_PRINTF("Binding to %d...\n", TINYCLR_SSL_NTOHS(sa_serv.sin_port)); err = TINYCLR_SSL_BIND(listen_sd, (struct TINYCLR_SSL_SOCKADDR*) &sa_serv, sizeof (sa_serv)); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Bind Socket error %d\n", wsa); goto cleanup; } TINYCLR_SSL_PRINTF("Listening...\n"); /* Receive a TCP connection. */ err = TINYCLR_SSL_LISTEN (listen_sd, 5); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Listen Socket error %d\n", wsa); goto cleanup; } // create a client socket client_sd = TINYCLR_SSL_SOCKET (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (client_sd < 0) goto cleanup; // set it to non-blocking err = TINYCLR_SSL_IOCTL(client_sd,SOCK_FIONBIO,&nonblock); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Nonblocking call failed for client: %d.\n", wsa); goto cleanup; } // Set up a tcp connection for client: Bind, Connect err == TINYCLR_SSL_CONNECT( client_sd, (const struct TINYCLR_SSL_SOCKADDR*)&sa_serv, sizeof(sa_serv)); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Client connect failed with: %d.\n", wsa); } client_len = sizeof(sa_cli); char nodename[128] = ""; char servname[128] = ""; SOCK_addrinfo hints; SOCK_addrinfo *res = NULL; TINYCLR_SSL_MEMSET(&hints, '\0', sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; SOCK_getaddrinfo(nodename,servname,&hints,&res); SOCK_addrinfo *ptr = NULL; for (ptr=res; ptr!=NULL; ptr=ptr->ai_next) { struct sockaddr_in *ip = (struct sockaddr_in*) ptr->ai_addr; TINYCLR_SSL_PRINTF("Accepting connections on...%s:%d\n", inet_ntoa(ip->sin_addr), 1111 ); } int counter=0; do { server_sd = TINYCLR_SSL_ACCEPT (listen_sd, (struct TINYCLR_SSL_SOCKADDR*) &sa_cli, (int*)&client_len); Events_WaitForEvents(0,2000); TINYCLR_SSL_PRINTF("Accept again %d:%d\n", TINYCLR_SSL_GETLASTSOCKETERROR(), counter++); } while (server_sd == -1); TINYCLR_SSL_CLOSESOCKET (listen_sd); TINYCLR_SSL_PRINTF ("Connection from %lx, port %x\n", sa_cli.sin_addr.S_un.S_addr, sa_cli.sin_port); // connections are completed between server & client // now lets do the SSL negotiations // create server ssl server_ssl = SSL_new(server_ctx); if (server_ssl == NULL) goto cleanup; SSL_set_fd (server_ssl, server_sd); //Create server bio and set as non-blocking BIO* server_bio = BIO_new(BIO_s_socket()); if (server_bio == NULL) goto cleanup; //CHK_NULL(bio); BIO_set_nbio(server_bio,1); BIO_set_fd(server_bio, server_sd, BIO_NOCLOSE); SSL_set_bio(server_ssl,server_bio,server_bio); // create client ssl & connect client_ssl = SSL_new(client_ctx); if (client_ssl == NULL) goto cleanup; SSL_set_fd(client_ssl, client_sd); //Create client bio and set as non-blocking BIO* client_bio = BIO_new(BIO_s_socket()); if (client_bio == NULL) goto cleanup; BIO_set_nbio(client_bio,1); BIO_set_fd(client_bio, client_sd, BIO_NOCLOSE); SSL_set_bio(client_ssl,client_bio,client_bio); // loop until server accepts ssl client connect int ssl_err =0; do { err = SSL_connect(client_ssl); if (err <= 0) { ssl_err = SSL_get_error(client_ssl,err); TINYCLR_SSL_PRINTF("SSL_Connect error: %d\n", ssl_err); } Events_WaitForEvents(0,1000); err = SSL_accept (server_ssl); if (err <= 0) { ssl_err = SSL_get_error(server_ssl, err); TINYCLR_SSL_PRINTF("SSL_Accept error: %d\n", ssl_err); } Events_WaitForEvents(0,1000); } while (err != 1); //Get the cipher - opt TINYCLR_SSL_PRINTF("SSL connection using %s\n", SSL_get_cipher (server_ssl)); //Get client's certificate (note: beware of dynamic allocation) - opt client_cert = SSL_get_peer_certificate (server_ssl); if (client_cert != NULL) { TINYCLR_SSL_PRINTF("Client certificate:\n"); str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("issuer: %s\n", str); OPENSSL_free (str); //We could do all sorts of certificate verification stuff here before // deallocating the certificate. X509_free (client_cert); } else TINYCLR_SSL_PRINTF("Client does not have certificate.\n"); //Get server's certificate (note: beware of dynamic allocation) - opt server_cert = SSL_get_peer_certificate (client_ssl); if (server_cert != NULL) { TINYCLR_SSL_PRINTF("Server certificate:\n"); str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (server_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("issuer: %s\n", str); OPENSSL_free (str); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free (server_cert); } else TINYCLR_SSL_PRINTF("Server with no certificate?!?!?.\n"); do { // DATA EXCHANGE - Receive message and send reply. err = SSL_write(client_ssl,"Hello World!",TINYCLR_SSL_STRLEN("Hello World!")); if (err <= 0) ssl_err = SSL_get_error(client_ssl, err); Events_WaitForEvents(0,1000); server_numbytes= SSL_read (server_ssl, server_buf, sizeof(server_buf) - 1); if (server_numbytes <= 0) ssl_err = SSL_get_error(server_ssl, server_numbytes); else server_buf[server_numbytes] = '\0'; Events_WaitForEvents(0,1000); err = SSL_write (server_ssl, "I hear you.", TINYCLR_SSL_STRLEN("I hear you.")); if (err <= 0) ssl_err = SSL_get_error(server_ssl, err); Events_WaitForEvents(0,1000); client_numbytes= SSL_read(client_ssl, client_buf, sizeof(client_buf) -1); if (client_numbytes <= 0) ssl_err = SSL_get_error(client_ssl, client_numbytes); else client_buf[client_numbytes] = '\0'; Events_WaitForEvents(0,1000); } while (err <= 0); TINYCLR_SSL_PRINTF("Server got %d chars:'%s'\n", server_numbytes, server_buf); TINYCLR_SSL_PRINTF("Client go %d chars:'%s'\n", client_numbytes, client_buf); /* Clean up. */ cleanup: if (pkey) EVP_PKEY_free(pkey); if (cert) BIO_free(cert); if (x) X509_free(x); TINYCLR_SSL_CLOSESOCKET(server_sd); if (server_ssl) SSL_shutdown(server_ssl); if (server_ssl) SSL_free (server_ssl); server_ssl = NULL; if (server_ctx) SSL_CTX_free(server_ctx); server_ctx = NULL; TINYCLR_SSL_CLOSESOCKET(client_sd); if (client_ssl) SSL_shutdown(client_ssl); if (client_ssl) SSL_free (client_ssl); client_ssl = NULL; if (client_ctx) SSL_CTX_free(client_ctx); client_ctx = NULL; }