/* Most of this function is taken from the function 'soap_wsse_add_UsernameTokenDigest()' defined in wsseapi.cpp // // Used to alter the soap request for an offset time (for authorization purposes - replay attack protection) */ int OnvifClientDevice::LocalAddUsernameTokenDigest(struct soap *soapOff,double cam_pc_offset) { string strUrl; string strUser; string strPass; if (this->GetUserPasswd(strUser, strPass) == false || this->GetUrl(strUrl) == false) { return SOAP_ERR; } /* start soap_wsse_add_UsernameTokenDigest; Taken from wsseapi.cpp*/ /* All of this is taken from the function soap_wsse_add_UsernameTokenDigest() defined in wsseapi.cpp */ _wsse__Security *security = soap_wsse_add_Security(soapOff); time_t now = time(NULL); now -= (time_t) cam_pc_offset; //offset so digest comes out correctly (synced times between cam and pc); const char *created = soap_dateTime2s(soapOff, now); char HA[SOAP_SMD_SHA1_SIZE], HABase64[29]; char nonce[20], *nonceBase64; /*start calc_nonce(soapOff, nonce); Taken from wsseapi.cpp */ time_t r = time(NULL); cout << "now time: " << r << endl; r -= (time_t) cam_pc_offset; //offset so digest comes out correctly (synced times between cam and pc); cout << "now time minus offset: " << r << endl; memcpy(nonce, &r, 4); for (int i = 4; i < 20; i += 4) { r = soap_random; memcpy(nonce + i, &r, 4); } /*end calc_nonce(soapOff, nonce); */ nonceBase64 = soap_s2base64(soapOff, (unsigned char*)nonce, NULL, 20); /* start calc_digest(soapOff, created, nonce, 20, strPass, HA); Taken from wsseapi.cpp */ struct soap_smd_data context; /* use smdevp engine */ soap_smd_init(soapOff, &context, SOAP_SMD_DGST_SHA1, NULL, 0); soap_smd_update(soapOff, &context, nonce, 20); soap_smd_update(soapOff, &context, created, strlen(created)); soap_smd_update(soapOff, &context, strPass.c_str(), strlen(strPass.c_str())); soap_smd_final(soapOff, &context, HA, NULL); /* end calc_digest(soapOff, created, nonce, 20, strPass, HA); */ soap_s2base64(soapOff, (unsigned char*)HA, HABase64, SOAP_SMD_SHA1_SIZE); /* populate the UsernameToken with digest */ soap_wsse_add_UsernameTokenText(soapOff, "Id", strUser.c_str(), 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(soapOff, created); /* end soap_wsse_add_UsernameTokenDigest */ return SOAP_OK; }
// Caller needs to free the returned pointer char* condor_base64_encode(const unsigned char *input, int length) { char *buff = NULL; if ( length < 1 ) { buff = (char *)malloc(1); buff[0] = '\0'; return buff; } int buff_len = (length+2)/3*4+1; buff = (char *)malloc(buff_len); ASSERT(buff); memset(buff,0,buff_len); struct soap soap; soap_init(&soap); soap_s2base64(&soap,input,buff,length); soap_destroy(&soap); soap_end(&soap); soap_done(&soap); return buff; }
static int http_md5_post_header(struct soap *soap, const char *key, const char *val) { struct http_md5_data *data = (struct http_md5_data*)soap_lookup_plugin(soap, http_md5_id); char buf64[25]; /* 24 base64 chars + '\0' */ int err; if (!data) return SOAP_PLUGIN_ERROR; if (!key) /* last line */ { if ((err = md5_handler(soap, &data->context, MD5_FINAL, data->digest, 0))) return err; data->fposthdr(soap, "Content-MD5", soap_s2base64(soap, (unsigned char*)data->digest, buf64, 16)); } return data->fposthdr(soap, key, val); }