Example #1
0
static
int serve_request_main(sec_mod_st *sec, int fd, uint8_t *buffer, unsigned buffer_size)
{
	int ret, e;
	uint8_t cmd;
	size_t length;
	void *pool = buffer;

	/* read request */
	ret = recv_msg_headers(fd, &cmd, MAIN_SEC_MOD_TIMEOUT);
	if (ret < 0) {
		seclog(sec, LOG_ERR, "error receiving msg head from main");
		ret = ERR_BAD_COMMAND;
		goto leave;
	}

	length = ret;

	seclog(sec, LOG_DEBUG, "received request %s", cmd_request_to_str(cmd));
	if (cmd <= MIN_SECM_CMD || cmd >= MAX_SECM_CMD) {
		seclog(sec, LOG_ERR, "received invalid message from main of %u bytes (cmd: %u)\n",
		      (unsigned)length, (unsigned)cmd);
		return ERR_BAD_COMMAND;
	}

	if (length > buffer_size) {
		seclog(sec, LOG_ERR, "received too big message (%d)", (int)length);
		ret = ERR_BAD_COMMAND;
		goto leave;
	}

	/* read the body */
	ret = force_read_timeout(fd, buffer, length, MAIN_SEC_MOD_TIMEOUT);
	if (ret < 0) {
		e = errno;
		seclog(sec, LOG_ERR, "error receiving msg body of cmd %u with length %u: %s",
		       cmd, (unsigned)length, strerror(e));
		ret = ERR_BAD_COMMAND;
		goto leave;
	}

	ret = process_packet_from_main(pool, fd, sec, cmd, buffer, ret);
	if (ret < 0) {
		seclog(sec, LOG_ERR, "error processing data for '%s' command (%d)", cmd_request_to_str(cmd), ret);
	}
	
 leave:
	return ret;
}
Example #2
0
static
int serve_request_worker(sec_mod_st *sec, int cfd, pid_t pid, uint8_t *buffer, unsigned buffer_size)
{
	int ret, e;
	uint8_t cmd;
	size_t length;
	void *pool = buffer;

	/* read request */
	ret = recv_msg_headers(cfd, &cmd, MAX_WAIT_SECS);
	if (ret < 0) {
		seclog(sec, LOG_DEBUG, "error receiving msg head from worker");
		goto leave;
	}

	length = ret;

	if (length > buffer_size) {
		seclog(sec, LOG_INFO, "too big message (%d)", (int)length);
		ret = -1;
		goto leave;
	}

	/* read the body */
	ret = force_read_timeout(cfd, buffer, length, MAX_WAIT_SECS);
	if (ret < 0) {
		e = errno;
		seclog(sec, LOG_INFO, "error receiving msg body: %s",
		       strerror(e));
		ret = -1;
		goto leave;
	}

	ret = process_worker_packet(pool, cfd, pid, sec, cmd, buffer, ret);
	if (ret < 0) {
		seclog(sec, LOG_INFO, "error processing data for '%s' command (%d)", cmd_request_to_str(cmd), ret);
	}
	
 leave:
	return ret;
}
Example #3
0
int handle_commands_from_main(struct worker_st *ws)
{
	uint8_t cmd;
	size_t length;
	uint8_t cmd_data[1536];
	UdpFdMsg *tmsg = NULL;
	int ret;
	int fd = -1;
	/*int cmd_data_len;*/

	memset(&cmd_data, 0, sizeof(cmd_data));

	ret = recv_msg_data(ws->cmd_fd, &cmd, cmd_data, sizeof(cmd_data), &fd);
	if (ret < 0) {
		oclog(ws, LOG_DEBUG, "cannot obtain data from command socket");
		exit_worker_reason(ws, REASON_SERVER_DISCONNECT);
	}

	if (ret == 0) {
		oclog(ws, LOG_ERR, "parent terminated");
		return ERR_NO_CMD_FD;
	}

	length = ret;

	oclog(ws, LOG_DEBUG, "worker received message %s of %u bytes\n", cmd_request_to_str(cmd), (unsigned)length);

	/*cmd_data_len = ret - 1;*/

	switch(cmd) {
		case CMD_TERMINATE:
			exit_worker_reason(ws, REASON_SERVER_DISCONNECT);
		case CMD_UDP_FD: {
			unsigned has_hello = 1;

			if (ws->udp_state != UP_WAIT_FD) {
				oclog(ws, LOG_DEBUG, "received another a UDP fd!");
			}

			tmsg = udp_fd_msg__unpack(NULL, length, cmd_data);
			if (tmsg) {
				has_hello = tmsg->hello;
			}

			if (fd == -1) {
				oclog(ws, LOG_ERR, "received UDP fd message of wrong type");
				goto udp_fd_fail;
			}

			set_non_block(fd);

			if (has_hello == 0) {
				/* check if the first packet received is a valid one -
				 * if not discard the new fd */
				if (!recv_from_new_fd(ws, fd, tmsg)) {
					oclog(ws, LOG_INFO, "received UDP fd message but its session has invalid data!");
					if (tmsg)
						udp_fd_msg__free_unpacked(tmsg, NULL);
					close(fd);
					return 0;
				}
				RESET_DTLS_MTU(ws);
			} else { /* received client hello */
				ws->udp_state = UP_SETUP;
			}

			if (ws->dtls_tptr.fd != -1)
				close(ws->dtls_tptr.fd);
			if (ws->dtls_tptr.msg != NULL)
				udp_fd_msg__free_unpacked(ws->dtls_tptr.msg, NULL);

			ws->dtls_tptr.msg = tmsg;
			ws->dtls_tptr.fd = fd;

			oclog(ws, LOG_DEBUG, "received new UDP fd and connected to peer");
			return 0;

			}
			break;
		default:
			oclog(ws, LOG_ERR, "unknown CMD 0x%x", (unsigned)cmd);
			exit_worker_reason(ws, REASON_ERROR);
	}

	return 0;

udp_fd_fail:
	if (tmsg)
		udp_fd_msg__free_unpacked(tmsg, NULL);
	if (ws->dtls_tptr.fd == -1)
		ws->udp_state = UP_DISABLED;

	return -1;
}
Example #4
0
static
int process_packet_from_main(void *pool, int fd, sec_mod_st * sec, cmd_request_t cmd,
		   uint8_t * buffer, size_t buffer_size)
{
	gnutls_datum_t data;
	int ret;
	PROTOBUF_ALLOCATOR(pa, pool);

	seclog(sec, LOG_DEBUG, "cmd [size=%d] %s\n", (int)buffer_size,
	       cmd_request_to_str(cmd));
	data.data = buffer;
	data.size = buffer_size;

	switch (cmd) {
	case CMD_SECM_LIST_COOKIES:
		handle_secm_list_cookies_reply(pool, fd, sec);

		return 0;
	case CMD_SECM_BAN_IP_REPLY:{
		BanIpReplyMsg *msg = NULL;

		msg =
		    ban_ip_reply_msg__unpack(&pa, data.size,
					     data.data);
		if (msg == NULL) {
			seclog(sec, LOG_INFO, "error unpacking auth ban ip reply\n");
			return ERR_BAD_COMMAND;
		}

		handle_sec_auth_ban_ip_reply(sec, msg);
		ban_ip_reply_msg__free_unpacked(msg, &pa);

		return 0;
	}
	case CMD_SECM_SESSION_OPEN:{
			SecmSessionOpenMsg *msg;

			msg =
			    secm_session_open_msg__unpack(&pa, data.size,
						      data.data);
			if (msg == NULL) {
				seclog(sec, LOG_INFO, "error unpacking session open\n");
				return ERR_BAD_COMMAND;
			}

			ret = handle_secm_session_open_cmd(sec, fd, msg);
			secm_session_open_msg__free_unpacked(msg, &pa);

			return ret;
		}
	case CMD_SECM_SESSION_CLOSE:{
			SecmSessionCloseMsg *msg;

			msg =
			    secm_session_close_msg__unpack(&pa, data.size,
						      data.data);
			if (msg == NULL) {
				seclog(sec, LOG_INFO, "error unpacking session close\n");
				return ERR_BAD_COMMAND;
			}

			ret = handle_secm_session_close_cmd(sec, fd, msg);
			secm_session_close_msg__free_unpacked(msg, &pa);

			return ret;
		}
	default:
		seclog(sec, LOG_WARNING, "unknown type 0x%.2x", cmd);
		return ERR_BAD_COMMAND;
	}

	return 0;
}
Example #5
0
static
int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st * sec, cmd_request_t cmd,
		   uint8_t * buffer, size_t buffer_size)
{
	unsigned i;
	gnutls_datum_t data, out;
	int ret;
	SecOpMsg *op;
	PROTOBUF_ALLOCATOR(pa, pool);

	seclog(sec, LOG_DEBUG, "cmd [size=%d] %s\n", (int)buffer_size,
	       cmd_request_to_str(cmd));
	data.data = buffer;
	data.size = buffer_size;

	switch (cmd) {
	case CMD_SEC_SIGN:
	case CMD_SEC_DECRYPT:
		op = sec_op_msg__unpack(&pa, data.size, data.data);
		if (op == NULL) {
			seclog(sec, LOG_INFO, "error unpacking sec op\n");
			return -1;
		}

		i = op->key_idx;
		if (op->has_key_idx == 0 || i >= sec->key_size) {
			seclog(sec, LOG_INFO,
			       "received out-of-bounds key index (%d)", i);
			return -1;
		}

		data.data = op->data.data;
		data.size = op->data.len;

		if (cmd == CMD_SEC_DECRYPT) {
			ret =
			    gnutls_privkey_decrypt_data(sec->key[i], 0, &data,
							&out);
		} else {
#if GNUTLS_VERSION_NUMBER >= 0x030200
			ret =
			    gnutls_privkey_sign_hash(sec->key[i], 0,
						     GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA,
						     &data, &out);
#else
			ret =
			    gnutls_privkey_sign_raw_data(sec->key[i], 0, &data,
							 &out);
#endif
		}
		sec_op_msg__free_unpacked(op, &pa);

		if (ret < 0) {
			seclog(sec, LOG_INFO, "error in crypto operation: %s",
			       gnutls_strerror(ret));
			return -1;
		}

		ret = handle_op(pool, cfd, sec, cmd, out.data, out.size);
		gnutls_free(out.data);

		return ret;

	case CMD_SEC_CLI_STATS:{
			CliStatsMsg *tmsg;

			tmsg = cli_stats_msg__unpack(&pa, data.size, data.data);
			if (tmsg == NULL) {
				seclog(sec, LOG_ERR, "error unpacking data");
				return -1;
			}

			ret = handle_sec_auth_stats_cmd(sec, tmsg, pid);
			cli_stats_msg__free_unpacked(tmsg, &pa);
			return ret;
		}
		break;

	case CMD_SEC_AUTH_INIT:{
			SecAuthInitMsg *auth_init;

			auth_init =
			    sec_auth_init_msg__unpack(&pa, data.size,
						      data.data);
			if (auth_init == NULL) {
				seclog(sec, LOG_INFO, "error unpacking auth init\n");
				return -1;
			}

			ret = handle_sec_auth_init(cfd, sec, auth_init, pid);
			sec_auth_init_msg__free_unpacked(auth_init, &pa);
			return ret;
		}
	case CMD_SEC_AUTH_CONT:{
			SecAuthContMsg *auth_cont;

			auth_cont =
			    sec_auth_cont_msg__unpack(&pa, data.size,
						      data.data);
			if (auth_cont == NULL) {
				seclog(sec, LOG_INFO, "error unpacking auth cont\n");
				return -1;
			}

			ret = handle_sec_auth_cont(cfd, sec, auth_cont);
			sec_auth_cont_msg__free_unpacked(auth_cont, &pa);
			return ret;
		}
	case RESUME_STORE_REQ:{
			SessionResumeStoreReqMsg *smsg;

			smsg =
			    session_resume_store_req_msg__unpack(&pa, buffer_size,
								 buffer);
			if (smsg == NULL) {
				seclog(sec, LOG_ERR, "error unpacking data");
				return ERR_BAD_COMMAND;
			}

			ret = handle_resume_store_req(sec, smsg);

			/* zeroize the data */
			safe_memset(buffer, 0, buffer_size);
			safe_memset(smsg->session_data.data, 0, smsg->session_data.len);

			session_resume_store_req_msg__free_unpacked(smsg, &pa);

			if (ret < 0) {
				seclog(sec, LOG_DEBUG,
				      "could not store resumption data");
			}
		}

		break;

	case RESUME_DELETE_REQ:{
			SessionResumeFetchMsg *fmsg;

			fmsg =
			    session_resume_fetch_msg__unpack(&pa, buffer_size,
							     buffer);
			if (fmsg == NULL) {
				seclog(sec, LOG_ERR, "error unpacking data");
				return ERR_BAD_COMMAND;
			}

			ret = handle_resume_delete_req(sec, fmsg);

			session_resume_fetch_msg__free_unpacked(fmsg, &pa);

			if (ret < 0) {
				seclog(sec, LOG_DEBUG,
				      "could not delete resumption data.");
			}
		}

		break;
	case RESUME_FETCH_REQ:{
			SessionResumeReplyMsg msg =
			    SESSION_RESUME_REPLY_MSG__INIT;
			SessionResumeFetchMsg *fmsg;

			/* FIXME: rate limit that */

			fmsg =
			    session_resume_fetch_msg__unpack(&pa, buffer_size,
							     buffer);
			if (fmsg == NULL) {
				seclog(sec, LOG_ERR, "error unpacking data");
				return ERR_BAD_COMMAND;
			}

			ret = handle_resume_fetch_req(sec, fmsg, &msg);

			session_resume_fetch_msg__free_unpacked(fmsg, &pa);

			if (ret < 0) {
				msg.reply =
				    SESSION_RESUME_REPLY_MSG__RESUME__REP__FAILED;
				seclog(sec, LOG_DEBUG,
				      "could not fetch resumption data.");
			} else {
				msg.reply =
				    SESSION_RESUME_REPLY_MSG__RESUME__REP__OK;
			}

			ret =
			    send_msg(pool, cfd, RESUME_FETCH_REP, &msg,
					       (pack_size_func)
					       session_resume_reply_msg__get_packed_size,
					       (pack_func)
					       session_resume_reply_msg__pack);

			if (ret < 0) {
				seclog(sec, LOG_ERR,
				      "could not send reply cmd %d.",
				      (unsigned)cmd);
				return ERR_BAD_COMMAND;
			}

		}

		break;

	default:
		seclog(sec, LOG_WARNING, "unknown type 0x%.2x", cmd);
		return -1;
	}

	return 0;
}