soap_dom_iterator &soap_dom_iterator::operator++() { while (this->elt) { if (this->elt->elts) this->elt = elt->elts; else if (this->elt->next) this->elt = this->elt->next; else { do this->elt = this->elt->prnt; while (this->elt && !this->elt->next); if (this->elt) this->elt = this->elt->next; if (!this->elt) break; } if (this->name && this->elt->name) { if (!soap_tag_cmp(this->elt->name, this->name)) { if (this->nstr && this->elt->nstr) { if (!soap_tag_cmp(this->elt->nstr, this->nstr)) break; } else break; } } else if (this->type) { if (this->elt->type == this->type) break; } else break; } return *this; }
soap_dom_attribute_iterator soap_dom_attribute::find(const char *nstr, const char *name) { soap_dom_attribute_iterator iter(this); iter.nstr = nstr; iter.name = name; if (name && soap_tag_cmp(this->name, name)) return ++iter; if (nstr && this->nstr && soap_tag_cmp(this->nstr, nstr)) return ++iter; return iter; }
static int http_da_parse_header(struct soap *soap, const char *key, const char *val) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; /* check if server received Authorization Digest HTTP header from client */ if (!soap_tag_cmp(key, "Authorization") && !soap_tag_cmp(val, "Digest *")) { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "realm")); soap->userid = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "username")); soap->passwd = NULL; data->nonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nonce")); data->opaque = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "opaque")); data->qop = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "qop")); data->alg = NULL; data->ncount = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nc")); data->cnonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "cnonce")); data->response = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "response")); if (data->qop && !soap_tag_cmp(data->qop, "auth-int")) { if (soap->fpreparerecv != http_da_preparerecv) { data->fpreparerecv = soap->fpreparerecv; soap->fpreparerecv = http_da_preparerecv; } if (soap->fdisconnect != http_da_disconnect) { data->fdisconnect = soap->fdisconnect; soap->fdisconnect = http_da_disconnect; } md5_handler(soap, &data->context, MD5_INIT, NULL, 0); } return SOAP_OK; } /* check if client received WWW-Authenticate Digest HTTP header from server */ if (!soap_tag_cmp(key, "WWW-Authenticate") && !soap_tag_cmp(val, "Digest *")) { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "realm")); data->nonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nonce")); data->opaque = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "opaque")); data->qop = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "qop")); data->alg = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "algorithm")); data->nc = 1; data->ncount = NULL; data->cnonce = NULL; data->response = NULL; return SOAP_OK; } return data->fparsehdr(soap, key, val); }
static int http_da_parse_header(struct soap *soap, const char *key, const char *val) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; /* check if server received Authorization Digest HTTP header from client */ if (!soap_tag_cmp(key, "Authorization") && !soap_tag_cmp(val, "Digest *")) { data->alg = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "algorithm")); soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "realm")); soap->userid = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "username")); soap->passwd = NULL; data->nonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nonce")); data->opaque = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "opaque")); data->qop = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "qop")); data->ncount = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nc")); data->cnonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "cnonce")); (void)soap_hex2s(soap, soap_get_header_attribute(soap, val + 7, "response"), data->response, 32, NULL); return SOAP_OK; } /* check if client received WWW-Authenticate Digest HTTP header from server */ if ((!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate")) && !soap_tag_cmp(val, "Digest *")) { const char *authrealm = soap_get_header_attribute(soap, val + 7, "realm"); if (authrealm && (!soap->authrealm || strcmp(authrealm, soap->authrealm))) { const char *alg; soap->authrealm = soap_strdup(soap, authrealm); alg = soap_get_header_attribute(soap, val + 7, "algorithm"); if (!alg || soap_tag_cmp(alg, "SHA-512-256*")) { /* got the first authenticate header for this realm that we can accept */ data->alg = soap_strdup(soap, alg); data->nonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nonce")); data->opaque = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "opaque")); data->qop = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "qop")); data->nc = 1; data->ncount = NULL; data->cnonce = NULL; } else { soap->authrealm = NULL; } } return SOAP_OK; } return data->fparsehdr(soap, key, val); }
static int http_da_parse(struct soap *soap) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; data->qop = NULL; /* HTTP GET w/o body with qop=auth-int still requires a digest */ if (soap_smd_init(soap, &data->smd_data, SOAP_SMD_DGST_MD5, NULL, 0) || soap_smd_final(soap, &data->smd_data, data->digest, NULL)) return soap->error; if ((soap->error = data->fparse(soap))) return soap->error; if (data->qop && !soap_tag_cmp(data->qop, "auth-int")) { if (soap->fpreparerecv != http_da_preparerecv) { data->fpreparerecv = soap->fpreparerecv; soap->fpreparerecv = http_da_preparerecv; } if (soap->fpreparefinalrecv != http_da_preparefinalrecv) { data->fpreparefinalrecv = soap->fpreparefinalrecv; soap->fpreparefinalrecv = http_da_preparefinalrecv; } if (soap_smd_init(soap, &data->smd_data, SOAP_SMD_DGST_MD5, NULL, 0)) return soap->error; } return SOAP_OK; }
static void http_da_calc_HA1(struct soap *soap, void **context, char *alg, char *userid, char *realm, char *passwd, char *nonce, char *cnonce, char HA1hex[33]) { char HA1[16]; md5_handler(soap, context, MD5_INIT, NULL, 0); md5_handler(soap, context, MD5_UPDATE, userid, strlen(userid)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, realm, strlen(realm)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, passwd, strlen(passwd)); md5_handler(soap, context, MD5_FINAL, HA1, 0); if (alg && !soap_tag_cmp(alg, "MD5-sess")) { md5_handler(soap, context, MD5_INIT, NULL, 0); md5_handler(soap, context, MD5_UPDATE, HA1, 16); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, nonce, strlen(nonce)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, cnonce, strlen(cnonce)); md5_handler(soap, context, MD5_FINAL, HA1, 0); }; soap_s2hex(soap, (unsigned char*)HA1, HA1hex, 16); };
static int http_post_parse_header(struct soap *soap, const char *key, const char *val) { struct http_post_data *data = (struct http_post_data*)soap_lookup_plugin(soap, http_post_id); if (!data) return SOAP_PLUGIN_ERROR; soap->error = data->fparsehdr(soap, key, val); /* parse HTTP header */ if (soap->error == SOAP_OK) { if (!soap_tag_cmp(key, "Content-Type")) { /* check content type: you can filter any type of payloads here */ if (!soap_tag_cmp(val, "application/x-www-form-urlencoded")) soap->error = SOAP_FORM; /* delegate body parsing to handler */ else if (!soap_tag_cmp(val, "image/*")) soap->error = SOAP_FORM; /* delegate images of any type */ } } return soap->error; }
static int http_da_parse(struct soap *soap) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; data->qop = NULL; /* HTTP GET w/o body with qop=auth-int still requires a digest */ md5_handler(soap, &data->context, MD5_INIT, NULL, 0); md5_handler(soap, &data->context, MD5_FINAL, data->digest, 0); if ((soap->error = data->fparse(soap))) return soap->error; if (data->qop && !soap_tag_cmp(data->qop, "auth-int")) { if (soap->fpreparerecv != http_da_preparerecv) { data->fpreparerecv = soap->fpreparerecv; soap->fpreparerecv = http_da_preparerecv; } if (soap->fpreparefinalrecv != http_da_preparefinalrecv) { data->fpreparefinalrecv = soap->fpreparefinalrecv; soap->fpreparefinalrecv = http_da_preparefinalrecv; } md5_handler(soap, &data->context, MD5_INIT, NULL, 0); } return SOAP_OK; }
static int http_da_calc_HA1(struct soap *soap, struct soap_smd_data *smd_data, const char *alg, const char *userid, const char *realm, const char *passwd, const char *nonce, const char *cnonce, char HA1hex[65]) { int smd_alg = SOAP_SMD_DGST_MD5; size_t smd_len = 16; char HA1[32]; if (alg && !soap_tag_cmp(alg, "SHA-256*")) { smd_alg = SOAP_SMD_DGST_SHA256; smd_len = 32; } if (soap_smd_init(soap, smd_data, smd_alg, NULL, 0) || soap_smd_update(soap, smd_data, userid, strlen(userid)) || soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, realm, strlen(realm)) || soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, passwd, strlen(passwd)) || soap_smd_final(soap, smd_data, HA1, NULL)) return soap->error; if (alg && !soap_tag_cmp(alg, "*-sess")) { if (soap_smd_init(soap, smd_data, smd_alg, NULL, 0) || soap_smd_update(soap, smd_data, HA1, smd_len)) return soap->error; if (nonce) { if (soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, nonce, strlen(nonce))) return soap->error; } if (soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, cnonce, strlen(cnonce)) || soap_smd_final(soap, smd_data, HA1, NULL)) return soap->error; } (void)soap_s2hex(soap, (unsigned char*)HA1, HA1hex, smd_len); return SOAP_OK; };
static http_handler_t http_lookup_handler(struct soap *soap, const char *type, struct http_post_data *data) { struct http_post_handlers *p; for (p = data->handlers; p && p->type; p++) { if (!soap_tag_cmp(type, p->type)) { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Found HTTP POST plugin handler for '%s'\n", type)); return p->handler; } } return NULL; }
soap_dom_attribute_iterator &soap_dom_attribute_iterator::operator++() { while (att) { att = soap_dom_next_attribute(att); if (!att) break; if (name && att->name) { if (!soap_tag_cmp(att->name, name)) { if (nstr && att->nstr) { if (!soap_tag_cmp(att->nstr, nstr)) break; } else break; } } else break; } return *this; }
static int http_form_parse_header(struct soap *soap, const char *key, const char *val) { struct http_form_data *data = (struct http_form_data*)soap_lookup_plugin(soap, http_form_id); if (!data) return SOAP_PLUGIN_ERROR; soap->error = data->fparsehdr(soap, key, val); /* parse HTTP header */ if (soap->error == SOAP_OK) { if (!soap_tag_cmp(key, "Content-Type")) { /* check content type: you can filter any type of payloads here */ if (!soap_tag_cmp(val, "application/x-www-form-urlencoded")) { soap->fform = data->handler; soap->error = SOAP_FORM; /* delegate body parsing to form handler */ } /* it is possible to add other payload types to handle via forms if (!soap_tag_cmp(val, "image/jpg")) soap->error = SOAP_FORM; */ } } return soap->error; }
static int http_da_parse_header(struct soap *soap, const char *key, const char *val) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; /* check if server received Authorization Digest HTTP header from client */ if (!soap_tag_cmp(key, "Authorization") && !soap_tag_cmp(val, "Digest *")) { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "realm")); soap->userid = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "username")); soap->passwd = NULL; data->nonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nonce")); data->opaque = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "opaque")); data->qop = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "qop")); data->alg = NULL; data->ncount = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nc")); data->cnonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "cnonce")); data->response = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "response")); return SOAP_OK; } /* check if client received WWW-Authenticate Digest HTTP header from server */ if ((!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate")) && !soap_tag_cmp(val, "Digest *")) { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "realm")); data->nonce = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "nonce")); data->opaque = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "opaque")); data->qop = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "qop")); data->alg = soap_strdup(soap, soap_get_header_attribute(soap, val + 7, "algorithm")); data->nc = 1; data->ncount = NULL; data->cnonce = NULL; data->response = NULL; return SOAP_OK; } return data->fparsehdr(soap, key, val); }
static int http_da_verify_method(struct soap *soap, const char *method, const char *passwd) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); char HA1hex[65], entityHAhex[65], response[65], responseHA[32]; size_t smd_len = 16; if (!data) return SOAP_ERR; if (data->alg && !soap_tag_cmp(data->alg, "SHA-256*")) smd_len = 32; /* reject if none or basic authentication was used */ if (!soap->authrealm || !soap->userid || soap->passwd) /* passwd is set when basic auth is used */ return SOAP_ERR; /* require at least qop="auth" to prevent replay attacks */ if (!data->qop) return SOAP_ERR; if (http_da_session_update(soap->authrealm, data->nonce, data->opaque, data->cnonce, data->ncount)) return SOAP_ERR; if (http_da_calc_HA1(soap, &data->smd_data, data->alg, soap->userid, soap->authrealm, passwd, data->nonce, data->cnonce, HA1hex)) return soap->error; if (!soap_tag_cmp(data->qop, "auth-int")) (void)soap_s2hex(soap, (unsigned char*)data->digest, entityHAhex, smd_len); if (http_da_calc_response(soap, &data->smd_data, data->alg, HA1hex, data->nonce, data->ncount, data->cnonce, data->qop, method, soap->path, entityHAhex, response, responseHA)) return soap->error; /* check digest response values */ if (memcmp(data->response, responseHA, smd_len)) return SOAP_ERR; return SOAP_OK; }
int soap_s2decimal(struct soap *soap, const char *s, long double *p) { if (s) { if (!*s) return soap->error = SOAP_TYPE; if (!soap_tag_cmp(s, "INF")) *p = (long double)DBL_PINFTY; else if (!soap_tag_cmp(s, "+INF")) *p = (long double)DBL_PINFTY; else if (!soap_tag_cmp(s, "-INF")) *p = (long double)DBL_NINFTY; else if (!soap_tag_cmp(s, "NaN")) *p = (long double)DBL_NAN; else { #if defined(WITH_C_LOCALE) && defined(HAVE_STRTOLD_L) char *r; # ifdef WIN32 *p = _strtold_l(s, &r, SOAP_LOCALE(soap)); # else *p = strtold_l(s, &r, SOAP_LOCALE(soap)); # endif if (*r) #elif defined(HAVE_STRTOLD) char *r; *p = strtold(s, &r); if (*r) #endif #if defined(WITH_C_LOCALE) && defined(HAVE_SSCANF_L) if (sscanf_l(s, SOAP_LOCALE(soap), "%Lg", p) != 1) soap->error = SOAP_TYPE; #elif defined(HAVE_SSCANF) if (sscanf(s, "%Lg", p) != 1) soap->error = SOAP_TYPE; #else soap->error = SOAP_TYPE; #endif } } return soap->error; }
int http_get(struct soap *soap) { int retCode = 404; FILE *fd = fopen(soap->path + 1, "rb"); if (fd != NULL) { if (!soap_tag_cmp(soap->path, "*.html")) soap->http_content = "text/html"; if (!soap_tag_cmp(soap->path, "*.wsdl")) soap->http_content = "text/xml"; soap_response(soap, SOAP_FILE); for (;;) { size_t r = fread(soap->tmpbuf, 1, sizeof(soap->tmpbuf), fd); if ( (r == 0) || (soap_send_raw(soap, soap->tmpbuf, r)) ) break; } fclose(fd); soap_end_send(soap); retCode = SOAP_OK; } return retCode; }
static int http_md5_parse_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); if (!data) return SOAP_PLUGIN_ERROR; if (!soap_tag_cmp(key, "Content-MD5")) { soap_base642s(soap, val, data->digest, 16, NULL); data->fpreparerecv = soap->fpreparerecv; soap->fpreparerecv = http_md5_preparerecv; data->fdisconnect = soap->fdisconnect; soap->fdisconnect = http_md5_disconnect; return SOAP_OK; } return data->fparsehdr(soap, key, val); }
soap_dom_element_iterator &soap_dom_element_iterator::operator++() { while (elt) { elt = soap_dom_next_element(elt); if (!elt) break; if (name && elt->name) { if (!soap_tag_cmp(elt->name, name)) { if (nstr && elt->nstr) { if (!soap_tag_cmp(elt->nstr, nstr)) break; } else break; } } else if (type) { if (elt->type == type) break; } else break; } return *this; }
static int http_post_parse_header(struct soap *soap, const char *key, const char *val) { struct http_post_data *data = (struct http_post_data*)soap_lookup_plugin(soap, http_post_id); if (!data) return SOAP_PLUGIN_ERROR; soap->error = data->fparsehdr(soap, key, val); /* parse HTTP header */ if (soap->error == SOAP_OK) { if (!soap_tag_cmp(key, "Content-Type")) { /* check content type */ soap->fform = http_lookup_handler(soap, val, data); if (!soap->fform) soap->fform = http_lookup_handler(soap, "POST", data); if (soap->fform) return SOAP_FORM; /* calls soap->fform after processing the HTTP header */ } } return soap->error; }
static void http_da_calc_response(struct soap *soap, void **context, char HA1hex[33], const char *nonce, const char *ncount, const char *cnonce, const char *qop, const char *method, const char *uri, char entityHAhex[33], char response[33]) { char HA2[16], HA2hex[33], responseHA[16]; md5_handler(soap, context, MD5_INIT, NULL, 0); md5_handler(soap, context, MD5_UPDATE, (char*)method, strlen(method)); md5_handler(soap, context, MD5_UPDATE, (char*)":", 1); md5_handler(soap, context, MD5_UPDATE, (char*)uri, strlen(uri)); if (qop && !soap_tag_cmp(qop, "auth-int")) { md5_handler(soap, context, MD5_UPDATE, (char*)":", 1); md5_handler(soap, context, MD5_UPDATE, entityHAhex, 32); } md5_handler(soap, context, MD5_FINAL, HA2, 0); soap_s2hex(soap, (unsigned char*)HA2, HA2hex, 16); md5_handler(soap, context, MD5_INIT, NULL, 0); md5_handler(soap, context, MD5_UPDATE, HA1hex, 32); if (nonce) { md5_handler(soap, context, MD5_UPDATE, (char*)":", 1); md5_handler(soap, context, MD5_UPDATE, (char*)nonce, strlen(nonce)); } md5_handler(soap, context, MD5_UPDATE, (char*)":", 1); if (qop && *qop) { md5_handler(soap, context, MD5_UPDATE, (char*)ncount, strlen(ncount)); md5_handler(soap, context, MD5_UPDATE, (char*)":", 1); md5_handler(soap, context, MD5_UPDATE, (char*)cnonce, strlen(cnonce)); md5_handler(soap, context, MD5_UPDATE, (char*)":", 1); md5_handler(soap, context, MD5_UPDATE, (char*)qop, strlen(qop)); md5_handler(soap, context, MD5_UPDATE, (char*)":", 1); } md5_handler(soap, context, MD5_UPDATE, HA2hex, 32); md5_handler(soap, context, MD5_FINAL, responseHA, 0); soap_s2hex(soap, (unsigned char*)responseHA, response, 16); }
static int http_da_verify_method(struct soap *soap, char *method, char *passwd) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); char HA1[33], entityHAhex[33], response[33]; if (!data) return SOAP_ERR; /* reject if none or basic authentication was used */ if (!soap->authrealm || !soap->userid || soap->passwd) /* passwd is set when basic auth is used */ return SOAP_ERR; /* require at least qop="auth" to prevent replay attacks */ if (!data->qop) return SOAP_ERR; if (http_da_session_update(soap->authrealm, data->nonce, data->opaque, data->cnonce, data->ncount)) return SOAP_ERR; http_da_calc_HA1(soap, &data->context, NULL, soap->userid, soap->authrealm, passwd, data->nonce, data->cnonce, HA1); if (!soap_tag_cmp(data->qop, "auth-int")) soap_s2hex(soap, (unsigned char*)data->digest, entityHAhex, 16); http_da_calc_response(soap, &data->context, HA1, data->nonce, data->ncount, data->cnonce, data->qop, method, soap->path, entityHAhex, response); #ifdef SOAP_DEBUG fprintf(stderr, "Debug message: verifying client response=%s with calculated digest=%s\n", data->response, response); #endif /* check digest response values */ if (strcmp(data->response, response)) return SOAP_ERR; return SOAP_OK; }
static int http_da_post_header(struct soap *soap, const char *key, const char *val) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; /* client's HTTP Authorization request */ if (key && (!strcmp(key, "Authorization") || !strcmp(key, "Proxy-Authorization"))) { char HA1hex[65], entityHAhex[65], response[65], responseHA[32]; char cnonce[HTTP_DA_NONCELEN]; char ncount[9]; const char *qop, *method; const char *userid = (*key == 'A' ? soap->userid : soap->proxy_userid); const char *passwd = (*key == 'A' ? soap->passwd : soap->proxy_passwd); size_t smd_len = 16; if (data->alg && !soap_tag_cmp(data->alg, "SHA-256*")) smd_len = 32; if (soap_smd_final(soap, &data->smd_data, data->digest, NULL)) return soap->error; if (!userid || !passwd || !soap->authrealm || !data->nonce) { #ifdef SOAP_DEBUG fprintf(stderr, "Debug message: authentication header construction failed, missing some of the authentication data!\n"); #endif return SOAP_OK; } http_da_calc_nonce(soap, cnonce); if (http_da_calc_HA1(soap, &data->smd_data, data->alg, userid, soap->authrealm, passwd, data->nonce, cnonce, HA1hex)) return soap->error; if (soap->status != SOAP_GET && soap->status != SOAP_CONNECT && data->qop && !soap_tag_cmp(data->qop, "*auth-int*")) { qop = "auth-int"; (void)soap_s2hex(soap, (unsigned char*)data->digest, entityHAhex, smd_len); } else if (data->qop) qop = "auth"; else qop = NULL; if (soap->status == SOAP_GET) method = "GET"; else if (soap->status == SOAP_CONNECT) method = "CONNECT"; else method = "POST"; (SOAP_SNPRINTF(ncount, sizeof(ncount), 8), "%8.8lx", data->nc++); if (http_da_calc_response(soap, &data->smd_data, data->alg, HA1hex, data->nonce, ncount, cnonce, qop, method, soap->path, entityHAhex, response, responseHA)) return soap->error; (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->authrealm) + strlen(userid) + strlen(data->nonce) + strlen(soap->path) + strlen(ncount) + strlen(cnonce) + strlen(response) + 75), "Digest algorithm=%s, realm=\"%s\", username=\"%s\", nonce=\"%s\", uri=\"%s\", nc=%s, cnonce=\"%s\", response=\"%s\"", data->alg ? data->alg : "MD5", soap->authrealm, userid, data->nonce, soap->path, ncount, cnonce, response); if (data->opaque) { size_t l = strlen(soap->tmpbuf); (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(data->opaque) + 11), ", opaque=\"%s\"", data->opaque); } if (qop) { size_t l = strlen(soap->tmpbuf); (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(qop) + 8), ", qop=\"%s\"", qop); } return data->fposthdr(soap, key, soap->tmpbuf); } /* server's HTTP Authorization challenge/response */ if (key && (!strcmp(key, "WWW-Authenticate") || !strcmp(key, "Proxy-Authenticate"))) { static const char *algos[] = { "MD5", "MD5-sess", "SHA-256", "SHA-256-sess", "SHA-512-256", "SHA-512-256-sess" }; const char *alg = algos[data->option]; char nonce[HTTP_DA_NONCELEN]; char opaque[HTTP_DA_OPAQUELEN]; http_da_calc_nonce(soap, nonce); http_da_calc_opaque(soap, opaque); http_da_session_start(soap->authrealm, nonce, opaque); if (data->option > 0) { (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->authrealm) + strlen(nonce) + strlen(opaque) + 59), "Digest algorithm=%s, realm=\"%s\", qop=\"auth,auth-int\", nonce=\"%s\", opaque=\"%s\"", alg, soap->authrealm, nonce, opaque); if (data->fposthdr(soap, key, soap->tmpbuf)) return soap->error; } (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->authrealm) + strlen(nonce) + strlen(opaque) + 59), "Digest algorithm=MD5, realm=\"%s\", qop=\"auth,auth-int\", nonce=\"%s\", opaque=\"%s\"", soap->authrealm, nonce, opaque); return data->fposthdr(soap, key, soap->tmpbuf); } return data->fposthdr(soap, key, val); }
static int http_da_post_header(struct soap *soap, const char *key, const char *val) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; /* client's HTTP Authorization response */ if (key && !strcmp(key, "Authorization")) { char HA1[33], entityHAhex[33], response[33]; char cnonce[HTTP_DA_NONCELEN]; char ncount[9]; char *qop, *method; md5_handler(soap, &data->context, MD5_FINAL, data->digest, 0); http_da_calc_nonce(soap, cnonce); http_da_calc_HA1(soap, &data->context, data->alg, soap->userid, soap->authrealm, soap->passwd, data->nonce, cnonce, HA1); if (data->qop && !soap_tag_cmp(data->qop, "*auth-int*")) { qop = "auth-int"; soap_s2hex(soap, (unsigned char*)data->digest, entityHAhex, 16); } else if (data->qop) qop = "auth"; else qop = NULL; if (soap->status == SOAP_GET) method = "GET"; else method = "POST"; sprintf(ncount, "%8.8lx", data->nc++); http_da_calc_response(soap, &data->context, HA1, data->nonce, ncount, cnonce, qop, method, soap->path, entityHAhex, response); sprintf(soap->tmpbuf, "Digest realm=\"%s\", username=\"%s\", nonce=\"%s\", uri=\"%s\", nc=%s, cnonce=\"%s\", response=\"%s\"", soap->authrealm, soap->userid, data->nonce, soap->path, ncount, cnonce, response); if (data->opaque) sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ", opaque=\"%s\"", data->opaque); if (qop) sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ", qop=\"%s\"", qop); return data->fposthdr(soap, key, soap->tmpbuf); } /* server's HTTP Authorization response */ if (key && !strcmp(key, "WWW-Authenticate")) { char nonce[HTTP_DA_NONCELEN]; char opaque[HTTP_DA_OPAQUELEN]; http_da_calc_nonce(soap, nonce); http_da_calc_opaque(soap, opaque); http_da_session_start(soap->authrealm, nonce, opaque); sprintf(soap->tmpbuf, "Digest realm=\"%s\", qop=\"auth,auth-int\", nonce=\"%s\", opaque=\"%s\"", soap->authrealm, nonce, opaque); return data->fposthdr(soap, key, soap->tmpbuf); } return data->fposthdr(soap, key, val); }
static int http_da_post_header(struct soap *soap, const char *key, const char *val) { struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; /* client's HTTP Authorization request */ if (key && (!strcmp(key, "Authorization") || !strcmp(key, "Proxy-Authorization"))) { char HA1[33], entityHAhex[33], response[33]; char cnonce[HTTP_DA_NONCELEN]; char ncount[9]; const char *qop, *method; const char *userid = (*key == 'A' ? soap->userid : soap->proxy_userid); const char *passwd = (*key == 'A' ? soap->passwd : soap->proxy_passwd); md5_handler(soap, &data->context, MD5_FINAL, data->digest, 0); if (!userid || !passwd || !soap->authrealm || !data->nonce) { #ifdef SOAP_DEBUG fprintf(stderr, "Debug message: authentication header failed, missing authentication data\n"); #endif return SOAP_OK; } http_da_calc_nonce(soap, cnonce); http_da_calc_HA1(soap, &data->context, data->alg, userid, soap->authrealm, passwd, data->nonce, cnonce, HA1); if (data->qop && !soap_tag_cmp(data->qop, "*auth-int*")) { qop = "auth-int"; soap_s2hex(soap, (unsigned char*)data->digest, entityHAhex, 16); } else if (data->qop) qop = "auth"; else qop = NULL; if (soap->status == SOAP_GET) method = "GET"; else if (soap->status == SOAP_CONNECT) method = "CONNECT"; else method = "POST"; #ifdef HAVE_SNPRINTF soap_snprintf(ncount, sizeof(ncount), "%8.8lx", data->nc++); #else sprintf(ncount, "%8.8lx", data->nc++); #endif http_da_calc_response(soap, &data->context, HA1, data->nonce, ncount, cnonce, qop, method, soap->path, entityHAhex, response); #ifdef HAVE_SNPRINTF soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "Digest realm=\"%s\", username=\"%s\", nonce=\"%s\", uri=\"%s\", nc=%s, cnonce=\"%s\", response=\"%s\"", soap->authrealm, userid, data->nonce, soap->path, ncount, cnonce, response); #else sprintf(soap->tmpbuf, "Digest realm=\"%s\", username=\"%s\", nonce=\"%s\", uri=\"%s\", nc=%s, cnonce=\"%s\", response=\"%s\"", soap->authrealm, userid, data->nonce, soap->path, ncount, cnonce, response); #endif if (data->opaque) #ifdef HAVE_SNPRINTF soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), ", opaque=\"%s\"", data->opaque); #else sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ", opaque=\"%s\"", data->opaque); #endif if (qop) #ifdef HAVE_SNPRINTF soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), ", qop=\"%s\"", qop); #else sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ", qop=\"%s\"", qop); #endif return data->fposthdr(soap, key, soap->tmpbuf); } /* server's HTTP Authorization challenge/response */ if (key && (!strcmp(key, "WWW-Authenticate") || !strcmp(key, "Proxy-Authenticate"))) { char nonce[HTTP_DA_NONCELEN]; char opaque[HTTP_DA_OPAQUELEN]; http_da_calc_nonce(soap, nonce); http_da_calc_opaque(soap, opaque); http_da_session_start(soap->authrealm, nonce, opaque); #ifdef HAVE_SNPRINTF soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "Digest realm=\"%s\", qop=\"auth,auth-int\", nonce=\"%s\", opaque=\"%s\"", soap->authrealm, nonce, opaque); #else sprintf(soap->tmpbuf, "Digest realm=\"%s\", qop=\"auth,auth-int\", nonce=\"%s\", opaque=\"%s\"", soap->authrealm, nonce, opaque); #endif return data->fposthdr(soap, key, soap->tmpbuf); } return data->fposthdr(soap, key, val); }
static int http_da_calc_response(struct soap *soap, struct soap_smd_data *smd_data, const char *alg, char HA1hex[65], const char *nonce, const char *ncount, const char *cnonce, const char *qop, const char *method, const char *uri, char entityHAhex[65], char response[65], char responseHA[32]) { int smd_alg = SOAP_SMD_DGST_MD5; size_t smd_len = 16; char HA2[32], HA2hex[65]; if (alg && !soap_tag_cmp(alg, "SHA-256*")) { smd_alg = SOAP_SMD_DGST_SHA256; smd_len = 32; } if (soap_smd_init(soap, smd_data, smd_alg, NULL, 0) || soap_smd_update(soap, smd_data, method, strlen(method)) || soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, uri, strlen(uri))) return soap->error; if (qop && !soap_tag_cmp(qop, "auth-int")) { if (soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, entityHAhex, 2*smd_len)) return soap->error; } if (soap_smd_final(soap, smd_data, HA2, NULL)) return soap->error; (void)soap_s2hex(soap, (unsigned char*)HA2, HA2hex, smd_len); if (soap_smd_init(soap, smd_data, smd_alg, NULL, 0) || soap_smd_update(soap, smd_data, HA1hex, 2*smd_len)) return soap->error; if (nonce) { if (soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, nonce, strlen(nonce))) return soap->error; } if (qop && *qop) { if (soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, ncount, strlen(ncount)) || soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, cnonce, strlen(cnonce)) || soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, qop, strlen(qop))) return soap->error; } if (soap_smd_update(soap, smd_data, ":", 1) || soap_smd_update(soap, smd_data, HA2hex, 2*smd_len) || soap_smd_final(soap, smd_data, responseHA, NULL)) return soap->error; (void)soap_s2hex(soap, (unsigned char*)responseHA, response, smd_len); return SOAP_OK; }