Added configuration for PLAIN security

* ZMQ_PLAIN_SERVER, ZMQ_PLAIN_USERNAME, ZMQ_PLAIN_PASSWORD options
* Man page changes to zmq_setsockopt and zmq_getsockopt
* Man pages for ZMQ_NULL, ZMQ_PLAIN, and ZMQ_CURVE
* Test program test_security
This commit is contained in:
Pieter Hintjens
2013-05-15 17:54:03 +02:00
parent 8ea779c8f7
commit e1f797b048
14 changed files with 693 additions and 309 deletions

View File

@@ -51,6 +51,8 @@ zmq::options_t::options_t () :
tcp_keepalive_cnt (-1),
tcp_keepalive_idle (-1),
tcp_keepalive_intvl (-1),
mechanism (ZMQ_NULL),
plain_server (0),
socket_id (0)
{
}
@@ -58,30 +60,29 @@ zmq::options_t::options_t () :
int zmq::options_t::setsockopt (int option_, const void *optval_,
size_t optvallen_)
{
bool valid = true;
bool is_int = (optvallen_ == sizeof (int));
int value = is_int? *((int *) optval_): 0;
switch (option_) {
case ZMQ_SNDHWM:
if (is_int && value >= 0)
if (is_int && value >= 0) {
sndhwm = value;
else
valid = false;
return 0;
}
break;
case ZMQ_RCVHWM:
if (is_int && value >= 0)
if (is_int && value >= 0) {
rcvhwm = value;
else
valid = false;
return 0;
}
break;
case ZMQ_AFFINITY:
if (optvallen_ == sizeof (uint64_t))
if (optvallen_ == sizeof (uint64_t)) {
affinity = *((uint64_t*) optval_);
else
valid = false;
return 0;
}
break;
case ZMQ_IDENTITY:
@@ -92,405 +93,419 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
&& *((const unsigned char *) optval_) != 0) {
identity_size = optvallen_;
memcpy (identity, optval_, identity_size);
return 0;
}
else
valid = false;
break;
case ZMQ_RATE:
if (is_int && value > 0)
if (is_int && value > 0) {
rate = value;
else
valid = false;
return 0;
}
break;
case ZMQ_RECOVERY_IVL:
if (is_int && value >= 0)
if (is_int && value >= 0) {
recovery_ivl = value;
else
valid = false;
return 0;
}
break;
case ZMQ_SNDBUF:
if (is_int && value >= 0)
if (is_int && value >= 0) {
sndbuf = value;
else
valid = false;
return 0;
}
break;
case ZMQ_RCVBUF:
if (is_int && value >= 0)
if (is_int && value >= 0) {
rcvbuf = value;
else
valid = false;
return 0;
}
break;
case ZMQ_LINGER:
if (is_int && value >= -1)
if (is_int && value >= -1) {
linger = value;
else
valid = false;
return 0;
}
break;
case ZMQ_RECONNECT_IVL:
if (is_int && value >= -1)
if (is_int && value >= -1) {
reconnect_ivl = value;
else
valid = false;
return 0;
}
break;
case ZMQ_RECONNECT_IVL_MAX:
if (is_int && value >= 0)
if (is_int && value >= 0) {
reconnect_ivl_max = value;
else
valid = false;
return 0;
}
break;
case ZMQ_BACKLOG:
if (is_int && value >= 0)
if (is_int && value >= 0) {
backlog = value;
else
valid = false;
return 0;
}
break;
case ZMQ_MAXMSGSIZE:
if (optvallen_ == sizeof (int64_t))
if (optvallen_ == sizeof (int64_t)) {
maxmsgsize = *((int64_t *) optval_);
else
valid = false;
return 0;
}
break;
case ZMQ_MULTICAST_HOPS:
if (is_int && value > 0)
if (is_int && value > 0) {
multicast_hops = value;
else
valid = false;
return 0;
}
break;
case ZMQ_RCVTIMEO:
if (is_int && value >= -1)
if (is_int && value >= -1) {
rcvtimeo = value;
else
valid = false;
return 0;
}
break;
case ZMQ_SNDTIMEO:
if (is_int && value >= -1)
if (is_int && value >= -1) {
sndtimeo = value;
else
valid = false;
return 0;
}
break;
/* Deprecated in favor of ZMQ_IPV6 */
case ZMQ_IPV4ONLY:
if (is_int && (value == 0 || value == 1))
if (is_int && (value == 0 || value == 1)) {
ipv6 = (value == 0);
else
valid = false;
return 0;
}
break;
/* To replace the somewhat surprising IPV4ONLY */
case ZMQ_IPV6:
if (is_int && (value == 0 || value == 1))
if (is_int && (value == 0 || value == 1)) {
ipv6 = (value != 0);
else
valid = false;
return 0;
}
break;
case ZMQ_TCP_KEEPALIVE:
if (is_int && (value >= -1 || value <= 1))
if (is_int && (value >= -1 || value <= 1)) {
tcp_keepalive = value;
else
valid = false;
return 0;
}
break;
case ZMQ_TCP_KEEPALIVE_CNT:
if (is_int && (value == -1 || value >= 0))
if (is_int && (value == -1 || value >= 0)) {
tcp_keepalive_cnt = value;
else
valid = false;
return 0;
}
break;
case ZMQ_TCP_KEEPALIVE_IDLE:
if (is_int && (value == -1 || value >= 0))
if (is_int && (value == -1 || value >= 0)) {
tcp_keepalive_idle = value;
else
valid = false;
return 0;
}
break;
case ZMQ_TCP_KEEPALIVE_INTVL:
if (is_int && (value == -1 || value >= 0))
if (is_int && (value == -1 || value >= 0)) {
tcp_keepalive_intvl = value;
else
valid = false;
return 0;
}
break;
case ZMQ_IMMEDIATE:
if (is_int && (value == 0 || value == 1))
if (is_int && (value == 0 || value == 1)) {
immediate = value;
else
valid = false;
return 0;
}
break;
case ZMQ_TCP_ACCEPT_FILTER:
if (optvallen_ == 0 && optval_ == NULL)
if (optvallen_ == 0 && optval_ == NULL) {
tcp_accept_filters.clear ();
return 0;
}
else
if (optvallen_ < 1 || optvallen_ > 255 || optval_ == NULL || *((const char*) optval_) == 0)
valid = false;
else {
if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL && *((const char*) optval_) != 0) {
std::string filter_str ((const char *) optval_, optvallen_);
tcp_address_mask_t mask;
int rc = mask.resolve (filter_str.c_str (), ipv6);
if (rc == 0)
if (rc == 0) {
tcp_accept_filters.push_back (mask);
else
valid = false;
return 0;
}
}
break;
case ZMQ_PLAIN_SERVER:
if (is_int && (value == 0 || value == 1)) {
plain_server = value;
mechanism = value? ZMQ_PLAIN: ZMQ_NULL;
return 0;
}
break;
case ZMQ_PLAIN_USERNAME:
if (optvallen_ == 0 && optval_ == NULL) {
mechanism = ZMQ_NULL;
return 0;
}
else
if (optvallen_ >= 0 && optvallen_ < 256 && optval_ != NULL) {
plain_username.assign ((const char *) optval_, optvallen_);
plain_server = false;
mechanism = ZMQ_PLAIN;
return 0;
}
break;
case ZMQ_PLAIN_PASSWORD:
if (optvallen_ == 0 && optval_ == NULL) {
mechanism = ZMQ_NULL;
return 0;
}
else
if (optvallen_ >= 0 && optvallen_ < 256 && optval_ != NULL) {
plain_password.assign ((const char *) optval_, optvallen_);
plain_server = false;
mechanism = ZMQ_PLAIN;
return 0;
}
break;
default:
valid = false;
break;
}
if (valid)
return 0;
else {
errno = EINVAL;
return -1;
}
errno = EINVAL;
return -1;
}
int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
{
bool is_int = (*optvallen_ == sizeof (int));
int *value = (int *) optval_;
switch (option_) {
case ZMQ_SNDHWM:
if (is_int) {
*value = sndhwm;
return 0;
}
break;
case ZMQ_SNDHWM:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = sndhwm;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_RCVHWM:
if (is_int) {
*value = rcvhwm;
return 0;
}
break;
case ZMQ_RCVHWM:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = rcvhwm;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_AFFINITY:
if (*optvallen_ == sizeof (uint64_t)) {
*((uint64_t *) optval_) = affinity;
return 0;
}
break;
case ZMQ_AFFINITY:
if (*optvallen_ < sizeof (uint64_t)) {
errno = EINVAL;
return -1;
}
*((uint64_t*) optval_) = affinity;
*optvallen_ = sizeof (uint64_t);
return 0;
case ZMQ_IDENTITY:
if (*optvallen_ >= identity_size) {
memcpy (optval_, identity, identity_size);
*optvallen_ = identity_size;
return 0;
}
break;
case ZMQ_IDENTITY:
if (*optvallen_ < identity_size) {
errno = EINVAL;
return -1;
}
memcpy (optval_, identity, identity_size);
*optvallen_ = identity_size;
return 0;
case ZMQ_RATE:
if (is_int) {
*value = rate;
return 0;
}
break;
case ZMQ_RATE:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = rate;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_RECOVERY_IVL:
if (is_int) {
*value = recovery_ivl;
return 0;
}
break;
case ZMQ_RECOVERY_IVL:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = recovery_ivl;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_SNDBUF:
if (is_int) {
*value = sndbuf;
return 0;
}
break;
case ZMQ_SNDBUF:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = sndbuf;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_RCVBUF:
if (is_int) {
*value = rcvbuf;
return 0;
}
break;
case ZMQ_RCVBUF:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = rcvbuf;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_TYPE:
if (is_int) {
*value = type;
return 0;
}
break;
case ZMQ_TYPE:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = type;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_LINGER:
if (is_int) {
*value = linger;
return 0;
}
break;
case ZMQ_LINGER:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = linger;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_RECONNECT_IVL:
if (is_int) {
*value = reconnect_ivl;
return 0;
}
break;
case ZMQ_RECONNECT_IVL:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = reconnect_ivl;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_RECONNECT_IVL_MAX:
if (is_int) {
*value = reconnect_ivl_max;
return 0;
}
break;
case ZMQ_RECONNECT_IVL_MAX:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = reconnect_ivl_max;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_BACKLOG:
if (is_int) {
*value = backlog;
return 0;
}
break;
case ZMQ_BACKLOG:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = backlog;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_MAXMSGSIZE:
if (*optvallen_ == sizeof (int64_t)) {
*((int64_t *) optval_) = maxmsgsize;
*optvallen_ = sizeof (int64_t);
return 0;
}
break;
case ZMQ_MAXMSGSIZE:
if (*optvallen_ < sizeof (int64_t)) {
errno = EINVAL;
return -1;
}
*((int64_t*) optval_) = maxmsgsize;
*optvallen_ = sizeof (int64_t);
return 0;
case ZMQ_MULTICAST_HOPS:
if (is_int) {
*value = multicast_hops;
return 0;
}
break;
case ZMQ_MULTICAST_HOPS:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = multicast_hops;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_RCVTIMEO:
if (is_int) {
*value = rcvtimeo;
return 0;
}
break;
case ZMQ_RCVTIMEO:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = rcvtimeo;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_SNDTIMEO:
if (is_int) {
*value = sndtimeo;
return 0;
}
break;
case ZMQ_SNDTIMEO:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = sndtimeo;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_IPV4ONLY:
if (is_int) {
*value = 1 - ipv6;
return 0;
}
break;
case ZMQ_IPV6:
if (is_int) {
*value = ipv6;
return 0;
}
break;
case ZMQ_IPV4ONLY:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = 1 - ipv6;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_IMMEDIATE:
if (is_int) {
*value = immediate;
return 0;
}
break;
case ZMQ_TCP_KEEPALIVE:
if (is_int) {
*value = tcp_keepalive;
return 0;
}
break;
case ZMQ_TCP_KEEPALIVE_CNT:
if (is_int) {
*value = tcp_keepalive_cnt;
return 0;
}
break;
case ZMQ_TCP_KEEPALIVE_IDLE:
if (is_int) {
*value = tcp_keepalive_idle;
return 0;
}
break;
case ZMQ_TCP_KEEPALIVE_INTVL:
if (is_int) {
*value = tcp_keepalive_intvl;
return 0;
}
break;
case ZMQ_LAST_ENDPOINT:
if (*optvallen_ >= last_endpoint.size () + 1) {
memcpy (optval_, last_endpoint.c_str (), last_endpoint.size () + 1);
*optvallen_ = last_endpoint.size () + 1;
return 0;
}
break;
case ZMQ_IPV6:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = ipv6;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_IMMEDIATE:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = immediate;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_TCP_KEEPALIVE:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = tcp_keepalive;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_TCP_KEEPALIVE_CNT:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = tcp_keepalive_cnt;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_TCP_KEEPALIVE_IDLE:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = tcp_keepalive_idle;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_TCP_KEEPALIVE_INTVL:
if (*optvallen_ < sizeof (int)) {
errno = EINVAL;
return -1;
}
*((int*) optval_) = tcp_keepalive_intvl;
*optvallen_ = sizeof (int);
return 0;
case ZMQ_LAST_ENDPOINT:
/* don't allow string which cannot contain the entire message */
if (*optvallen_ < last_endpoint.size() + 1) {
errno = EINVAL;
return -1;
}
memcpy (optval_, last_endpoint.c_str(), last_endpoint.size()+1);
*optvallen_ = last_endpoint.size()+1;
return 0;
case ZMQ_MECHANISM:
if (is_int) {
*value = mechanism;
return 0;
}
break;
case ZMQ_PLAIN_SERVER:
if (is_int) {
*value = plain_server;
return 0;
}
break;
case ZMQ_PLAIN_USERNAME:
if (*optvallen_ >= plain_username.size () + 1) {
memcpy (optval_, plain_username.c_str (), plain_username.size () + 1);
*optvallen_ = plain_username.size () + 1;
return 0;
}
break;
case ZMQ_PLAIN_PASSWORD:
if (*optvallen_ >= plain_password.size () + 1) {
memcpy (optval_, plain_password.c_str (), plain_password.size () + 1);
*optvallen_ = plain_password.size () + 1;
return 0;
}
break;
}
errno = EINVAL;
return -1;
}