void pni_sasl_set_user_password(pn_transport_t *transport, const char *user, const char *password) { pni_sasl_t *sasl = transport->sasl; sasl->username = user; free(sasl->password); sasl->password = password ? pn_strdup(password) : NULL; }
pn_sasl_t *pn_sasl(pn_transport_t *transport) { if (!transport->sasl) { pni_sasl_t *sasl = (pni_sasl_t *) malloc(sizeof(pni_sasl_t)); const char *sasl_config_path = getenv("PN_SASL_CONFIG_PATH"); sasl->impl_context = NULL; sasl->client = !transport->server; sasl->selected_mechanism = NULL; sasl->included_mechanisms = NULL; sasl->username = NULL; sasl->password = NULL; sasl->config_name = NULL; sasl->config_dir = sasl_config_path ? pn_strdup(sasl_config_path) : NULL; sasl->remote_fqdn = NULL; sasl->external_auth = NULL; sasl->external_ssf = 0; sasl->outcome = PN_SASL_NONE; sasl->impl_context = NULL; sasl->decoded_buffer = pn_buffer(0); sasl->encoded_buffer = pn_buffer(0); sasl->bytes_out.size = 0; sasl->bytes_out.start = NULL; sasl->desired_state = SASL_NONE; sasl->last_state = SASL_NONE; sasl->allow_insecure_mechs = false; transport->sasl = sasl; } // The actual external pn_sasl_t pointer is a pointer to its enclosing pn_transport_t return (pn_sasl_t *)transport; }
void pni_sasl_set_external_security(pn_transport_t *transport, int ssf, const char *authid) { pni_sasl_t *sasl = transport->sasl; sasl->external_ssf = ssf; free(sasl->external_auth); sasl->external_auth = authid ? pn_strdup(authid) : NULL; }
int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain, const pn_ssl_verify_mode_t mode, const char *trusted_CAs) { if (!domain) return -1; switch (mode) { case PN_SSL_VERIFY_PEER: case PN_SSL_VERIFY_PEER_NAME: if (!domain->has_ca_db) { pn_transport_logf(NULL, "Error: cannot verify peer without a trusted CA configured.\n" " Use pn_ssl_domain_set_trusted_ca_db()"); return -1; } if (domain->mode == PN_SSL_MODE_SERVER) { // openssl requires that server connections supply a list of trusted CAs which is // sent to the client if (!trusted_CAs) { pn_transport_logf(NULL, "Error: a list of trusted CAs must be provided."); return -1; } if (!domain->has_certificate) { pn_transport_logf(NULL, "Error: Server cannot verify peer without configuring a certificate.\n" " Use pn_ssl_domain_set_credentials()"); } if (domain->trusted_CAs) free(domain->trusted_CAs); domain->trusted_CAs = pn_strdup( trusted_CAs ); STACK_OF(X509_NAME) *cert_names; cert_names = SSL_load_client_CA_file( domain->trusted_CAs ); if (cert_names != NULL) SSL_CTX_set_client_CA_list(domain->ctx, cert_names); else { pn_transport_logf(NULL, "Error: Unable to process file of trusted CAs: %s", trusted_CAs); return -1; } } SSL_CTX_set_verify( domain->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); #if (OPENSSL_VERSION_NUMBER < 0x00905100L) SSL_CTX_set_verify_depth(domain->ctx, 1); #endif break; case PN_SSL_ANONYMOUS_PEER: // hippie free love mode... :) SSL_CTX_set_verify( domain->ctx, SSL_VERIFY_NONE, NULL ); break; default: pn_transport_logf(NULL, "Invalid peer authentication mode given." ); return -1; } domain->verify_mode = mode; return 0; }
char* pn_i_genuuid(void) { unsigned char *generated; UUID uuid; UuidCreate(&uuid); UuidToString(&uuid, &generated); char* r = pn_strdup((const char*)generated); RpcStringFree(&generated); return r; }
int pn_error_set(pn_error_t *error, int code, const char *text) { pn_error_clear(error); if (code) { error->code = code; error->text = pn_strdup(text); } return code; }
void pn_sasl_allowed_mechs(pn_sasl_t *sasl0, const char *mechs) { pni_sasl_t *sasl = get_sasl_internal(sasl0); free(sasl->included_mechanisms); sasl->included_mechanisms = mechs ? pn_strdup(mechs) : NULL; if (strcmp(mechs, "ANONYMOUS")==0 ) { pn_transport_t *transport = get_transport_internal(sasl0); pni_sasl_force_anonymous(transport); } }
char *build_name(const char *name) { if (name) { return pn_strdup(name); } else { char *generated = malloc(37*sizeof(char)); uuid_t uuid; uuid_generate(uuid); uuid_unparse_lower(uuid, generated); return generated; } }
int pni_sasl_impl_list_mechs(pn_transport_t *transport, char **mechlist) { pni_sasl_t *sasl = transport->sasl; sasl_conn_t *cyrus_conn = (sasl_conn_t*)sasl->impl_context; int count = 0; if (cyrus_conn) { const char *result = NULL; int r = sasl_listmech(cyrus_conn, NULL, "", " ", "", &result, NULL, &count); if (pni_check_sasl_result(cyrus_conn, r, transport)) { if (result && *result) { *mechlist = pn_strdup(result); } } } return count; }
bool pni_process_mechanisms(pn_transport_t *transport, const char *mechs) { pni_sasl_t *sasl = transport->sasl; sasl_conn_t *cyrus_conn = (sasl_conn_t*)sasl->impl_context; const char *mech_selected; int result = pni_wrap_client_start(sasl, mechs, &mech_selected); switch (result) { case SASL_OK: case SASL_CONTINUE: sasl->selected_mechanism = pn_strdup(mech_selected); return true; case SASL_NOMECH: default: pni_check_sasl_result(cyrus_conn, result, transport); return false; } }
int pn_ssl_init(pn_ssl_t *ssl0, pn_ssl_domain_t *domain, const char *session_id) { pn_transport_t *transport = get_transport_internal(ssl0); pni_ssl_t *ssl = transport->ssl; if (!ssl || !domain || ssl->domain) return -1; ssl->domain = domain; domain->ref_count++; if (session_id && domain->mode == PN_SSL_MODE_CLIENT) ssl->session_id = pn_strdup(session_id); // If SSL doesn't specifically allow skipping encryption, require SSL // TODO: This is a probably a stop-gap until allow_unsecured is removed if (!domain->allow_unsecured) transport->encryption_required = true; return init_ssl_socket(transport, ssl); }
int pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname ) { if (!ssl) return -1; if (ssl->peer_hostname) free((void *)ssl->peer_hostname); ssl->peer_hostname = NULL; if (hostname) { ssl->peer_hostname = pn_strdup(hostname); if (!ssl->peer_hostname) return -2; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (ssl->ssl && ssl->domain && ssl->domain->mode == PN_SSL_MODE_CLIENT) { SSL_set_tlsext_host_name(ssl->ssl, ssl->peer_hostname); } #endif } return 0; }
int pn_ssl_init( pn_ssl_t *ssl, pn_ssl_domain_t *domain, const char *session_id) { if (!ssl || !domain || ssl->domain) return -1; ssl->domain = domain; domain->ref_count++; if (domain->allow_unsecured) { ssl->io_layer->process_input = process_input_unknown; ssl->io_layer->process_output = process_output_unknown; } else { ssl->io_layer->process_input = process_input_ssl; ssl->io_layer->process_output = process_output_ssl; } if (session_id && domain->mode == PN_SSL_MODE_CLIENT) ssl->session_id = pn_strdup(session_id); return init_ssl_socket(ssl); }
int pn_ssl_domain_set_credentials( pn_ssl_domain_t *domain, const char *certificate_file, const char *private_key_file, const char *password) { if (!domain || !domain->ctx) return -1; if (SSL_CTX_use_certificate_chain_file(domain->ctx, certificate_file) != 1) { ssl_log_error("SSL_CTX_use_certificate_chain_file( %s ) failed", certificate_file); return -3; } if (password) { domain->keyfile_pw = pn_strdup(password); // @todo: obfuscate me!!! SSL_CTX_set_default_passwd_cb(domain->ctx, keyfile_pw_cb); SSL_CTX_set_default_passwd_cb_userdata(domain->ctx, domain->keyfile_pw); } if (SSL_CTX_use_PrivateKey_file(domain->ctx, private_key_file, SSL_FILETYPE_PEM) != 1) { ssl_log_error("SSL_CTX_use_PrivateKey_file( %s ) failed", private_key_file); return -4; } if (SSL_CTX_check_private_key(domain->ctx) != 1) { ssl_log_error("The key file %s is not consistent with the certificate %s", private_key_file, certificate_file); return -5; } domain->has_certificate = true; // bug in older versions of OpenSSL: servers may request client cert even if anonymous // cipher was negotiated. TLSv1 will reject such a request. Hack: once a cert is // configured, allow only authenticated ciphers. if (!SSL_CTX_set_cipher_list( domain->ctx, CIPHERS_AUTHENTICATE )) { ssl_log_error("Failed to set cipher list to %s", CIPHERS_AUTHENTICATE); return -6; } return 0; }
static int start_ssl_shutdown( pn_ssl_t *ssl ) { if (!ssl->ssl_shutdown) { _log(ssl, "Shutting down SSL connection...\n"); if (ssl->session_id) { // save the negotiated credentials before we close the connection pn_ssl_session_t *ssn = (pn_ssl_session_t *)calloc( 1, sizeof(pn_ssl_session_t)); if (ssn) { ssn->id = pn_strdup( ssl->session_id ); ssn->session = SSL_get1_session( ssl->ssl ); if (ssn->session) { _log( ssl, "Saving SSL session as %s\n", ssl->session_id ); LL_ADD( ssl->domain, ssn_cache, ssn ); } else { ssl_session_free( ssn ); } } } ssl->ssl_shutdown = true; BIO_ssl_shutdown( ssl->bio_ssl ); } return 0; }
void pn_sasl_config_path(pn_sasl_t *sasl0, const char *dir) { pni_sasl_t *sasl = get_sasl_internal(sasl0); free(sasl->config_dir); sasl->config_dir = pn_strdup(dir); }
void pn_sasl_config_name(pn_sasl_t *sasl0, const char *name) { pni_sasl_t *sasl = get_sasl_internal(sasl0); free(sasl->config_name); sasl->config_name = pn_strdup(name); }
void pn_sasl_mechanisms(pn_sasl_t *sasl, const char *mechanisms) { if (!sasl) return; sasl->mechanisms = pn_strdup(mechanisms); }