带 SSL 的简单 gSoap 服务器和客户端
Simple gSoap Server and Client with SSL
对 soap_ssl_accept
的调用总是导致错误 SSL23_GET_CLIENT_HELLO:unknown protocol
。我让它尽可能简单,并通过设置 SOAP_SSL_NO_AUTHENTICATION
关闭了服务器身份验证。我将其分解为以下服务器和客户端代码。你能帮我举个例子吗?
服务器端:
#include <cstdio>
#include "ADService.nsmap" // get namespace bindings
#include "stdsoap2.h"
#include "soapH.h"
int ns1__add(struct soap *soap, xsd__int a, xsd__int b, xsd__int& c) {
c = a + b;
return SOAP_OK;
}
int main() {
int m, s;
struct soap soap;
soap_ssl_init(); // init OpenSSL (just once)
soap_init(&soap);
if (soap_ssl_server_context(&soap,
SOAP_SSL_NO_AUTHENTICATION,
NULL, // keyfile: required when server must authenticate to clients
NULL, // password to read the key file
NULL, // optional cacert file to store trusted certificates
NULL, // optional capath to directory with trusted certificates
NULL, // DH file name or DH key len bits
NULL, // if randfile!=NULL: use a file with random data
NULL)) {
soap_print_fault(&soap, stderr);
exit(1);
}
m = soap_bind(&soap, NULL, 18000, 100); // use port 18000
if (m < 0) {
soap_print_fault(&soap, stderr);
exit(1);
}
printf("Socket connection successful: master socket = %d\n", m);
for (;;) {
s = soap_accept(&soap);
printf("Socket connection successful: slave socket = %d\n", s);
if (s < 0) {
soap_print_fault(&soap, stderr);
break;
}
if (soap_ssl_accept(&soap))
soap_print_fault(&soap, stderr);
else
soap_serve(&soap);
soap_destroy(&soap);
soap_end(&soap);
soap_free(&soap); // done and free context
}
soap_done(&soap); /* deallocates SSL context */
return 0;
}
客户端:
#include <iostream>
#include "soapH.h" // obtain the generated stub
#include "ADService.nsmap" // obtain the namespace mapping table
int main(int argc, const char* argv[]) {
soap soap;
soap_ssl_init();
soap_init(&soap);
if (soap_ssl_client_context(&soap,
SOAP_SSL_NO_AUTHENTICATION,
NULL, // keyfile: required only when client must authenticate to server
NULL, // password to read the key file (not used with GNUTLS)
NULL, // cacert file to store trusted certificates
NULL, // capath to directory with trusted certificates
NULL // if randfile!=NULL: use a file with random data to seed randomness
)) {
soap_print_fault(&soap, stderr);
return 1;
}
xsd__int result;
if(soap_call_ns1__add(
&soap, "localhost:18000", 0, 1, 2, result) != SOAP_OK) {
soap_print_fault(&soap, stderr);
soap_print_fault_location(&soap, stderr);
return 1;
}
printf("Result = %d", result);
soap_destroy(&soap);
soap_end(&soap);
soap_done(&soap);
return 0;
}
服务器端输出:
Socket connection successful: master socket = 1916
Socket connection successful: slave socket = 1912
Error 30 fault: SOAP-ENV:Server [no subcode]
"SSL_ERROR_SSL
error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown > protocol"
Detail: SSL_accept() failed in soap_ssl_accept()
Press any key to continue
这不是一个确定的答案。但可能会有所帮助。我是如何以你所看到的错误结束的:
3077928696:error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol:s23_srvr.c:628
当与服务器建立成功的 TCP 连接时,客户端发送格式错误的 client_hello 消息时会发生这种情况。我基本上在我的测试中在 TCP 连接后发送了垃圾字节。
捕获 tcpdump b/w 服务器和客户端,看看客户端输出了什么。
使用主机名 https://localhost:18000
调用 soap_call_ns1__add
解决了问题。
对 soap_ssl_accept
的调用总是导致错误 SSL23_GET_CLIENT_HELLO:unknown protocol
。我让它尽可能简单,并通过设置 SOAP_SSL_NO_AUTHENTICATION
关闭了服务器身份验证。我将其分解为以下服务器和客户端代码。你能帮我举个例子吗?
服务器端:
#include <cstdio>
#include "ADService.nsmap" // get namespace bindings
#include "stdsoap2.h"
#include "soapH.h"
int ns1__add(struct soap *soap, xsd__int a, xsd__int b, xsd__int& c) {
c = a + b;
return SOAP_OK;
}
int main() {
int m, s;
struct soap soap;
soap_ssl_init(); // init OpenSSL (just once)
soap_init(&soap);
if (soap_ssl_server_context(&soap,
SOAP_SSL_NO_AUTHENTICATION,
NULL, // keyfile: required when server must authenticate to clients
NULL, // password to read the key file
NULL, // optional cacert file to store trusted certificates
NULL, // optional capath to directory with trusted certificates
NULL, // DH file name or DH key len bits
NULL, // if randfile!=NULL: use a file with random data
NULL)) {
soap_print_fault(&soap, stderr);
exit(1);
}
m = soap_bind(&soap, NULL, 18000, 100); // use port 18000
if (m < 0) {
soap_print_fault(&soap, stderr);
exit(1);
}
printf("Socket connection successful: master socket = %d\n", m);
for (;;) {
s = soap_accept(&soap);
printf("Socket connection successful: slave socket = %d\n", s);
if (s < 0) {
soap_print_fault(&soap, stderr);
break;
}
if (soap_ssl_accept(&soap))
soap_print_fault(&soap, stderr);
else
soap_serve(&soap);
soap_destroy(&soap);
soap_end(&soap);
soap_free(&soap); // done and free context
}
soap_done(&soap); /* deallocates SSL context */
return 0;
}
客户端:
#include <iostream>
#include "soapH.h" // obtain the generated stub
#include "ADService.nsmap" // obtain the namespace mapping table
int main(int argc, const char* argv[]) {
soap soap;
soap_ssl_init();
soap_init(&soap);
if (soap_ssl_client_context(&soap,
SOAP_SSL_NO_AUTHENTICATION,
NULL, // keyfile: required only when client must authenticate to server
NULL, // password to read the key file (not used with GNUTLS)
NULL, // cacert file to store trusted certificates
NULL, // capath to directory with trusted certificates
NULL // if randfile!=NULL: use a file with random data to seed randomness
)) {
soap_print_fault(&soap, stderr);
return 1;
}
xsd__int result;
if(soap_call_ns1__add(
&soap, "localhost:18000", 0, 1, 2, result) != SOAP_OK) {
soap_print_fault(&soap, stderr);
soap_print_fault_location(&soap, stderr);
return 1;
}
printf("Result = %d", result);
soap_destroy(&soap);
soap_end(&soap);
soap_done(&soap);
return 0;
}
服务器端输出:
Socket connection successful: master socket = 1916
Socket connection successful: slave socket = 1912
Error 30 fault: SOAP-ENV:Server [no subcode]
"SSL_ERROR_SSL
error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown > protocol"
Detail: SSL_accept() failed in soap_ssl_accept()
Press any key to continue
这不是一个确定的答案。但可能会有所帮助。我是如何以你所看到的错误结束的:
3077928696:error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol:s23_srvr.c:628
当与服务器建立成功的 TCP 连接时,客户端发送格式错误的 client_hello 消息时会发生这种情况。我基本上在我的测试中在 TCP 连接后发送了垃圾字节。
捕获 tcpdump b/w 服务器和客户端,看看客户端输出了什么。
使用主机名 https://localhost:18000
调用 soap_call_ns1__add
解决了问题。