const char *soap_xsd__duration2s(struct soap *soap, LONG64 a) { LONG64 d; int k, h, m, s, f; if (a < 0) { soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "-P"); k = 2; a = -a; } else { soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "P"); k = 1; } f = a % 1000; a /= 1000; s = a % 60; a /= 60; m = a % 60; a /= 60; h = a % 24; d = a / 24; if (d) (SOAP_SNPRINTF(soap->tmpbuf + k, sizeof(soap->tmpbuf) - k, 21), SOAP_LONG_FORMAT "D", d); if (h || m || s || f) { if (d) k = strlen(soap->tmpbuf); if (f) (SOAP_SNPRINTF(soap->tmpbuf + k, sizeof(soap->tmpbuf) - k, 14), "T%02dH%02dM%02d.%03dS", h, m, s, f); else (SOAP_SNPRINTF(soap->tmpbuf + k, sizeof(soap->tmpbuf) - k, 10), "T%02dH%02dM%02dS", h, m, s); } else if (!d) soap_strcpy(soap->tmpbuf + k, sizeof(soap->tmpbuf) - k, "T0S"); return soap->tmpbuf; }
const char *soap_decimal2s(struct soap *soap, long double n) { #if !defined(WITH_C_LOCALE) || !defined(HAVE_SPRINTF_L) char *s; #endif if (soap_isnan(n)) return "NaN"; if (soap_ispinfd(n)) return "INF"; if (soap_isninfd(n)) return "-INF"; #if defined(WITH_C_LOCALE) && defined(HAVE_SPRINTF_L) # ifdef WIN32 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), "%.*Lg", SOAP_LOCALE(soap), LDBL_DIG, n); # else sprintf_l(soap->tmpbuf, SOAP_LOCALE(soap), "%.*Lg", LDBL_DIG, n); # endif #else (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), LDBL_DIG + 8), "%.*Lg", LDBL_DIG, n); s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */ if (s) *s = '.'; #endif return soap->tmpbuf; }
const char *soap_xsd__dateTime2s(struct soap *soap, const struct timeval a) { size_t n; soap_dateTime2s(soap, a.tv_sec); /* assuming result is in tmpbuf! */ n = strlen(soap->tmpbuf); if (soap->tmpbuf[n-1] == 'Z') n--; (SOAP_SNPRINTF(soap->tmpbuf + n, sizeof(soap->tmpbuf) - n, 10), ".%.6dZ", a.tv_usec); return soap->tmpbuf; }
static int out_element(struct soap *soap, const struct soap_dom_element *node, const char *prefix, const char *name) { if (node->head && soap_send(soap, node->head)) return soap->error; if (node->type && node->node) { if (prefix && *prefix) { size_t l = strlen(prefix) + strlen(name); char *s = (char*)SOAP_MALLOC(soap, l + 2); if (!s) return soap->error = SOAP_EOM; (SOAP_SNPRINTF(s, l + 2, l + 1), "%s:%s", prefix, name); soap_putelement(soap, node->node, s, 0, node->type); SOAP_FREE(soap, s); } else return soap_putelement(soap, node->node, name, 0, node->type); } else if (prefix && *prefix) { size_t l = strlen(prefix) + strlen(name); char *s; if (l + 1 < sizeof(soap->msgbuf)) s = soap->msgbuf; else { s = (char*)SOAP_MALLOC(soap, l + 2); if (!s) return soap->error = SOAP_EOM; } (SOAP_SNPRINTF(s, l + 2, l + 1), "%s:%s", prefix, name); soap_element(soap, s, 0, NULL); /* element() */ if (s != soap->msgbuf) SOAP_FREE(soap, s); } else if (*name != '-') { soap_mode m = soap->mode; if ((soap->mode & SOAP_DOM_ASIS)) soap->mode &= ~SOAP_XML_INDENT; soap_element(soap, name, 0, NULL); /* element() */ soap->mode = m; } return soap->error; }
int calcService::pow(double a, double b, double *result) { printf("pow ... \n"); *result = ::pow(a, b); if (soap_errno == EDOM) /* soap_errno is like errno, but compatible with Win32 */ { char *s = (char*)soap_malloc(this, 1024); (SOAP_SNPRINTF(s, 1024, 100), "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b); return soap_senderfault("Power function domain error", s); } return SOAP_OK; }
int calcService::div(double a, double b, double *result) { printf("div ... \n"); if (b) *result = a / b; else { char *s = (char*)soap_malloc(this, 1024); (SOAP_SNPRINTF(s, 1024, 100), "<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b); return soap_senderfault("Division by zero", s); } return SOAP_OK; }
static const char * soap_push_ns_prefix(struct soap *soap, const char *id, const char *ns, int flag) { struct soap_nlist *np; if (!id) { struct Namespace *n; for (n = soap->local_namespaces; n && n->id; n++) { if (n->ns && !strcmp(n->ns, ns)) { id = n->id; break; } } if (!id) { (SOAP_SNPRINTF(soap->tag, sizeof(soap->tag), sizeof(SOAP_DOMID_FORMAT) + 20), SOAP_DOMID_FORMAT, soap->idnum++); id = soap->tag; } } /* fix advance generation of xmlns, when element (level) is not output yet */ if (flag) soap->level++; np = soap_push_namespace(soap, id, ns); if (flag) soap->level--; if (!np) return NULL; if (!np->ns) { np->ns = soap->local_namespaces[np->index].out; if (!np->ns) np->ns = soap->local_namespaces[np->index].ns; } np->index = 0; /* for C14N utilized mark */ if (*np->id) { (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(np->id) + 6), "xmlns:%s", np->id); out_attribute(soap, NULL, soap->msgbuf, ns, NULL, flag); } else out_attribute(soap, NULL, "xmlns", ns, NULL, flag); return np->id; }
const char * soap_xsd__integer2s(struct soap *soap, __int128_t a) { char *s = soap->tmpbuf; /* INT128_MIN = -170141183460469231731687303715884105728 */ __int128_t min128 = -(((__int128_t)UINT64_MAX + 1) * 0x7FFFFFFFFFFFFFFFULL + 0xFFFFFFFFFFFFFFFFULL) - 1; if (a < 0) { if (a == min128) return "-170141183460469231731687303715884105728"; *s++ = '-'; a = -a; } if (a > UINT64_MAX) { __int128_t l = a / 10000000000000000000ULL; /* leading digits */ uint64_t t = a % 10000000000000000000ULL; /* trailing 19 digits */ if (l > UINT64_MAX) { uint64_t ll = l / 10000000000000000000ULL; uint64_t tl = l % 10000000000000000000ULL; (SOAP_SNPRINTF(s, (s - soap->tmpbuf) + sizeof(soap->tmpbuf), 20), "%" PRIu64, ll); s += strlen(s); (SOAP_SNPRINTF(s, (s - soap->tmpbuf) + sizeof(soap->tmpbuf), 20), "%0.19" PRIu64, tl); } else { (SOAP_SNPRINTF(s, (s - soap->tmpbuf) + sizeof(soap->tmpbuf), 20), "%" PRIu64, (uint64_t)l); } s += strlen(s); (SOAP_SNPRINTF(s, (s - soap->tmpbuf) + sizeof(soap->tmpbuf), 20), "%0.19" PRIu64, t); } else { (SOAP_SNPRINTF(s, sizeof(soap->tmpbuf) - 1, 20), "%" PRIu64, (uint64_t)a); } return soap->tmpbuf; }
static int out_attribute(struct soap *soap, const char *prefix, const char *name, const char *data, const wchar_t *wide, int flag) { char *s; const char *t; size_t l; int err; if (wide) data = soap_wchar2s(soap, wide); if (!prefix || !*prefix) { if (wide) return soap_set_attr(soap, name, data, 2); if (flag) return soap_set_attr(soap, name, data, 1); return soap_attribute(soap, name, data); } t = strchr(name, ':'); if (t) t++; else t = name; l = strlen(prefix) + strlen(t); if (l + 1 < sizeof(soap->msgbuf)) s = soap->msgbuf; else { s = (char*)SOAP_MALLOC(soap, l + 2); if (!s) return soap->error = SOAP_EOM; } (SOAP_SNPRINTF(s, l + 2, l + 1), "%s:%s", prefix, t); if (wide) err = soap_set_attr(soap, s, data, 2); else if (flag) err = soap_set_attr(soap, s, data, 1); else err = soap_attribute(soap, s, data); if (s != soap->msgbuf) SOAP_FREE(soap, s); return err; }
static int jsstrout(struct soap *soap, const char *s) { int c; char buf[8]; if (soap_send_raw(soap, "\"", 1)) return soap->error; while ((c = *s++)) { switch (c) { case '"': case '\\': buf[0] = '\\'; buf[1] = c; if (soap_send_raw(soap, buf, 2)) return soap->error; break; default: if (c < 32 && c > 0) { switch (c) { case '\b': c = 'b'; break; case '\f': c = 'f'; break; case '\n': c = 'n'; break; case '\r': c = 'r'; break; case '\t': c = 't'; break; } if (c > 32) { buf[0] = '\\'; buf[1] = c; if (soap_send_raw(soap, buf, 2)) return soap->error; } else { (SOAP_SNPRINTF(buf, sizeof(buf), 7), "\\u%4x", c); if (soap_send_raw(soap, buf, 6)) return soap->error; } } else if ((c & 0x80) && (soap->omode & SOAP_ENC_LATIN) && (soap->omode & SOAP_C_UTFSTRING)) // utf8 to ISO 8859-1 { if (c < 0xE0 && (c & 0x1F) <= 0x03) buf[0] = ((c & 0x1F) << 6) | (*s++ & 0x3F); else buf[0] = '?'; if (soap_send_raw(soap, buf, 1)) return soap->error; } else if ((c & 0x80) && !(soap->omode & SOAP_ENC_LATIN) && !(soap->omode & SOAP_C_UTFSTRING)) // ISO 8859-1 to utf8 { buf[0] = (char)(0xC0 | ((c >> 6) & 0x1F)); buf[1] = (char)(0x80 | (c & 0x3F)); if (soap_send_raw(soap, buf, 2)) return soap->error; } else { buf[0] = c; if (soap_send_raw(soap, buf, 1)) return soap->error; } }
SOAP_FMAC1 int SOAP_FMAC2 soap_out_xsd__anyType(struct soap *soap, const char *tag, int id, const struct soap_dom_element *node, const char *type) { (void)id; (void)type; if (node) { const char *prefix; /* namespace prefix, if namespace is present */ size_t colon; if (!(soap->mode & SOAP_DOM_ASIS)) { const struct soap_dom_attribute *att; for (att = node->atts; att; att = att->next) { if (att->name && att->data && !strncmp(att->name, "xmlns:", 6)) { if (soap_push_namespace(soap, att->name + 6, att->data) == NULL) return soap->error; } else if (att->name && att->data && !strcmp(att->name, "xmlns")) { if (soap_push_namespace(soap, "", att->data) == NULL) return soap->error; } } } if (node->name) tag = node->name; else if (!tag) tag = "-"; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node '%s' output at level %u\n", tag, soap->level)); if ((prefix = strchr(tag, ':'))) { colon = prefix - tag + 1; if (colon > sizeof(soap->tag)) colon = sizeof(soap->tag); } else colon = 0; prefix = NULL; if (node->nstr && *node->nstr && !(soap->mode & SOAP_DOM_ASIS)) { if (colon) { soap_strncpy(soap->tag, sizeof(soap->tag), tag, colon - 1); if ((prefix = soap_push_ns_prefix(soap, soap->tag, node->nstr, 1)) == NULL || out_element(soap, node, prefix, tag + colon)) return soap->error; } else { if ((prefix = soap_lookup_ns_prefix(soap, node->nstr))) { if (out_element(soap, node, prefix, tag + colon)) return soap->error; } else { if ((prefix = soap_push_ns_prefix(soap, NULL, node->nstr, 1)) == NULL || out_element(soap, node, prefix, tag + colon)) return soap->error; } } } else { colon = 0; if (out_element(soap, node, NULL, tag)) return soap->error; } if (!node->type || !node->node) { struct soap_dom_attribute *att; struct soap_dom_element *elt; for (att = node->atts; att; att = att->next) { if (att->name) { if (att->nstr && !(soap->mode & SOAP_DOM_ASIS)) { const char *p; if ((att->nstr == node->nstr || (node->nstr && !strcmp(att->nstr, node->nstr))) && prefix) { if (out_attribute(soap, prefix, att->name, att->data, att->wide, 0)) return soap->error; } else if ((p = soap_lookup_ns_prefix(soap, att->nstr))) { if (out_attribute(soap, p, att->name, att->data, att->wide, 0)) return soap->error; } else if (!strncmp(att->name, "xml", 3)) { if (out_attribute(soap, NULL, att->name, att->data, att->wide, 0)) return soap->error; } else if ((p = soap_push_ns_prefix(soap, NULL, att->nstr, 0)) == NULL || out_attribute(soap, p, att->name, att->data, att->wide, 0)) return soap->error; } else if (soap_attribute(soap, att->name, att->wide ? soap_wchar2s(soap, att->wide) : att->data)) return soap->error; } } if ((soap->mode & SOAP_DOM_ASIS) && !node->data && !node->wide && !node->elts && !node->tail) { soap_mode m = soap->mode; soap->mode &= ~SOAP_XML_INDENT; if (*tag != '-' && soap_element_start_end_out(soap, tag)) return soap->error; soap->mode = m; } else { if (*tag != '-' && soap_element_start_end_out(soap, NULL)) return soap->error; if (*tag != '-' && node->data) { if (soap_string_out(soap, node->data, 0)) return soap->error; } else if (node->data) { if (soap_send(soap, node->data)) return soap->error; } else if (node->wide) { if (soap_wstring_out(soap, node->wide, 0)) return soap->error; } for (elt = node->elts; elt; elt = elt->next) { if (soap_out_xsd__anyType(soap, NULL, 0, elt, NULL)) return soap->error; } if (node->tail && soap_send(soap, node->tail)) return soap->error; if (!prefix || !*prefix) { soap_mode m = soap->mode; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of DOM node '%s'\n", tag + colon)); if ((soap->mode & SOAP_DOM_ASIS)) soap->mode &= ~SOAP_XML_INDENT; if (soap_element_end_out(soap, tag + colon)) return soap->error; soap->mode = m; } else { char *s; size_t l = strlen(prefix) + strlen(tag + colon); if (l + 1 < sizeof(soap->msgbuf)) s = soap->msgbuf; else { s = (char*)SOAP_MALLOC(soap, l + 2); if (!s) return soap->error = SOAP_EOM; } DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of DOM node '%s'\n", tag)); (SOAP_SNPRINTF(s, l + 2, l + 1), "%s:%s", prefix, tag + colon); soap_pop_namespace(soap); if (soap_element_end_out(soap, s)) return soap->error; if (s != soap->msgbuf) SOAP_FREE(soap, s); } } } } 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 void http_da_calc_opaque(struct soap *soap, char opaque[HTTP_DA_OPAQUELEN]) { (void)soap; (SOAP_SNPRINTF(opaque, HTTP_DA_OPAQUELEN, 8), "%8.8x", soap_random); }
static void http_da_calc_nonce(struct soap *soap, char nonce[HTTP_DA_NONCELEN]) { static short count = 0xCA53; (void)soap; (SOAP_SNPRINTF(nonce, HTTP_DA_NONCELEN, 20), "%8.8x%4.4hx%8.8x", (int)time(NULL), count++, soap_random); }
int main(int argc, char **argv) { struct soap *soap; int server = 0; int text = 0; int port = 0; FILE *fd; double result; char *user; int runs = 1; /* create context */ soap = soap_new(); /* register wsse plugin */ soap_register_plugin_arg(soap, soap_wsse, (void*)token_handler); /* options */ if (argc >= 2) { if (strchr(argv[1], 'c')) soap_set_omode(soap, SOAP_IO_CHUNK); else if (strchr(argv[1], 'y')) soap_set_omode(soap, SOAP_IO_STORE); if (strchr(argv[1], 'i')) soap_set_omode(soap, SOAP_XML_INDENT); if (strchr(argv[1], 'n')) soap_set_omode(soap, SOAP_XML_CANONICAL); if (strchr(argv[1], 'a')) aes = 1; if (strchr(argv[1], 'o')) oaep = 1; if (strchr(argv[1], 'd')) sym = 1; if (strchr(argv[1], 'e')) enc = 1; if (strchr(argv[1], 'f')) addenc = 1; /* if (strchr(argv[1], 'F')) addenca = 1; */ if (strchr(argv[1], 'h')) hmac = 1; if (strchr(argv[1], 'k')) nokey = 1; if (strchr(argv[1], 's')) server = 1; if (strchr(argv[1], 't')) text = 1; if (strchr(argv[1], 'g')) addsig = 1; if (strchr(argv[1], 'b')) nobody = 1; if (strchr(argv[1], 'x')) nohttp = 1; if (strchr(argv[1], 'z')) soap_set_mode(soap, SOAP_ENC_ZLIB); if (isdigit(argv[1][strlen(argv[1])-1])) { runs = argv[1][strlen(argv[1])-1] - '0'; soap_set_mode(soap, SOAP_IO_KEEPALIVE); } } /* soap->actor = "..."; */ /* set only when required */ user = getenv("USER"); if (!user) user = "******"; /* read RSA private key for signing */ if ((fd = fopen("server.pem", "r"))) { rsa_privk = PEM_read_PrivateKey(fd, NULL, NULL, (void*)"password"); fclose(fd); if (!rsa_privk) { fprintf(stderr, "Could not read private RSA key from server.pem\n"); exit(1); } } else fprintf(stderr, "Could not read server.pem\n"); /* read certificate (more efficient is to keep certificate in memory) to obtain public key for encryption and signature verification */ if ((fd = fopen("servercert.pem", "r"))) { cert = PEM_read_X509(fd, NULL, NULL, NULL); fclose(fd); if (!cert) { fprintf(stderr, "Could not read certificate from servercert.pem\n"); exit(1); } } else fprintf(stderr, "Could not read server.pem\n"); rsa_pubk = X509_get_pubkey(cert); if (!rsa_pubk) { fprintf(stderr, "Could not get public key from certificate\n"); exit(1); } /* port argument */ if (argc >= 3) port = atoi(argv[2]); /* need cacert to verify certificates with CA (cacert.pem for testing and cacerts.pem for production, which contains the trusted CA certificates) */ soap->cafile = "cacert.pem"; /* server or client/ */ if (server) { if (port) { /* stand-alone server serving messages over port */ if (!soap_valid_socket(soap_bind(soap, NULL, port, 100))) { soap_print_fault(soap, stderr); exit(1); } printf("Server started at port %d\n", port); while (soap_valid_socket(soap_accept(soap))) { if (hmac) soap_wsse_verify_auto(soap, SOAP_SMD_HMAC_SHA1, hmac_key, sizeof(hmac_key)); else if (nokey) soap_wsse_verify_auto(soap, SOAP_SMD_VRFY_RSA_SHA1, rsa_pubk, 0); else soap_wsse_verify_auto(soap, SOAP_SMD_NONE, NULL, 0); if (sym) { if (aes) soap_wsse_decrypt_auto(soap, SOAP_MEC_DEC_AES256_CBC, aes_key, sizeof(aes_key)); else soap_wsse_decrypt_auto(soap, SOAP_MEC_DEC_DES_CBC, des_key, sizeof(des_key)); } else if (enc) soap_wsse_decrypt_auto(soap, SOAP_MEC_ENV_DEC_DES_CBC, rsa_privk, 0); if (soap_serve(soap)) { soap_wsse_delete_Security(soap); soap_print_fault(soap, stderr); soap_print_fault_location(soap, stderr); } soap_destroy(soap); soap_end(soap); } soap_print_fault(soap, stderr); exit(1); } else { /* CGI-style server serving messages over stdin/out */ if (hmac) soap_wsse_verify_auto(soap, SOAP_SMD_HMAC_SHA1, hmac_key, sizeof(hmac_key)); else if (nokey) soap_wsse_verify_auto(soap, SOAP_SMD_VRFY_RSA_SHA1, rsa_pubk, 0); else soap_wsse_verify_auto(soap, SOAP_SMD_NONE, NULL, 0); if (sym) { if (aes) soap_wsse_decrypt_auto(soap, SOAP_MEC_DEC_AES256_CBC, aes_key, sizeof(aes_key)); else soap_wsse_decrypt_auto(soap, SOAP_MEC_DEC_DES_CBC, des_key, sizeof(des_key)); } else if (enc) soap_wsse_decrypt_auto(soap, SOAP_MEC_ENV_DEC_DES_CBC, rsa_privk, 0); if (soap_serve(soap)) { soap_wsse_delete_Security(soap); soap_print_fault(soap, stderr); soap_print_fault_location(soap, stderr); } soap_destroy(soap); soap_end(soap); } } else /* client */ { int run; char endpoint[80]; /* ns1:test data */ struct ns1__add a; struct ns1__sub b; a.a = 123; a.b = 456; b.a = 789; b.b = -99999; /* client sending messages to stdout or over port */ if (port) (SOAP_SNPRINTF(endpoint, sizeof(endpoint), 37), "http://localhost:%d", port); else if (nohttp) soap_strcpy(endpoint, sizeof(endpoint), ""); else soap_strcpy(endpoint, sizeof(endpoint), "http://"); for (run = 0; run < runs; run++) { /* message lifetime of 60 seconds */ soap_wsse_add_Timestamp(soap, "Time", 60); /* add user name with text or digest password */ if (text) soap_wsse_add_UsernameTokenText(soap, "User", user, "userPass"); else soap_wsse_add_UsernameTokenDigest(soap, "User", user, "userPass"); if (sym) { if (aes) { /* symmetric encryption with AES */ soap_wsse_add_EncryptedData_KeyInfo_KeyName(soap, "My AES Key"); if (soap_wsse_encrypt_body(soap, SOAP_MEC_ENC_AES256_CBC, aes_key, sizeof(aes_key))) soap_print_fault(soap, stderr); soap_wsse_decrypt_auto(soap, SOAP_MEC_DEC_AES256_CBC, aes_key, sizeof(aes_key)); } else { /* symmetric encryption with DES */ soap_wsse_add_EncryptedData_KeyInfo_KeyName(soap, "My DES Key"); if (soap_wsse_encrypt_body(soap, SOAP_MEC_ENC_DES_CBC, des_key, sizeof(des_key))) soap_print_fault(soap, stderr); soap_wsse_decrypt_auto(soap, SOAP_MEC_DEC_DES_CBC, des_key, sizeof(des_key)); } } else if (addenc || addenca) { /* RSA encryption of the <ns1:add> element */ const char *SubjectKeyId = NULL; /* set to non-NULL to use SubjectKeyIdentifier in Header rather than a full cert key */ /* MUST set wsu:Id of the elements to encrypt */ if (addenc) /* encrypt element <ns1:add> */ { soap_wsse_set_wsu_id(soap, "ns1:add"); if (soap_wsse_add_EncryptedKey_encrypt_only(soap, SOAP_MEC_ENV_ENC_DES_CBC, "Cert", cert, SubjectKeyId, NULL, NULL, "ns1:add")) soap_print_fault(soap, stderr); } else /* encrypt element <a> */ { soap_wsse_set_wsu_id(soap, "a"); if (soap_wsse_add_EncryptedKey_encrypt_only(soap, SOAP_MEC_ENV_ENC_DES_CBC, "Cert", cert, SubjectKeyId, NULL, NULL, "a")) soap_print_fault(soap, stderr); } soap_wsse_decrypt_auto(soap, SOAP_MEC_ENV_DEC_DES_CBC, rsa_privk, 0); } else if (enc) { /* RSA encryption of the SOAP Body */ const char *SubjectKeyId = NULL; /* set to non-NULL to use SubjectKeyIdentifier in Header rather than a full cert key */ if (oaep) { if (soap_wsse_add_EncryptedKey(soap, SOAP_MEC_ENV_ENC_AES256_CBC | SOAP_MEC_OAEP, "Cert", cert, SubjectKeyId, NULL, NULL)) soap_print_fault(soap, stderr); } else if (aes) { if (soap_wsse_add_EncryptedKey(soap, SOAP_MEC_ENV_ENC_AES256_CBC, "Cert", cert, SubjectKeyId, NULL, NULL)) soap_print_fault(soap, stderr); } else { if (soap_wsse_add_EncryptedKey(soap, SOAP_MEC_ENV_ENC_DES_CBC, "Cert", cert, SubjectKeyId, NULL, NULL)) soap_print_fault(soap, stderr); } soap_wsse_decrypt_auto(soap, SOAP_MEC_ENV_DEC_DES_CBC, rsa_privk, 0); } if (hmac) { /* symmetric signature */ if (nobody) soap_wsse_sign(soap, SOAP_SMD_HMAC_SHA1, hmac_key, sizeof(hmac_key)); else soap_wsse_sign_body(soap, SOAP_SMD_HMAC_SHA1, hmac_key, sizeof(hmac_key)); /* WS-SecureConversation contect token */ soap_wsse_add_SecurityContextToken(soap, "SCT", contextId); } else { if (nokey) soap_wsse_add_KeyInfo_KeyName(soap, "MyKey"); else { soap_wsse_add_BinarySecurityTokenX509(soap, "X509Token", cert); soap_wsse_add_KeyInfo_SecurityTokenReferenceX509(soap, "#X509Token"); } if (nobody || addsig) /* do not sign body */ soap_wsse_sign(soap, SOAP_SMD_SIGN_RSA_SHA1, rsa_privk, 0); else soap_wsse_sign_body(soap, SOAP_SMD_SIGN_RSA_SHA256, rsa_privk, 0); } /* enable automatic signature verification of server responses */ if (hmac) soap_wsse_verify_auto(soap, SOAP_SMD_HMAC_SHA1, hmac_key, sizeof(hmac_key)); else if (nokey) soap_wsse_verify_auto(soap, SOAP_SMD_VRFY_RSA_SHA1, rsa_pubk, 0); else soap_wsse_verify_auto(soap, SOAP_SMD_NONE, NULL, 0); /* sign the response message in unsigned body? If so, set wsu:Id */ if (addsig) { soap_wsse_set_wsu_id(soap, "ns1:add"); soap_wsse_sign_only(soap, "User ns1:add"); } /* invoke the server. You can choose add, sub, mul, or div operations * that show different security aspects (intentional message rejections) * for demonstration purposes (see server operations below) */ if (!soap_call_ns1__add(soap, endpoint, NULL, 1.0, 2.0, &result)) { if (!soap_wsse_verify_Timestamp(soap)) { const char *servername = soap_wsse_get_Username(soap); if (servername && !strcmp(servername, "server") && !soap_wsse_verify_Password(soap, "serverPass")) printf("Result = %g\n", result); else { fprintf(stderr, "Server authentication failed\n"); soap_print_fault(soap, stderr); } } else { fprintf(stderr, "Server response expired\n"); soap_print_fault(soap, stderr); } } else { soap_print_fault(soap, stderr); soap_print_fault_location(soap, stderr); } /* clean up security header */ soap_wsse_delete_Security(soap); /* disable soap_wsse_verify_auto */ soap_wsse_verify_done(soap); } /* run */ } /* clean up keys */ if (rsa_privk) EVP_PKEY_free(rsa_privk); if (rsa_pubk) EVP_PKEY_free(rsa_pubk); if (cert) X509_free(cert); /* clean up gSOAP engine */ soap_destroy(soap); soap_end(soap); soap_done(soap); free(soap); /* done */ return 0; }