📄 wsseapi.c
字号:
/* allocate and populate the Password */ if (password) { security->UsernameToken->Password = (_wsse__Password*)soap_malloc(soap, sizeof(_wsse__Password)); soap_default__wsse__Password(soap, security->UsernameToken->Password); security->UsernameToken->Password->Type = (char*)wsse_PasswordTextURI; security->UsernameToken->Password->__item = soap_strdup(soap, password); } return SOAP_OK;}/**@fn int soap_wsse_add_UsernameTokenDigest(struct soap *soap, const char *id, const char *username, const char *password)@brief Adds UsernameToken element for digest authentication.@param soap context@param[in] id string for signature referencing or NULL@param[in] username string@param[in] password string@return SOAP_OKComputes SHA1 digest of the time stamp, a nonce, and the password. The digestprovides the authentication credentials. Passwords are NOT sent in the clear.Note: this release supports the use of at most one UsernameToken in the header.*/intsoap_wsse_add_UsernameTokenDigest(struct soap *soap, const char *id, const char *username, const char *password){ _wsse__Security *security = soap_wsse_add_Security(soap); time_t now = time(NULL); const char *created = soap_dateTime2s(soap, now); char HA[SOAP_SMD_SHA1_SIZE], HABase64[29]; char nonce[SOAP_WSSE_NONCELEN], *nonceBase64; DBGFUN2("soap_wsse_add_UsernameTokenDigest", "id=%s", id?id:"", "username=%s", username?username:""); /* generate a nonce */ calc_nonce(soap, nonce); nonceBase64 = soap_s2base64(soap, (unsigned char*)nonce, NULL, SOAP_WSSE_NONCELEN); /* The specs are not clear: compute digest over binary nonce or base64 nonce? */ /* compute SHA1(created, nonce, password) */ calc_digest(soap, created, nonce, SOAP_WSSE_NONCELEN, password, HA); /* calc_digest(soap, created, nonceBase64, strlen(nonceBase64), password, HA); */ soap_s2base64(soap, (unsigned char*)HA, HABase64, SOAP_SMD_SHA1_SIZE); /* populate the UsernameToken with digest */ soap_wsse_add_UsernameTokenText(soap, id, username, HABase64); /* populate the remainder of the password, nonce, and created */ security->UsernameToken->Password->Type = (char*)wsse_PasswordDigestURI; security->UsernameToken->Nonce = nonceBase64; security->UsernameToken->wsu__Created = soap_strdup(soap, created); return SOAP_OK;}/**@fn _wsse__UsernameToken* soap_wsse_UsernameToken(struct soap *soap, const char *id)@brief Returns UsernameToken element if present.@param soap context@param[in] id string of UsernameToken or NULL@return _wsse__UsernameToken object or NULLNote: this release supports the use of at most one UsernameToken in the header.*/struct _wsse__UsernameToken*soap_wsse_UsernameToken(struct soap *soap, const char *id){ _wsse__Security *security = soap_wsse_Security(soap); if (security && security->UsernameToken && (!id || (security->UsernameToken->wsu__Id && !strcmp(security->UsernameToken->wsu__Id, id)))) return security->UsernameToken; return NULL;}/**@fn const char* soap_wsse_get_Username(struct soap *soap)@brief Returns UsernameToken/username string or wsse:FailedAuthentication fault.@param soap context@return UsernameToken/username string or NULL with wsse:FailedAuthentication fault error set@see soap_wsse_verify_PasswordThe returned username should be used to lookup the user's password in adictionary or database for server-side authentication withsoap_wsse_verify_Password.*/const char*soap_wsse_get_Username(struct soap *soap){ _wsse__UsernameToken *token = soap_wsse_UsernameToken(soap, NULL); DBGFUN("soap_wsse_get_Username"); if (token) return token->Username; soap_wsse_fault(soap, wsse__FailedAuthentication, "Authentication required"); return NULL;}/**@fn int soap_wsse_verify_Password(struct soap *soap, const char *password)@brief Verifies the supplied password or sets wsse:FailedAuthentication fault.@param soap context@param[in] password string to verify against@return SOAP_OK (authorized) or SOAP_FAULT with wsse:FailedAuthentication faultThe verification supports both clear-text password verification and digestpassword authentication. For digest authentication a history mechanism with adigest authentication session database ensures protection against replayattacks.Note: this release supports the use of at most one UsernameToken in the header.*/intsoap_wsse_verify_Password(struct soap *soap, const char *password){ _wsse__UsernameToken *token = soap_wsse_UsernameToken(soap, NULL); DBGFUN("soap_wsse_verify_Password"); /* if we have a UsernameToken with a Password, check it */ if (token && token->Password) { /* password digest or text? */ if (token->Password->Type && !strcmp(token->Password->Type, wsse_PasswordDigestURI)) { /* check password digest: compute SHA1(created, nonce, password) */ if (token->Nonce && token->wsu__Created && strlen(token->Password->__item) == 28) /* digest pw len = 28 */ { char HA1[SOAP_SMD_SHA1_SIZE], HA2[SOAP_SMD_SHA1_SIZE]; /* The specs are not clear: compute digest over binary nonce or base64 nonce? The formet appears to be the case: */ int noncelen; const char *nonce = soap_base642s(soap, token->Nonce, NULL, 0, &noncelen); /* compute HA1 = SHA1(created, nonce, password) */ calc_digest(soap, token->wsu__Created, nonce, noncelen, password, HA1); /* calc_digest(soap, token->wsu__Created, token->Nonce, strlen(token->Nonce), password, HA1); */ /* get HA2 = supplied digest from base64 Password */ soap_base642s(soap, token->Password->__item, HA2, SOAP_SMD_SHA1_SIZE, NULL); /* compare HA1 to HA2 */ if (!memcmp(HA1, HA2, SOAP_SMD_SHA1_SIZE)) { /* authorize if HA1 and HA2 identical and not replay attack */ if (!soap_wsse_session_verify(soap, HA1, token->wsu__Created, token->Nonce)) return SOAP_OK; return soap->error; } } } else { /* check password text */ if (!strcmp(token->Password->__item, password)) return SOAP_OK; } } return soap_wsse_fault(soap, wsse__FailedAuthentication, "Authentication required");}/******************************************************************************\ * * wsse:Security/BinarySecurityToken header element *\******************************************************************************//**@fn int soap_wsse_add_BinarySecurityToken(struct soap *soap, const char *id, const char *valueType, const unsigned char *data, int size)@brief Adds BinarySecurityToken element.@param soap context@param[in] id string for signature referencing or NULL@param[in] valueType string@param[in] data points to binary token data@param[in] size is length of binary token@return SOAP_OK*/intsoap_wsse_add_BinarySecurityToken(struct soap *soap, const char *id, const char *valueType, const unsigned char *data, int size){ _wsse__Security *security = soap_wsse_add_Security(soap); DBGFUN2("wsse_add_BinarySecurityToken", "id=%s", id?id:"", "valueType=%s", valueType?valueType:""); /* allocate BinarySecurityToken if we don't already have one */ if (!security->BinarySecurityToken) security->BinarySecurityToken = (_wsse__BinarySecurityToken*)soap_malloc(soap, sizeof(_wsse__BinarySecurityToken)); soap_default__wsse__BinarySecurityToken(soap, security->BinarySecurityToken); /* populate the BinarySecurityToken */ security->BinarySecurityToken->wsu__Id = soap_strdup(soap, id); security->BinarySecurityToken->ValueType = soap_strdup(soap, valueType); security->BinarySecurityToken->EncodingType = (char*)wsse_Base64BinaryURI; security->BinarySecurityToken->__item = soap_s2base64(soap, data, NULL, size); return SOAP_OK;}/**@fn int soap_wsse_add_BinarySecurityTokenX509(struct soap *soap, const char *id, X509 *cert)@brief Adds BinarySecurityToken element with X509 certificate.@param soap context@param[in] id string for signature reference@param[in] cert points to the X509 certificate@return SOAP_OK or SOAP_EOMThis function uses i2d_X509 from the the OpenSSL library to convert an X509object to binary DER format.*/intsoap_wsse_add_BinarySecurityTokenX509(struct soap *soap, const char *id, X509 *cert){ int size; unsigned char *data, *next; if (!cert) return soap_wsse_fault(soap, wsse__InvalidSecurityToken, "Invalid certificate"); /* determine the storage requirement */ size = i2d_X509(cert, NULL); if (size < 0) return soap_wsse_fault(soap, wsse__InvalidSecurityToken, "Invalid certificate"); /* use the gSOAP engine's look-aside buffer to temporarily hold the cert */ if (soap_store_lab(soap, NULL, size)) return SOAP_EOM; data = next = (unsigned char*)soap->labbuf; /* store in DER format */ i2d_X509(cert, &next); /* populate the BinarySecurityToken with base64 certificate data */ return soap_wsse_add_BinarySecurityToken(soap, id, wsse_X509v3URI, data, size);}/**@fn int soap_wsse_add_BinarySecurityTokenPEM(struct soap *soap, const char *id, const char *filename)@brief Adds BinarySecurityToken element from a PEM file.@param soap context@param[in] id string for signature reference@param[in] filename@return SOAP_OK or SOAP_FAULT with wsse__InvalidSecurity fault when file cannot be read or does not contain a valid certificateThis function uses PEM_read_X509 from the the OpenSSL library to read acertificate from a PEM formatted file.*/intsoap_wsse_add_BinarySecurityTokenPEM(struct soap *soap, const char *id, const char *filename){ FILE *fd; DBGFUN2("soap_wsse_add_BinarySecurityTokenPEM", "id=%s", id?id:"", "filename=%s", filename?filename:""); if ((fd = fopen(filename, "r"))) { /* read the certificate */ X509 *cert = PEM_read_X509(fd, NULL, NULL, NULL); fclose(fd); /* if okay, populate the BinarySecurityToken element */ if (cert) { int err = soap_wsse_add_BinarySecurityTokenX509(soap, id, cert); X509_free(cert); return err; } } return soap_wsse_fault(soap, wsse__InvalidSecurity, "No certificate");}/**@fn _wsse__BinarySecurityToken* soap_wsse_BinarySecurityToken(struct soap *soap, const char *id)@brief Returns BinarySecurityToken element if present.@param soap context@param[in] id string of token to get or NULL@return _wsse__BinarySecurityToken object or NULL*/struct _wsse__BinarySecurityToken*soap_wsse_BinarySecurityToken(struct soap *soap, const char *id){ _wsse__Security *security = soap_wsse_Security(soap); if (security && security->BinarySecurityToken && (!id || (security->BinarySecurityToken->wsu__Id && !strcmp(security->BinarySecurityToken->wsu__Id, id)))) return security->BinarySecurityToken; return NULL;}/**@fn int soap_wsse_get_BinarySecurityToken(struct soap *soap, const char *id, char **valueType, unsigned char **data, int *size)@brief Get wsse:BinarySecurityToken element token data in binary form.@param soap context@param[in] id string of token to get or NULL@param[out] valueType string@param[out] data points to binary token data@param[out] size is length of binary token@return SOAP_OK or SOAP_FAULT with wsse:SecurityTokenUnavailable fault*/intsoap_wsse_get_BinarySecurityToken(struct soap *soap, const char *id, char **valueType, unsigned char **data, int *size){ _wsse__BinarySecurityToken *token = soap_wsse_BinarySecurityToken(soap, id); DBGFUN1("soap_wsse_get_BinarySecurityToken", "id=%s", id?id:""); if (token) { *valueType = token->ValueType; /* it appears we don't need HexBinary after all if (token->EncodingType && !strcmp(token->EncodingType, wsse_HexBinaryURI)) *data = (unsigned char*)soap_hex2s(soap, token->__item, NULL, 0, size); else */ /* assume token is represented in base64 by default */ *data = (unsigned char*)soap_base642s(soap, token->__item, NULL, 0, size); if (*data) return SOAP_OK; } return soap_wsse_fault(soap, wsse__SecurityTokenUnavailable, "BinarySecurityToken required");}/**@fn X509* soap_wsse_get_BinarySecurityTokenX509(struct soap *soap, const char *id)@brief Get X509 wsse:BinarySecurityToken certificate and verify its content.@param soap context@param[in] id string of token to get or NULL@return X509 certificate (dynamically allocated) or NULL with wsse:SecurityTokenUnavailable fault*/X509*soap_wsse_get_BinarySecurityTokenX509(struct soap *soap, const char *id){ X509 *cert = NULL; char *valueType; unsigned char *data; int size; DBGFUN1("soap_wsse_get_BinarySecurityTokenX509", "id=%s", id?id:""); if (!soap_wsse_get_BinarySecurityToken(soap, id, &valueType, &data, &size) && valueType && !strcmp(valueType, wsse_X509v3URI)) cert = d2i_X509(NULL, (unsigned char**)&data, size); /* verify the certificate */ if (!cert || soap_wsse_verify_X509(soap, cert)) return NULL; return cert;}/**@fn int soap_wsse_verify_X509(struct soap *soap, X509 *cert)@brief Verifies X509 certificate against soap->cafile, soap->capath, and soap->crlfile@param soap context@param[in] cert X509 certificate@return SOAP_OK or faultThis is an expensive operation. Whenever a new soap context is created, thecafile and objects are loaded into that context each time we need to verify acertificate.*/int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -