int ns1__mul(struct soap *soap, double a, double b, double *result) { const char *username = soap_wsse_get_Username(soap); if (username) fprintf(stderr, "Hello %s, want to multiply %g * %g = ?\n", username, a, b); if (soap_wsse_verify_Timestamp(soap) || soap_wsse_verify_Password(soap, "userPass")) { soap_wsse_delete_Security(soap); return soap->error; } if (soap_wsse_verify_element(soap, "http://www.genivia.com/schemas/wssetest.xsd", "mul") == 0) { soap_wsse_delete_Security(soap); return soap_sender_fault(soap, "Service operation not signed", NULL); } soap_wsse_delete_Security(soap); soap_wsse_add_Timestamp(soap, "Time", 10); /* lifetime of 10 seconds */ /* In this case we leave out the server name and password. Because the * client receiver requires the presence of authentication information, the * client will reject the response. */ if (hmac) { 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"); } soap_wsse_sign_body(soap, SOAP_SMD_SIGN_RSA_SHA256, rsa_privk, 0); } *result = a * b; return SOAP_OK; }
int bes_security(struct bes_context *context, char *x509cert, char *x509pass, char *capath, char *user, char *pass) { struct soap *soap; if (context == NULL) { return BESE_BAD_ARG; } soap = context->soap; if (soap_ssl_client_context(soap, SOAP_SSL_DEFAULT|SOAP_SSL_SKIP_HOST_CHECK, x509cert, x509pass, NULL, capath, NULL)) { setErrorString(context, context->soap, BESE_SOAP_ERR); return BESE_SOAP_ERR; } if (user) { if (soap_wsse_add_UsernameTokenText(soap, NULL, user, pass)) { setErrorString(context, context->soap, BESE_SOAP_ERR); return BESE_SOAP_ERR; } if (soap_wsse_add_Timestamp(soap, NULL, 60)) { setErrorString(context, context->soap, BESE_SOAP_ERR); return BESE_SOAP_ERR; } } if (x509cert) { if (context->x509cert) free(context->x509cert); context->x509cert = strdup(x509cert); } if (x509pass) { if (context->x509pass) free(context->x509pass); context->x509pass = strdup(x509pass); } if (capath) { if (context->capath) free(context->capath); context->capath = strdup(capath); } if (user) { if (context->user) free(context->user); context->user = strdup(user); } if (pass) { if (context->pass) free(context->pass); context->pass = strdup(pass); } return BESE_OK; }
void addSecurity(struct soap* soap, const std::string& username, const std::string & password) { if (!username.empty()) { soap_wsse_add_Timestamp(soap, "Time", 600); soap_wsse_add_UsernameTokenDigest(soap, "User", username.c_str() , password.c_str()); } }
/* Set WS-Security server-side properties after an operation */ static int set_srv_security(struct soap *soap) { if (soap_wsse_add_Timestamp(soap, "Time", 60) // 1 min to expire || soap_wsse_add_BinarySecurityTokenX509(soap, "X509Token", srv_cert) || soap_wsse_add_KeyInfo_SecurityTokenReferenceX509(soap, "#X509Token") || soap_wsse_sign_body(soap, SOAP_SMD_SIGN_RSA_SHA1, srv_privk, 0) #ifdef UNENCRYPTED_SIGNATURE || soap_wsse_add_EncryptedKey(soap, SOAP_MEC_ENV_ENC_AES256_CBC, NULL, clt_cert, NULL, clt_issuer+1, clt_serial) #else || soap_wsse_add_EncryptedKey_encrypt_only(soap, SOAP_MEC_ENV_ENC_AES256_CBC, NULL, clt_cert, NULL, clt_issuer+1, clt_serial, "ds:Signature SOAP-ENV:Body") #endif ) return soap->error; return SOAP_OK; }
/* Set WS-Security client-side properties before an operation */ static int set_clt_security(struct soap *soap) { // soap_wsse_set_wsu_id(soap, "ds:Signature"); // to encrypt ds:Signature if (soap_wsse_add_Timestamp(soap, "Time", 60) // 1 min to expire || soap_wsse_add_BinarySecurityTokenX509(soap, "X509Token", clt_cert) || soap_wsse_add_KeyInfo_SecurityTokenReferenceX509(soap, "#X509Token") || soap_wsse_sign_body(soap, SOAP_SMD_SIGN_RSA_SHA1, clt_privk, 0) || soap_wsse_verify_auto(soap, SOAP_WSSE_IGNORE_EXTRA_REFS, NULL, 0) #ifdef UNENCRYPTED_SIGNATURE || soap_wsse_add_EncryptedKey(soap, SOAP_MEC_ENV_ENC_AES256_CBC, NULL, srv_cert, NULL, srv_issuer+1, srv_serial) #else || soap_wsse_add_EncryptedKey_encrypt_only(soap, SOAP_MEC_ENV_ENC_AES256_CBC, NULL, srv_cert, NULL, srv_issuer+1, srv_serial, "ds:Signature SOAP-ENV:Body") #endif || soap_wsse_decrypt_auto(soap, SOAP_MEC_ENV_DEC_AES256_CBC, clt_privk, 0)) return soap->error; return SOAP_OK; }
int bes_add_usertoken(struct bes_context *context, char *user, char *pass) { if (context == NULL) { return BESE_BAD_ARG; } if (soap_wsse_add_UsernameTokenText(context->soap, NULL, user, pass)) { setErrorString(context, context->soap, BESE_SOAP_ERR); return BESE_SOAP_ERR; } if (soap_wsse_add_Timestamp(context->soap, NULL, 60)) { setErrorString(context, context->soap, BESE_SOAP_ERR); return BESE_SOAP_ERR; } return BESE_OK; }
int ns1__div(struct soap *soap, double a, double b, double *result) { const char *username = soap_wsse_get_Username(soap); if (username) fprintf(stderr, "Hello %s, want to divide %g / %g = ?\n", username, a, b); if (soap_wsse_verify_Timestamp(soap) || soap_wsse_verify_Password(soap, "userPass")) { soap_wsse_delete_Security(soap); return soap->error; } if (soap_wsse_verify_element(soap, "http://www.genivia.com/schemas/wssetest.xsd", "div") == 0) { soap_wsse_delete_Security(soap); return soap_sender_fault(soap, "Service operation not signed", NULL); } soap_wsse_delete_Security(soap); soap_wsse_add_Timestamp(soap, "Time", 10); /* lifetime of 10 seconds */ soap_wsse_add_UsernameTokenDigest(soap, "User", "server", "serverPass"); /* In this case we leave out the signature and the receiver will reject this unsigned message. */ if (b == 0.0) return soap_sender_fault(soap, "Division by zero", NULL); *result = a / b; return SOAP_OK; }
int ns1__add(struct soap *soap, double a, double b, double *result) { const char *username = soap_wsse_get_Username(soap); if (username) fprintf(stderr, "Hello %s, want to add %g + %g = ?\n", username, a, b); if (soap_wsse_verify_Timestamp(soap) || soap_wsse_verify_Password(soap, "userPass")) { int err = soap->error; /* preserve error code */ soap_wsse_delete_Security(soap); /* remove WS-Security information */ /* the above suffices to return an unsigned fault, but here we show how to return a signed fault: */ soap_wsse_add_BinarySecurityTokenX509(soap, "X509Token", cert); soap_wsse_add_KeyInfo_SecurityTokenReferenceX509(soap, "#X509Token"); soap_wsse_sign_body(soap, SOAP_SMD_SIGN_RSA_SHA256, rsa_privk, 0); return err; } if (soap_wsse_verify_element(soap, "http://www.genivia.com/schemas/wssetest.xsd", "add") == 0) { soap_wsse_delete_Security(soap); return soap_sender_fault(soap, "Service operation not signed", NULL); } soap_wsse_delete_Security(soap); /* remove WS-Security before setting new security information */ soap_wsse_add_Timestamp(soap, "Time", 10); /* lifetime of 10 seconds */ soap_wsse_add_UsernameTokenDigest(soap, "User", "server", "serverPass"); if (hmac) { if (nobody || addsig) 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 context 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) 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); } /* sign the response message inside the unsigned enveloping body? If so, set wsu:Id of the response */ if (addsig) soap_wsse_set_wsu_id(soap, "ns1:addResponse"); if (sym) { if (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); } else { 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); } } else if (addenc) { /* MUST set wsu:Id of the elements to encrypt */ soap_wsse_set_wsu_id(soap, "ns1:addResponse"); if (soap_wsse_add_EncryptedKey_encrypt_only(soap, SOAP_MEC_ENV_ENC_DES_CBC, "Cert", cert, NULL, NULL, NULL, "ns:addResponse")) soap_print_fault(soap, stderr); } else if (enc) { if (oaep) { if (soap_wsse_add_EncryptedKey(soap, SOAP_MEC_ENV_ENC_AES256_CBC | SOAP_MEC_OAEP, "Cert", cert, NULL, NULL, NULL)) soap_print_fault(soap, stderr); } else if (aes) { if (soap_wsse_add_EncryptedKey(soap, SOAP_MEC_ENV_ENC_AES256_CBC, "Cert", cert, NULL, NULL, NULL)) soap_print_fault(soap, stderr); } else { if (soap_wsse_add_EncryptedKey(soap, SOAP_MEC_ENV_ENC_DES_CBC, "Cert", cert, NULL, NULL, NULL)) soap_print_fault(soap, stderr); } } *result = a + b; return SOAP_OK; }
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) sprintf(endpoint, "http://localhost:%d", port); else if (nohttp) strcpy(endpoint, ""); else strcpy(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; }