📄 net.c
字号:
/* send the request */ msg[0] = 4; tds_strlcpy(msg + 1, instance, sizeof(msg) - 1); sendto(s, msg, strlen(msg) + 1, 0, (struct sockaddr *) &sin, sizeof(sin));#if USE_POLL fd.fd = s; fd.events = POLLIN; fd.revents = 0; retval = poll(&fd, 1, 1000);#else FD_ZERO(&fds); FD_SET(s, &fds); selecttimeout.tv_sec = 1; selecttimeout.tv_usec = 0; retval = select(s + 1, &fds, NULL, NULL, &selecttimeout);#endif /* on interrupt ignore */ if (retval < 0 && sock_errno == TDSSOCK_EINTR) continue; if (retval == 0) { /* timed out */#if 1 tdsdump_log(TDS_DBG_ERROR, "tds7_get_instance_port: timed out on try %d of 16\n", num_try); continue;#else int rc; tdsdump_log(TDS_DBG_INFO1, "timed out\n"); switch(rc = tdserror(NULL, NULL, TDSETIME, 0)) { case TDS_INT_CONTINUE: continue; /* try again */ default: tdsdump_log(TDS_DBG_ERROR, "error: client error handler returned %d\n", rc); case TDS_INT_CANCEL: CLOSESOCKET(s); return 0; }#endif } if (retval < 0) break; /* TODO pass also connection and set instance/servername ?? */ /* got data, read and parse */ if ((msg_len = recv(s, msg, sizeof(msg) - 1, 0)) > 3 && msg[0] == 5) { char *p; long l = 0; int instance_ok = 0, port_ok = 0; /* assure null terminated */ msg[msg_len] = 0; tdsdump_dump_buf(TDS_DBG_INFO1, "instance info", msg, msg_len); /* * Parse message and check instance name and port. * We don't check servername cause it can be very different from the client's. */ for (p = msg + 3;;) { char *name, *value; name = p; p = strchr(p, ';'); if (!p) break; *p++ = 0; value = p; p = strchr(p, ';'); if (!p) break; *p++ = 0; if (strcasecmp(name, "InstanceName") == 0) { if (strcasecmp(value, instance) != 0) break; instance_ok = 1; } else if (strcasecmp(name, "tcp") == 0) { l = strtol(value, &p, 10); if (l > 0 && l <= 0xffff && *p == 0) port_ok = 1; } } if (port_ok && instance_ok) { port = l; break; } } } CLOSESOCKET(s); tdsdump_log(TDS_DBG_ERROR, "instance port is %d\n", port); return port;}#if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)#ifdef HAVE_GNUTLSstatic ssize_t tds_pull_func(gnutls_transport_ptr ptr, void* data, size_t len){ TDSSOCKET *tds = (TDSSOCKET *) ptr;#elsestatic inttds_ssl_read(BIO *b, char* data, int len){ TDSSOCKET *tds = (TDSSOCKET *) b->ptr;#endif int have; tdsdump_log(TDS_DBG_INFO1, "in tds_pull_func\n"); /* if we have some data send it */ if (tds->out_pos > 8) tds_flush_packet(tds); if (tds->tls_session) { /* read directly from socket */ return tds_goodread(tds, data, len, 1); } for(;;) { have = tds->in_len - tds->in_pos; tdsdump_log(TDS_DBG_INFO1, "have %d\n", have); assert(have >= 0); if (have > 0) break; tdsdump_log(TDS_DBG_INFO1, "before read\n"); if (tds_read_packet(tds) < 0) return -1; tdsdump_log(TDS_DBG_INFO1, "after read\n"); } if (len > have) len = have; tdsdump_log(TDS_DBG_INFO1, "read %lu bytes\n", (unsigned long int) len); memcpy(data, tds->in_buf + tds->in_pos, len); tds->in_pos += len; return len;}#ifdef HAVE_GNUTLSstatic ssize_t tds_push_func(gnutls_transport_ptr ptr, const void* data, size_t len){ TDSSOCKET *tds = (TDSSOCKET *) ptr;#elsestatic inttds_ssl_write(BIO *b, const char* data, int len){ TDSSOCKET *tds = (TDSSOCKET *) b->ptr;#endif tdsdump_log(TDS_DBG_INFO1, "in tds_push_func\n"); if (tds->tls_session) { /* write to socket directly */ return tds_goodwrite(tds, data, len, 1); } tds_put_n(tds, data, len); return len;}#ifdef HAVE_GNUTLSstatic voidtds_tls_log( int level, const char* s){ tdsdump_log(TDS_DBG_INFO1, "GNUTLS: level %d:\n %s", level, s);}static int tls_initialized = 0;#ifdef TDS_ATTRIBUTE_DESTRUCTORstatic void __attribute__((destructor))tds_tls_deinit(void){ if (tls_initialized) gnutls_global_deinit();}#endifinttds_ssl_init(TDSSOCKET *tds){ gnutls_session session; gnutls_certificate_credentials xcred; static const int kx_priority[] = { GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, 0 }; static const int cipher_priority[] = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR_128,#if 0 GNUTLS_CIPHER_ARCFOUR_40, GNUTLS_CIPHER_DES_CBC,#endif 0 }; static const int comp_priority[] = { GNUTLS_COMP_NULL, 0 }; static const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 }; int ret; const char *tls_msg; xcred = NULL; session = NULL; tls_msg = "initializing tls"; /* FIXME place somewhere else, deinit at end */ ret = 0; if (!tls_initialized) ret = gnutls_global_init(); if (ret == 0) { tls_initialized = 1; gnutls_global_set_log_level(11); gnutls_global_set_log_function(tds_tls_log); tls_msg = "allocating credentials"; ret = gnutls_certificate_allocate_credentials(&xcred); } if (ret == 0) { /* Initialize TLS session */ tls_msg = "initializing session"; ret = gnutls_init(&session, GNUTLS_CLIENT); } if (ret == 0) { gnutls_transport_set_ptr(session, tds); gnutls_transport_set_pull_function(session, tds_pull_func); gnutls_transport_set_push_function(session, tds_push_func); /* NOTE: there functions return int however they cannot fail */ /* use default priorities... */ gnutls_set_default_priority(session); /* ... but overwrite some */ gnutls_cipher_set_priority(session, cipher_priority); gnutls_compression_set_priority(session, comp_priority); gnutls_kx_set_priority(session, kx_priority); gnutls_mac_set_priority(session, mac_priority); /* put the anonymous credentials to the current session */ tls_msg = "setting credential"; ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); } if (ret == 0) { /* Perform the TLS handshake */ tls_msg = "handshake"; ret = gnutls_handshake (session); } if (ret != 0) { if (session) gnutls_deinit(session); if (xcred) gnutls_certificate_free_credentials(xcred); tdsdump_log(TDS_DBG_ERROR, "%s failed: %s\n", tls_msg, gnutls_strerror (ret)); return TDS_FAIL; } tdsdump_log(TDS_DBG_INFO1, "handshake succeeded!!\n"); tds->tls_session = session; tds->tls_credentials = xcred; return TDS_SUCCEED;}voidtds_ssl_deinit(TDSSOCKET *tds){ if (tds->tls_session) { gnutls_deinit(tds->tls_session); tds->tls_session = NULL; } if (tds->tls_credentials) { gnutls_certificate_free_credentials(tds->tls_credentials); tds->tls_credentials = NULL; }}#elsestatic longtds_ssl_ctrl(BIO *b, int cmd, long num, void *ptr){ TDSSOCKET *tds = (TDSSOCKET *) b->ptr; switch (cmd) { case BIO_CTRL_FLUSH: if (tds->out_pos > 8) tds_flush_packet(tds); return 1; } return 0;}static inttds_ssl_free(BIO *a){ /* nothing to do but required */ return 1;}static BIO_METHOD tds_method ={ BIO_TYPE_MEM, "tds", tds_ssl_write, tds_ssl_read, NULL, NULL, tds_ssl_ctrl, NULL, tds_ssl_free, NULL,};static SSL_CTX *ssl_ctx;static inttds_init_openssl(void){ SSL_METHOD *meth; SSL_library_init (); meth = TLSv1_client_method (); if (meth == NULL) return 1; ssl_ctx = SSL_CTX_new (meth); if (ssl_ctx == NULL) return 1; return 0;}#ifdef TDS_ATTRIBUTE_DESTRUCTORstatic void __attribute__((destructor))tds_tls_deinit(void){ if (ssl_ctx) SSL_CTX_free (ssl_ctx);}#endifinttds_ssl_init(TDSSOCKET *tds){#define OPENSSL_CIPHERS \ SSL3_TXT_RSA_DES_64_CBC_SHA " " \ TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA " " \ TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA " " \ SSL3_TXT_RSA_RC4_40_MD5 " " \ SSL3_TXT_RSA_RC2_40_MD5 " " \ SSL3_TXT_EDH_DSS_DES_64_CBC_SHA " " \ TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA SSL *con; BIO *b; int ret; const char *tls_msg; con = NULL; b = NULL; tls_msg = "initializing tls"; /* FIXME place somewhere else, deinit at end */ ret = 0; if (!ssl_ctx) ret = tds_init_openssl(); if (ret == 0) { /* Initialize TLS session */ tls_msg = "initializing session"; con = SSL_new(ssl_ctx); } if (con) { tls_msg = "creating bio"; b = BIO_new(&tds_method); } ret = 0; if (b) { b->shutdown=1; b->init=1; b->num= -1; b->ptr = tds; SSL_set_bio(con, b, b); /* use priorities... */ SSL_set_cipher_list(con, OPENSSL_CIPHERS); /* Perform the TLS handshake */ tls_msg = "handshake"; SSL_set_connect_state(con); ret = SSL_connect(con) != 1 || con->state != SSL_ST_OK; } if (ret != 0) { if (con) { SSL_shutdown(con); SSL_free(con); } tdsdump_log(TDS_DBG_ERROR, "%s failed\n", tls_msg); return TDS_FAIL; } tdsdump_log(TDS_DBG_INFO1, "handshake succeeded!!\n"); tds->tls_session = con; tds->tls_credentials = NULL; return TDS_SUCCEED;}voidtds_ssl_deinit(TDSSOCKET *tds){ if (tds->tls_session) { /* NOTE do not call SSL_shutdown here */ SSL_free(tds->tls_session); tds->tls_session = NULL; }}#endif#endif/** @} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -