WS-Security using gSOAP
gSOAP plug-in을 이용하여 ONVIF device service 에 WS-Security를 추가하는 방법을 설명한다.
-
/gSOAP/bin/share/gsoap/WS/typemap.dat 에서 아래 추가 후 ONVIF-typemap.dat로 수정.
tt = "http://www.onvif.org/ver10/schema"
tds = "http://www.onvif.org/ver10/device/wsdl"
trt = "http://www.onvif.org/ver10/media/wsdl"
tev = "http://www.onvif.org/ver10/events/wsdl"
ter = "http://www.onvif.org/ver10/error"
dn = "http://www.onvif.org/ver10/network/wsdl"
tptz = "http://www.onvif.org/ver20/ptz/wsdl"
tima = "http://www.onvif.org/ver20/imaging/wsdl"
tns1 = "http://www.onvif.org/ver10/topics"
wsdl = "http://schemas.xmlsoap.org/wsdl/"
wsoap12 = "http://schemas.xmlsoap.org/wsdl/soap12/"
http = "http://schemas.xmlsoap.org/wsdl/http/"
soapenc = "http://www.w3.org/2003/05/soap-encoding"
soapenv = "http://www.w3.org/2003/05/soap-envelope"
xs = "http://www.w3.org/2001/XMLSchema"
xsi = "http://www.w3.org/2001/XMLSchema-instance"
d = "http://schemas.xmlsoap.org/ws/2005/04/discovery"
wsadis = "http://schemas.xmlsoap.org/ws/2004/08/addressing"
wstop = "ttp://docs.oasis-open.org/wsn/t-1"
wsnt = "http://docs.oasis-open.org/wsn/b-2"
xop = "http://www.w3.org/2004/08/xop/include"
wsrf_bf2 = "http://docs.oasis-open.org/wsrf/bf-2"
wsrf_rw2 = "http://docs.oasis-open.org/wsrf/rw-2"
wsrf_r2 = "http://docs.oasis-open.org/wsrf/r-2"
wstop = "http://docs.oasis-open.org/wsn/t-1"
wsnt = "http://docs.oasis-open.org/wsn/b-2"
xop = "http://www.w3.org/2004/08/xop/include"
-
wsdl2h -c -nonvif -Nonvif -t wsdl/ONVIF-typemap.dat -o wsdl/devicemgmt_gsoap.h wsdl/devicemgmt.wsdl
-
devicemgmt_gsoap.h 수정
#import "wsse.h" 추가.
-
soapcpp2 -L -x -S -c -I../../gSOAP/bin/share/gsoap/import/ wsdl/devicemgmt_gsoap.h
-
인증 처리절차 추가
-
int security_check(struct soap *soap)
{
const char *username = soap_wsse_get_Username(soap);
if(username)
{
sprintf(debug_buff,"request user:%s", username);
Debug_cgi(debug_buff);
}
if (soap_wsse_verify_Timestamp(soap)
|| soap_wsse_verify_Password(soap, "password"))
{
Debug_cgi("failed to soap_wsse_verify_Password ");
soap_wsse_delete_Security(soap);
return soap->error;
}
soap_wsse_delete_Security(soap);
Debug_cgi("success to soap_wsse_verify_Password");
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap)
{
soap_peek_element(soap);
// 클라이언트가 시간을 동기화할 수 있도록 허용하여 인증만료로 인한 인증실패를 피한다.
if (soap_match_tag(soap, soap->tag, "tds:GetSystemDateAndTime"))
{
if ( security_check(soap) != SOAP_OK) return soap->error;
}
.....
....
-
int security_check(struct soap *soap)
- compile
참조 : gSOAP/gsoap-2.8/gsoap/doc/wsse/html/wsse.html
-
include ../Rules.make
GCC_PATH=/usr/arm/mv_pro_5.0.0/montavista/pro/devkit/arm/v5t_le/bin
CROSS:=$(GCC_PATH)/arm_v5t_le-
CC:=$(CROSS)gcc
AR:=$(CROSS)ar
RELTARGET := services
INC_PATH= -I$(BASE_DIR)/gSOAP/bin/include -I$(LIB_PATH)/include
CFLAGS := -Wall -g $(INC_PATH) -DWITH_DOM -DWITH_OPENSSL
SRC_COMMON = soapC.c soapServer.c
SRCS := $(SRC_COMMON) devicemgmt_service.c wsaapi.c wsseapi.c threads.c dom.c smdevp.c mecevp.c
OBJS := $(SRCS:%.c=%.o)
LIBS = -L$(BASE_DIR)/gSOAP/bin/lib -lgsoapssl -lssl -lcrypto -lz -L$(LIB_PATH)/bin -lnettool
.PHONY : clean all
all: release
release: $(RELTARGET)
$(RELTARGET): $(OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
install: release
install $(RELTARGET) $(TARGET_CGI_PATH)
clean:
@rm -f $(TARGET)
@rm -f $(OBJS)
@rm -f $(RELTARGET)
1). 문제: 인증실패시 wsseapi.c에서 soap_wsse_sender_fault_subcode() 호출하면 soap protocol error메시지가 'Plugin registry error'
원인: 메시지 처럼 WSA plug-in 을 등록해야한다.
해결: 플러그인 등록 함수 추가
soap_register_plugin(&soap, soap_wsa);
soap_register_plugin_arg(&soap, soap_wsse, token_handler);
2). 문졔: CGI라 디버깅 하기가 어렵다
해결: soap 라이브러리 컴파일시 -enalbe-debug
추가, 컴파일시 -DDEBUG 플래그추가 , soap_set_test_logfile() 함수 등록.
3). 문제: __tds__GetSystemDateAndTime() 함수에서 인증이 실패된다.
원인: 클라이언트(GMT)와 서버간(로컬시간)의 시간이 달라서 인증만료로 에러된다.
해결: __tds__GetSystemDateAndTime() 는 인증을 하지않도록 하여 클라이언트가 시간을 동기화 하도록한다.
4). 문제: __tds__GetHostname() 수신시 soap protocol error 메시지가 '502 bad gateway'
원인: HostnameInformation->Extension를 초기화 하지않음.
해결: HostnameInformation->Extension=NULL;
5). 문제: security 인증 시퀀스를 모든 메소드에 넣으면 손이 많이 가고 지저분하다.
해결: soap_serve_request()에서 인증을 하고 각 메소드를 처리하도록 수정.
댓글 없음:
댓글 쓰기