int be_mysql_superuser(void *handle, const char *username)
{
	struct mysql_backend *conf = (struct mysql_backend *)handle;
	char *query = NULL, *u = NULL;
	long nrows, ulen;
	int issuper = FALSE;
	MYSQL_RES *res = NULL;
	MYSQL_ROW rowdata;


	if (!conf || !conf->superquery)
		return (FALSE);

    if (mysql_ping(conf->mysql)) {
        fprintf(stderr, "%s\n", mysql_error(conf->mysql));
        if (!auto_connect(conf)) {
            return (FALSE);
        }
    }

	if ((u = escape(conf, username, &ulen)) == NULL)
		return (FALSE);

	if ((query = malloc(strlen(conf->superquery) + ulen + 128)) == NULL) {
		free(u);
		return (FALSE);
	}
	sprintf(query, conf->superquery, u);
	free(u);

	// puts(query);

	if (mysql_query(conf->mysql, query)) {
		fprintf(stderr, "%s\n", mysql_error(conf->mysql));
		goto out;
	}

	res = mysql_store_result(conf->mysql);
	if ((nrows = mysql_num_rows(res)) != 1) {
		goto out;
	}

	if (mysql_num_fields(res) != 1) {
		// DEBUG fprintf(stderr, "numfields not ok\n");
		goto out;
	}

	if ((rowdata = mysql_fetch_row(res)) == NULL) {
		goto out;
	}

	issuper = atoi(rowdata[0]);

   out:

	mysql_free_result(res);
	free(query);

	return (issuper);
}
static int recv_msg(struct kiocb *iocb, struct socket *sock,
		    struct msghdr *m, size_t buf_len, int flags)
{
	struct sock *sk = sock->sk;
	struct tipc_port *tport = tipc_sk_port(sk);
	struct sk_buff *buf;
	struct tipc_msg *msg;
	long timeout;
	unsigned int sz;
	u32 err;
	int res;

	/* Catch invalid receive requests */

	if (unlikely(!buf_len))
		return -EINVAL;

	lock_sock(sk);

	if (unlikely(sock->state == SS_UNCONNECTED)) {
		res = -ENOTCONN;
		goto exit;
	}

	/* will be updated in set_orig_addr() if needed */
	m->msg_namelen = 0;

	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
restart:

	/* Look for a message in receive queue; wait if necessary */

	while (skb_queue_empty(&sk->sk_receive_queue)) {
		if (sock->state == SS_DISCONNECTING) {
			res = -ENOTCONN;
			goto exit;
		}
		if (timeout <= 0L) {
			res = timeout ? timeout : -EWOULDBLOCK;
			goto exit;
		}
		release_sock(sk);
		timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
							   tipc_rx_ready(sock),
							   timeout);
		lock_sock(sk);
	}

	/* Look at first message in receive queue */

	buf = skb_peek(&sk->sk_receive_queue);
	msg = buf_msg(buf);
	sz = msg_data_sz(msg);
	err = msg_errcode(msg);

	/* Complete connection setup for an implied connect */

	if (unlikely(sock->state == SS_CONNECTING)) {
		res = auto_connect(sock, msg);
		if (res)
			goto exit;
	}

	/* Discard an empty non-errored message & try again */

	if ((!sz) && (!err)) {
		advance_rx_queue(sk);
		goto restart;
	}

	/* Capture sender's address (optional) */

	set_orig_addr(m, msg);

	/* Capture ancillary data (optional) */

	res = anc_data_recv(m, msg, tport);
	if (res)
		goto exit;

	/* Capture message data (if valid) & compute return value (always) */

	if (!err) {
		if (unlikely(buf_len < sz)) {
			sz = buf_len;
			m->msg_flags |= MSG_TRUNC;
		}
		res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
					      m->msg_iov, sz);
		if (res)
			goto exit;
		res = sz;
	} else {
		if ((sock->state == SS_READY) ||
		    ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
			res = 0;
		else
			res = -ECONNRESET;
	}

	/* Consume received message (optional) */

	if (likely(!(flags & MSG_PEEK))) {
		if ((sock->state != SS_READY) &&
		    (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
			tipc_acknowledge(tport->ref, tport->conn_unacked);
		advance_rx_queue(sk);
	}
exit:
	release_sock(sk);
	return res;
}
static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
		   int flags)
{
	struct sock *sk = sock->sk;
	struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
	struct msghdr m = {NULL,};
	struct sk_buff *buf;
	struct tipc_msg *msg;
	unsigned int timeout;
	int res;

	lock_sock(sk);

	/* For now, TIPC does not allow use of connect() with DGRAM/RDM types */

	if (sock->state == SS_READY) {
		res = -EOPNOTSUPP;
		goto exit;
	}

	/* For now, TIPC does not support the non-blocking form of connect() */

	if (flags & O_NONBLOCK) {
		res = -EOPNOTSUPP;
		goto exit;
	}

	/* Issue Posix-compliant error code if socket is in the wrong state */

	if (sock->state == SS_LISTENING) {
		res = -EOPNOTSUPP;
		goto exit;
	}
	if (sock->state == SS_CONNECTING) {
		res = -EALREADY;
		goto exit;
	}
	if (sock->state != SS_UNCONNECTED) {
		res = -EISCONN;
		goto exit;
	}

	/*
	 * Reject connection attempt using multicast address
	 *
	 * Note: send_msg() validates the rest of the address fields,
	 *       so there's no need to do it here
	 */

	if (dst->addrtype == TIPC_ADDR_MCAST) {
		res = -EINVAL;
		goto exit;
	}

	/* Reject any messages already in receive queue (very unlikely) */

	reject_rx_queue(sk);

	/* Send a 'SYN-' to destination */

	m.msg_name = dest;
	m.msg_namelen = destlen;
	res = send_msg(NULL, sock, &m, 0);
	if (res < 0)
		goto exit;

	/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */

	timeout = tipc_sk(sk)->conn_timeout;
	release_sock(sk);
	res = wait_event_interruptible_timeout(*sk_sleep(sk),
			(!skb_queue_empty(&sk->sk_receive_queue) ||
			(sock->state != SS_CONNECTING)),
			timeout ? (long)msecs_to_jiffies(timeout)
				: MAX_SCHEDULE_TIMEOUT);
	lock_sock(sk);

	if (res > 0) {
		buf = skb_peek(&sk->sk_receive_queue);
		if (buf != NULL) {
			msg = buf_msg(buf);
			res = auto_connect(sock, msg);
			if (!res) {
				if (!msg_data_sz(msg))
					advance_rx_queue(sk);
			}
		} else {
			if (sock->state == SS_CONNECTED)
				res = -EISCONN;
			else
				res = -ECONNREFUSED;
		}
	} else {
		if (res == 0)
			res = -ETIMEDOUT;
		else
			; /* leave "res" unchanged */
		sock->state = SS_DISCONNECTING;
	}

exit:
	release_sock(sk);
	return res;
}
/**
 * filter_connect - Handle all incoming messages for a connection-based socket
 * @tsock: TIPC socket
 * @msg: message
 *
 * Returns TIPC error status code and socket error status code
 * once it encounters some errors
 */
static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
{
	struct socket *sock = tsock->sk.sk_socket;
	struct tipc_msg *msg = buf_msg(*buf);
	struct sock *sk = &tsock->sk;
	u32 retval = TIPC_ERR_NO_PORT;
	int res;

	if (msg_mcast(msg))
		return retval;

	switch ((int)sock->state) {
	case SS_CONNECTED:
		/* Accept only connection-based messages sent by peer */
		if (msg_connected(msg) && tipc_port_peer_msg(tsock->p, msg)) {
			if (unlikely(msg_errcode(msg))) {
				sock->state = SS_DISCONNECTING;
				__tipc_disconnect(tsock->p);
			}
			retval = TIPC_OK;
		}
		break;
	case SS_CONNECTING:
		/* Accept only ACK or NACK message */
		if (unlikely(msg_errcode(msg))) {
			sock->state = SS_DISCONNECTING;
			sk->sk_err = ECONNREFUSED;
			retval = TIPC_OK;
			break;
		}

		if (unlikely(!msg_connected(msg)))
			break;

		res = auto_connect(sock, msg);
		if (res) {
			sock->state = SS_DISCONNECTING;
			sk->sk_err = -res;
			retval = TIPC_OK;
			break;
		}

		/* If an incoming message is an 'ACK-', it should be
		 * discarded here because it doesn't contain useful
		 * data. In addition, we should try to wake up
		 * connect() routine if sleeping.
		 */
		if (msg_data_sz(msg) == 0) {
			kfree_skb(*buf);
			*buf = NULL;
			if (waitqueue_active(sk_sleep(sk)))
				wake_up_interruptible(sk_sleep(sk));
		}
		retval = TIPC_OK;
		break;
	case SS_LISTENING:
	case SS_UNCONNECTED:
		/* Accept only SYN message */
		if (!msg_connected(msg) && !(msg_errcode(msg)))
			retval = TIPC_OK;
		break;
	case SS_DISCONNECTING:
		break;
	default:
		pr_err("Unknown socket state %u\n", sock->state);
	}
	return retval;
}
Exemple #5
0
static int recv_msg(struct kiocb *iocb, struct socket *sock,
		    struct msghdr *m, size_t buf_len, int flags)
{
	struct tipc_sock *tsock = tipc_sk(sock->sk);
	struct sk_buff *buf;
	struct tipc_msg *msg;
	unsigned int q_len;
	unsigned int sz;
	u32 err;
	int res;

	/* Currently doesn't support receiving into multiple iovec entries */

	if (m->msg_iovlen != 1)
		return -EOPNOTSUPP;

	/* Catch invalid receive attempts */

	if (unlikely(!buf_len))
		return -EINVAL;

	if (sock->type == SOCK_SEQPACKET) {
		if (unlikely(sock->state == SS_UNCONNECTED))
			return -ENOTCONN;
		if (unlikely((sock->state == SS_DISCONNECTING) &&
			     (skb_queue_len(&sock->sk->sk_receive_queue) == 0)))
			return -ENOTCONN;
	}

	/* Look for a message in receive queue; wait if necessary */

	if (unlikely(down_interruptible(&tsock->sem)))
		return -ERESTARTSYS;

restart:
	if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
		     (flags & MSG_DONTWAIT))) {
		res = -EWOULDBLOCK;
		goto exit;
	}

	if ((res = wait_event_interruptible(
		*sock->sk->sk_sleep,
		((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
		 (sock->state == SS_DISCONNECTING))) )) {
		goto exit;
	}

	/* Catch attempt to receive on an already terminated connection */
	/* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */

	if (!q_len) {
		res = -ENOTCONN;
		goto exit;
	}

	/* Get access to first message in receive queue */

	buf = skb_peek(&sock->sk->sk_receive_queue);
	msg = buf_msg(buf);
	sz = msg_data_sz(msg);
	err = msg_errcode(msg);

	/* Complete connection setup for an implied connect */

	if (unlikely(sock->state == SS_CONNECTING)) {
		if ((res = auto_connect(sock, tsock, msg)))
			goto exit;
	}

	/* Discard an empty non-errored message & try again */

	if ((!sz) && (!err)) {
		advance_queue(tsock);
		goto restart;
	}

	/* Capture sender's address (optional) */

	set_orig_addr(m, msg);

	/* Capture ancillary data (optional) */

	if ((res = anc_data_recv(m, msg, tsock->p)))
		goto exit;

	/* Capture message data (if valid) & compute return value (always) */

	if (!err) {
		if (unlikely(buf_len < sz)) {
			sz = buf_len;
			m->msg_flags |= MSG_TRUNC;
		}
		if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
					  sz))) {
			res = -EFAULT;
			goto exit;
		}
		res = sz;
	} else {
		if ((sock->state == SS_READY) ||
		    ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
			res = 0;
		else
			res = -ECONNRESET;
	}

	/* Consume received message (optional) */

	if (likely(!(flags & MSG_PEEK))) {
		if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
			tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
		advance_queue(tsock);
	}
exit:
	up(&tsock->sem);
	return res;
}
Exemple #6
0
static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
		   int flags)
{
   struct tipc_sock *tsock = tipc_sk(sock->sk);
   struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
   struct msghdr m = {NULL,};
   struct sk_buff *buf;
   struct tipc_msg *msg;
   int res;

   /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */

   if (sock->state == SS_READY)
	   return -EOPNOTSUPP;

   /* Issue Posix-compliant error code if socket is in the wrong state */

   if (sock->state == SS_LISTENING)
	   return -EOPNOTSUPP;
   if (sock->state == SS_CONNECTING)
	   return -EALREADY;
   if (sock->state != SS_UNCONNECTED)
	   return -EISCONN;

   /*
    * Reject connection attempt using multicast address
    *
    * Note: send_msg() validates the rest of the address fields,
    *       so there's no need to do it here
    */

   if (dst->addrtype == TIPC_ADDR_MCAST)
	   return -EINVAL;

   /* Send a 'SYN-' to destination */

   m.msg_name = dest;
   m.msg_namelen = destlen;
   if ((res = send_msg(NULL, sock, &m, 0)) < 0) {
	   sock->state = SS_DISCONNECTING;
	   return res;
   }

   if (down_interruptible(&tsock->sem))
	   return -ERESTARTSYS;

   /* Wait for destination's 'ACK' response */

   res = wait_event_interruptible_timeout(*sock->sk->sk_sleep,
					  skb_queue_len(&sock->sk->sk_receive_queue),
					  sock->sk->sk_rcvtimeo);
   buf = skb_peek(&sock->sk->sk_receive_queue);
   if (res > 0) {
	   msg = buf_msg(buf);
	   res = auto_connect(sock, tsock, msg);
	   if (!res) {
		   if (!msg_data_sz(msg))
			   advance_queue(tsock);
	   }
   } else {
	   if (res == 0) {
		   res = -ETIMEDOUT;
	   } else
		   { /* leave "res" unchanged */ }
	   sock->state = SS_DISCONNECTING;
   }

   up(&tsock->sem);
   return res;
}
static int connect(struct socket *sock, struct sockaddr *dest, int destlen, 
		   int flags)
{
   struct tipc_sock *tsock = tipc_sk(sock->sk);
   struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
   struct msghdr m = {0,};
   struct sk_buff *buf;
   struct tipc_msg *msg;
   int res;

   /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */

   if (sock->state == SS_READY)
	   return -EOPNOTSUPP;

   /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */
   if (sock->state == SS_LISTENING)
	   return -EOPNOTSUPP;
   if (sock->state == SS_CONNECTING)
	   return -EALREADY;
   if (sock->state != SS_UNCONNECTED)
           return -EISCONN;

   if ((dst->family != AF_TIPC) ||
       ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID)))
           return -EINVAL;

   /* Send a 'SYN-' to destination */

   m.msg_name = dest;
   if ((res = send_msg(0, sock, &m, 0)) < 0) {
	   sock->state = SS_DISCONNECTING;
	   return res;
   }

   if (down_interruptible(&tsock->sem)) 
           return -ERESTARTSYS;
	
   /* Wait for destination's 'ACK' response */

   res = wait_event_interruptible_timeout(*sock->sk->sk_sleep,
                                          skb_queue_len(&sock->sk->sk_receive_queue),
					  sock->sk->sk_rcvtimeo);
   buf = skb_peek(&sock->sk->sk_receive_queue);
   if (res > 0) {
	   msg = buf_msg(buf);
           res = auto_connect(sock, tsock, msg);
           if (!res) {
		   if (dst->addrtype == TIPC_ADDR_NAME) {
			   tsock->p->conn_type = dst->addr.name.name.type;
			   tsock->p->conn_instance = dst->addr.name.name.instance;
		   }
		   if (!msg_data_sz(msg))
			   advance_queue(tsock);
	   }
   } else {
	   if (res == 0) {
		   res = -ETIMEDOUT;
	   } else
	           { /* leave "res" unchanged */ }
	   sock->state = SS_DISCONNECTING;
   }

   up(&tsock->sem);
   return res;
}
int be_mysql_aclcheck(void *handle, const char *username, const char *topic, int acc)
{
	struct mysql_backend *conf = (struct mysql_backend *)handle;
	char *query = NULL, *u = NULL, *v;
	long ulen;
	int match = 0;
	bool bf;
	MYSQL_RES *res = NULL;
	MYSQL_ROW rowdata;

	if (!conf || !conf->aclquery)
		return (FALSE);

	if (mysql_ping(conf->mysql)) {
		fprintf(stderr, "%s\n", mysql_error(conf->mysql));
		if (!auto_connect(conf)) {
			return (FALSE);
		}
	}

	if ((u = escape(conf, username, &ulen)) == NULL)
		return (FALSE);

	if ((query = malloc(strlen(conf->aclquery) + ulen + 128)) == NULL) {
		free(u);
		return (FALSE);
	}
	sprintf(query, conf->aclquery, u, acc);
	free(u);

	//_log(LOG_DEBUG, "SQL: %s", query);

	if (mysql_query(conf->mysql, query)) {
		_log(LOG_NOTICE, "%s", mysql_error(conf->mysql));
		goto out;
	}

	res = mysql_store_result(conf->mysql);
	if (mysql_num_fields(res) != 1) {
		fprintf(stderr, "numfields not ok\n");
		goto out;
	}

	while (match == 0 && (rowdata = mysql_fetch_row(res)) != NULL) {
		if ((v = rowdata[0]) != NULL) {

			/* Check mosquitto_match_topic. If true,
			 * if true, set match and break out of loop. */

			// FIXME: does this need special work for %c and %u ???
			mosquitto_topic_matches_sub(v, topic, &bf);
			match |= bf;
			_log(LOG_DEBUG, "  mysql: topic_matches(%s, %s) == %d",
				topic, v, bf);
		}
	}

   out:

	mysql_free_result(res);
	free(query);

	return (match);
}
char *be_mysql_getuser(void *handle, const char *username, const char *password, int *authenticated)
{
	struct mysql_backend *conf = (struct mysql_backend *)handle;
	char *query = NULL, *u = NULL, *value = NULL, *v;
	long nrows, ulen;
	MYSQL_RES *res = NULL;
	MYSQL_ROW rowdata;

	if (!conf || !conf->userquery || !username || !*username)
		return (NULL);

    if (mysql_ping(conf->mysql)) {
        fprintf(stderr, "%s\n", mysql_error(conf->mysql));
        if (!auto_connect(conf)) {
            return (NULL);
        }
    }

	if ((u = escape(conf, username, &ulen)) == NULL)
		return (NULL);

	if ((query = malloc(strlen(conf->userquery) + ulen + 128)) == NULL) {
		free(u);
		return (NULL);
	}
	sprintf(query, conf->userquery, u);
	free(u);

	// DEBUG puts(query);

	if (mysql_query(conf->mysql, query)) {
		fprintf(stderr, "%s\n", mysql_error(conf->mysql));
		goto out;
	}

	res = mysql_store_result(conf->mysql);
	if ((nrows = mysql_num_rows(res)) != 1) {
		// DEBUG fprintf(stderr, "rowcount = %ld; not ok\n", nrows);
		goto out;
	}

	if (mysql_num_fields(res) != 1) {
		// DEBUG fprintf(stderr, "numfields not ok\n");
		goto out;
	}

	if ((rowdata = mysql_fetch_row(res)) == NULL) {
		goto out;
	}

	v = rowdata[0];
	value = (v) ? strdup(v) : NULL;


   out:

	mysql_free_result(res);
	free(query);

	return (value);
}