📄 wsseapi.c
字号:
soap_wsse_add_Timestamp(soap, NULL, 10); // 10 seconds lifetime@endcodeTimestamps, like other header elements, are not automatically secured with adigital signature. To secure a timestamp, we add an identifier (wsu:Id) to eachelement we want the WS-Security plugin to sign thereby making it impossible forsomeone to tamper with that part of the message. To do this for the timestamp,we simply pass a unique identification string as the second argument:@code soap_wsse_add_Timestamp(soap, "Time", 10); // timestamp will be signed@endcode*/#include "wsseapi.h"#include "smdevp.h"#include "threads.h" /* only need threads to enable mutex for MT *//** Plugin identification for plugin registry */const char soap_wsse_id[14] = SOAP_WSSE_ID;/** Maximum number of SignedInfo References */#define SOAP_WSSE_MAX_REF (100)/** Clock skew between machines (in sec) to fit message expiration in window */#define SOAP_WSSE_CLKSKEW (600)/** Size of the random nonce */#define SOAP_WSSE_NONCELEN (20)/** Digest authentication accepts messages that are not older than creation time + SOAP_WSSE_NONCETIME */#define SOAP_WSSE_NONCETIME (SOAP_WSSE_CLKSKEW + 240)/******************************************************************************\ * * Common URIs *\******************************************************************************/const char *wsse_PasswordTextURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";const char *wsse_PasswordDigestURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest";const char *wsse_Base64BinaryURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary";const char *wsse_X509v3URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";const char *wsse_X509v3SubjectKeyIdentifierURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier";const char *ds_sha1URI = "http://www.w3.org/2000/09/xmldsig#sha1";const char *ds_hmac_sha1URI = "http://www.w3.org/2000/09/xmldsig#hmac-sha1";const char *ds_dsa_sha1URI = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";const char *ds_rsa_sha1URI = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";const char *ds_URI = "http://www.w3.org/2000/09/xmldsig#";const char *c14n_URI = "http://www.w3.org/2001/10/xml-exc-c14n#";const char *wsu_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";/******************************************************************************\ * * Digest authentication session *\******************************************************************************//**@struct soap_wsse_session@brief Digest authentication session data*/struct soap_wsse_session{ struct soap_wsse_session *next; /**< Next session in list */ time_t expired; /**< Session expiration */ char hash[SOAP_SMD_SHA1_SIZE]; /**< SHA1 digest */ char nonce[1]; /**< Nonce string flows into region below this struct */};/** The digest authentication session database */static struct soap_wsse_session *soap_wsse_session = NULL;/** Lock for digest authentication session database exclusive access */#ifndef WIN32static MUTEX_TYPE soap_wsse_session_lock = PTHREAD_MUTEX_INITIALIZER;#elsestatic MUTEX_TYPE soap_wsse_session_lock;#endifstatic int soap_wsse_session_verify(struct soap *soap, const char hash[SOAP_SMD_SHA1_SIZE], const char *created, const char *nonce);static void soap_wsse_session_cleanup(struct soap *soap);static void calc_digest(struct soap *soap, const char *created, const char *nonce, int noncelen, const char *password, char hash[SOAP_SMD_SHA1_SIZE]);static void calc_nonce(struct soap *soap, char nonce[SOAP_WSSE_NONCELEN]);static int soap_wsse_init(struct soap *soap, struct soap_wsse_data *data, X509 *(*arg)(struct soap*));static int soap_wsse_copy(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src);static void soap_wsse_delete(struct soap *soap, struct soap_plugin *p);static int soap_wsse_prepareinit(struct soap *soap);static int soap_wsse_preparesend(struct soap *soap, const char *buf, size_t len);static int soap_wsse_preparefinal(struct soap *soap);static void soap_wsse_preparecleanup(struct soap *soap, struct soap_wsse_data *data);static int soap_wsse_disconnect(struct soap *soap);/******************************************************************************\ * * wsse:Security header element *\******************************************************************************//**@fn _wsse__Security* soap_wsse_add_Security(struct soap *soap)@brief Adds Security header element.@param soap context@return _wsse__Security object*/struct _wsse__Security*soap_wsse_add_Security(struct soap *soap){ DBGFUN("soap_wsse_add_Security"); /* if we don't have a SOAP Header, create one */ if (!soap->header) { soap->header = (struct SOAP_ENV__Header*)soap_malloc(soap, sizeof(struct SOAP_ENV__Header)); soap_default_SOAP_ENV__Header(soap, soap->header); } /* if we don't have a wsse:Security element in the SOAP Header, create one */ if (!soap->header->wsse__Security) { soap->header->wsse__Security = (_wsse__Security*)soap_malloc(soap, sizeof(_wsse__Security)); soap_default__wsse__Security(soap, soap->header->wsse__Security); } return soap->header->wsse__Security;}/**@fn _wsse__Security* soap_wsse_add_Security_actor(struct soap *soap, const char *actor)@brief Adds Security header element with actor or role attribute.@param soap context@param actor string@return _wsse__Security object*/struct _wsse__Security*soap_wsse_add_Security_actor(struct soap *soap, const char *actor){ _wsse__Security *security = soap_wsse_add_Security(soap); DBGFUN1("soap_wsse_add_Security_actor", "actor=%s", actor); if (soap->namespaces && !strcmp(soap->namespaces[0].ns, "http://schemas.xmlsoap.org/soap/envelope/")) security->SOAP_ENV__actor = soap_strdup(soap, actor); else security->SOAP_ENV__role = soap_strdup(soap, actor); return security;}/**@fn void soap_wsse_delete_Security(struct soap *soap)@brief Deletes Security header element.@param soap context*/voidsoap_wsse_delete_Security(struct soap *soap){ DBGFUN("soap_wsse_delete_Security"); if (soap->header) soap->header->wsse__Security = NULL;}/**@fn _wsse__Security* soap_wsse_Security(struct soap *soap)@brief Returns Security header element if present.@param soap context@return _wsse__Security object or NULL*/struct _wsse__Security*soap_wsse_Security(struct soap *soap){ if (soap->header) return soap->header->wsse__Security; return NULL;}/******************************************************************************\ * * wsse:Security/ds:Signature header element *\******************************************************************************//**@fn ds__SignatureType* soap_wsse_add_Signature(struct soap *soap)@brief Adds Signature header element.@param soap context@return ds__SignatureType object*/struct ds__SignatureType*soap_wsse_add_Signature(struct soap *soap){ _wsse__Security *security = soap_wsse_add_Security(soap); DBGFUN("soap_wsse_add_Signature"); /* if we don't have a ds:Signature, create one */ if (!security->ds__Signature) { security->ds__Signature = (ds__SignatureType*)soap_malloc(soap, sizeof(ds__SignatureType)); soap_default_ds__SignatureType(soap, security->ds__Signature); } return security->ds__Signature;}/**@fn void soap_wsse_delete_Signature(struct soap *soap)@brief Deletes Signature header element.@param soap context*/voidsoap_wsse_delete_Signature(struct soap *soap){ _wsse__Security *security = soap_wsse_Security(soap); DBGFUN("soap_wsse_delete_Signature"); if (security) security->ds__Signature = NULL;}/**@fn ds__SignatureType* soap_wsse_Signature(struct soap *soap)@brief Returns Signature header element if present.@param soap context@return ds__SignatureType object or NULL*/struct ds__SignatureType*soap_wsse_Signature(struct soap *soap){ _wsse__Security *security = soap_wsse_Security(soap); if (security) return security->ds__Signature; return NULL;}/******************************************************************************\ * * wsse:Security/wsu:Timestamp header element *\******************************************************************************//**@fn int soap_wsse_add_Timestamp(struct soap *soap, const char *id, time_t lifetime)@brief Adds Timestamp element with optional expiration date+time (lifetime).@param[in] soap context@param[in] id for signature referencing or NULL@param[in] lifetime expressed in time_t units, or 0 for no expiration@return SOAP_OK*/intsoap_wsse_add_Timestamp(struct soap *soap, const char *id, time_t lifetime){ _wsse__Security *security = soap_wsse_add_Security(soap); time_t now = time(NULL); char *created = soap_strdup(soap, soap_dateTime2s(soap, now)); char *expired = lifetime ? soap_strdup(soap, soap_dateTime2s(soap, now + lifetime)) : NULL; DBGFUN1("soap_wsse_add_Timestamp", "id=%s", id?id:""); /* allocate a Timestamp if we don't have one already */ if (!security->wsu__Timestamp) security->wsu__Timestamp = (_wsu__Timestamp*)soap_malloc(soap, sizeof(_wsu__Timestamp)); soap_default__wsu__Timestamp(soap, security->wsu__Timestamp); /* populate the wsu:Timestamp element */ security->wsu__Timestamp->wsu__Id = soap_strdup(soap, id); security->wsu__Timestamp->Created = created; security->wsu__Timestamp->Expires = expired; return SOAP_OK;}/**@fn _wsu__Timestamp *soap_wsse_Timestamp(struct soap *soap)@brief Returns Timestamp element if present.@param soap context@return _wsu__Timestamp object or NULL*/struct _wsu__Timestamp*soap_wsse_Timestamp(struct soap *soap){ _wsse__Security *security = soap_wsse_Security(soap); if (security) return security->wsu__Timestamp; return NULL;}/**@fn int soap_wsse_verify_Timestamp(struct soap *soap)@brief Verifies the Timestamp/Expires element against the current time.@param soap context@return SOAP_OK or SOAP_FAULT with wsse:FailedAuthentication faultSets wsse:FailedAuthentication fault if wsu:Timestamp is expired. TheSOAP_WSSE_CLKSKEW value is used as a margin to mitigate clock skew. Keepssilent when no timestamp is supplied or no expiration date is included in thewsu:Timestamp element.*/intsoap_wsse_verify_Timestamp(struct soap *soap){ _wsu__Timestamp *timestamp = soap_wsse_Timestamp(soap); DBGFUN("soap_wsse_verify_Timestamp"); /* if we have a timestamp with an expiration date, check it */ if (timestamp && timestamp->Expires) { time_t now = time(NULL), expired; soap_s2dateTime(soap, timestamp->Expires, &expired); if (expired + SOAP_WSSE_CLKSKEW <= now) { const char *code = soap_wsu__tTimestampFault2s(soap, wsu__MessageExpired); return soap_sender_fault_subcode(soap, code, "Message has expired", timestamp->Expires); } } return SOAP_OK;}/******************************************************************************\ * * wsse:Security/UsernameToken header element *\******************************************************************************//**@fn int soap_wsse_add_UsernameTokenText(struct soap *soap, const char *id, const char *username, const char *password)@brief Adds UsernameToken element with optional clear-text password.@param soap context@param[in] id string for signature referencing or NULL@param[in] username string@param[in] password string or NULL to omit the password@return SOAP_OKPasswords are sent in the clear, so transport-level encryption is required.Note: this release supports the use of at most one UsernameToken in the header.*/intsoap_wsse_add_UsernameTokenText(struct soap *soap, const char *id, const char *username, const char *password){ _wsse__Security *security = soap_wsse_add_Security(soap); DBGFUN2("soap_wsse_add_UsernameTokenText", "id=%s", id?id:"", "username=%s", username?username:""); /* allocate a UsernameToken if we don't have one already */ if (!security->UsernameToken) security->UsernameToken = (_wsse__UsernameToken*)soap_malloc(soap, sizeof(_wsse__UsernameToken)); soap_default__wsse__UsernameToken(soap, security->UsernameToken); /* populate the UsernameToken */ security->UsernameToken->wsu__Id = soap_strdup(soap, id); security->UsernameToken->Username = soap_strdup(soap, username);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -