mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +08:00
Added occtl command to display cookies
This allows to display and examine valid cookies from occtl.
This commit is contained in:
@@ -64,7 +64,8 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
||||
proc-search.c proc-search.h http-heads.h ip-util.c ip-util.h \
|
||||
main-ban.c main-ban.h common-config.h base64-helper.c base64-helper.h \
|
||||
str.c str.h gettime.h $(CCAN_SOURCES) $(HTTP_PARSER_SOURCES) \
|
||||
sec-mod-acct.h setproctitle.c setproctitle.h sec-mod-resume.h
|
||||
sec-mod-acct.h setproctitle.c setproctitle.h sec-mod-resume.h \
|
||||
sec-mod-cookies.c
|
||||
|
||||
if ENABLE_COMPRESSION
|
||||
ocserv_SOURCES += lzs.c lzs.h
|
||||
|
||||
@@ -34,6 +34,29 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Note that meaning slightly changes depending on whether we are
|
||||
* referring to the cookie or the session itself.
|
||||
*/
|
||||
const char *ps_status_to_str(int status, unsigned cookie)
|
||||
{
|
||||
switch (status) {
|
||||
case PS_AUTH_COMPLETED:
|
||||
if (cookie)
|
||||
return "authenticated";
|
||||
else
|
||||
return "connected";
|
||||
case PS_AUTH_INIT:
|
||||
case PS_AUTH_CONT:
|
||||
return "authenticating";
|
||||
case PS_AUTH_INACTIVE:
|
||||
return "pre-auth";
|
||||
case PS_AUTH_FAILED:
|
||||
return "auth failed";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char *cmd_request_to_str(unsigned _cmd)
|
||||
{
|
||||
cmd_request_t cmd = _cmd;
|
||||
@@ -275,6 +298,91 @@ ssize_t recvmsg_timeout(int sockfd, struct msghdr * msg, int flags,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int forward_msg32(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsigned timeout)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
char data[5];
|
||||
uint32_t length;
|
||||
ssize_t left;
|
||||
uint8_t rcmd;
|
||||
struct msghdr hdr;
|
||||
union {
|
||||
struct cmsghdr cm;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} control_un;
|
||||
int ret;
|
||||
|
||||
iov[0].iov_base = &rcmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = &length;
|
||||
iov[1].iov_len = 4;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_iov = iov;
|
||||
hdr.msg_iovlen = 2;
|
||||
|
||||
hdr.msg_control = control_un.control;
|
||||
hdr.msg_controllen = sizeof(control_un.control);
|
||||
|
||||
ret = recvmsg_timeout(ifd, &hdr, 0, timeout);
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__, __LINE__,
|
||||
strerror(e));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
syslog(LOG_ERR, "%s:%u: recvmsg returned zero", __FILE__,
|
||||
__LINE__);
|
||||
return ERR_PEER_TERMINATED;
|
||||
}
|
||||
|
||||
if (rcmd != icmd) {
|
||||
syslog(LOG_ERR, "%s:%u: expected %d, received %d", __FILE__,
|
||||
__LINE__, (int)rcmd, (int)icmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
data[0] = ocmd;
|
||||
memcpy(&data[1], &length, 4);
|
||||
|
||||
/* send headers */
|
||||
ret = force_write(ofd, data, 5);
|
||||
if (ret != 5) {
|
||||
syslog(LOG_ERR, "%s:%u: cannot send headers: %s", __FILE__,
|
||||
__LINE__, strerror(errno));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
left = length;
|
||||
|
||||
while (left > 0) {
|
||||
char buf[1024];
|
||||
|
||||
ret = recv(ifd, buf, sizeof(buf), 0);
|
||||
if (ret == -1 || ret == 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
syslog(LOG_ERR, "%s:%u: cannot send between descriptors: %s", __FILE__,
|
||||
__LINE__, strerror(errno));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = force_write(ofd, buf, ret);
|
||||
if (ret == -1 || ret == 0) {
|
||||
syslog(LOG_ERR, "%s:%u: cannot send between descriptors: %s", __FILE__,
|
||||
__LINE__, strerror(errno));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
left -= ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sends message + socketfd */
|
||||
static
|
||||
int send_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
@@ -300,7 +408,8 @@ int send_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
length = get_size(msg);
|
||||
if (msg)
|
||||
length = get_size(msg);
|
||||
|
||||
if (use_32bit) {
|
||||
if (length >= UINT32_MAX)
|
||||
@@ -383,12 +492,13 @@ int send_socket_msg32(void *pool, int fd, uint8_t cmd,
|
||||
return send_socket_msg(pool, fd, cmd, socketfd, msg, get_size, pack, 1);
|
||||
}
|
||||
|
||||
int recv_socket_msg16(void *pool, int fd, uint8_t cmd,
|
||||
static
|
||||
int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
int *socketfd, void **msg, unpack_func unpack,
|
||||
unsigned timeout)
|
||||
unsigned timeout, unsigned use_32bits)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
uint16_t length;
|
||||
uint32_t length;
|
||||
uint8_t rcmd;
|
||||
struct msghdr hdr;
|
||||
uint8_t *data = NULL;
|
||||
@@ -404,7 +514,11 @@ int recv_socket_msg16(void *pool, int fd, uint8_t cmd,
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = &length;
|
||||
iov[1].iov_len = 2;
|
||||
if (use_32bits) {
|
||||
iov[1].iov_len = 4;
|
||||
} else {
|
||||
iov[1].iov_len = 2;
|
||||
}
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_iov = iov;
|
||||
@@ -433,6 +547,12 @@ int recv_socket_msg16(void *pool, int fd, uint8_t cmd,
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
if (!use_32bits) {
|
||||
uint16_t l16;
|
||||
memcpy(&l16, &length, 2);
|
||||
length = l16;
|
||||
}
|
||||
|
||||
/* try to receive socket (if any) */
|
||||
if (socketfd != NULL) {
|
||||
if ((cmptr = CMSG_FIRSTHDR(&hdr)) != NULL
|
||||
@@ -488,6 +608,21 @@ int recv_socket_msg16(void *pool, int fd, uint8_t cmd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int recv_socket_msg16(void *pool, int fd, uint8_t cmd,
|
||||
int *socketfd, void **msg, unpack_func unpack,
|
||||
unsigned timeout)
|
||||
{
|
||||
return recv_socket_msg(pool,fd, cmd, socketfd, msg, unpack, timeout, 0);
|
||||
}
|
||||
|
||||
int recv_socket_msg32(void *pool, int fd, uint8_t cmd,
|
||||
int *socketfd, void **msg, unpack_func unpack,
|
||||
unsigned timeout)
|
||||
{
|
||||
return recv_socket_msg(pool,fd, cmd, socketfd, msg, unpack, timeout, 1);
|
||||
}
|
||||
|
||||
void _talloc_free2(void *ctx, void *ptr)
|
||||
{
|
||||
talloc_free(ptr);
|
||||
|
||||
@@ -62,6 +62,8 @@ int send_socket_msg32(void *pool, int fd, uint8_t cmd,
|
||||
int socketfd,
|
||||
const void* msg, pack_size_func get_size, pack_func pack);
|
||||
|
||||
int forward_msg32(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsigned timeout);
|
||||
|
||||
inline static int send_msg16(void *pool, int fd, uint8_t cmd,
|
||||
const void *msg, pack_size_func get_size, pack_func pack)
|
||||
{
|
||||
@@ -79,6 +81,9 @@ int send_msg32(void *pool, int fd, uint8_t cmd,
|
||||
int recv_socket_msg16(void *pool, int fd, uint8_t cmd,
|
||||
int *socketfd, void** msg, unpack_func, unsigned timeout);
|
||||
|
||||
int recv_socket_msg32(void *pool, int fd, uint8_t cmd,
|
||||
int *socketfd, void** msg, unpack_func, unsigned timeout);
|
||||
|
||||
/* the timeout is in seconds */
|
||||
inline static int recv_msg16(void *pool, int fd, uint8_t cmd,
|
||||
void **msg, unpack_func unpack, unsigned timeout)
|
||||
@@ -86,6 +91,11 @@ inline static int recv_msg16(void *pool, int fd, uint8_t cmd,
|
||||
return recv_socket_msg16(pool, fd, cmd, NULL, msg, unpack, timeout);
|
||||
}
|
||||
|
||||
inline static int recv_msg32(void *pool, int fd, uint8_t cmd,
|
||||
void **msg, unpack_func unpack, unsigned timeout)
|
||||
{
|
||||
return recv_socket_msg32(pool, fd, cmd, NULL, msg, unpack, timeout);
|
||||
}
|
||||
|
||||
|
||||
const char* cmd_request_to_str(unsigned cmd);
|
||||
@@ -128,6 +138,8 @@ void ms_sleep(unsigned ms)
|
||||
nanosleep(&tv, NULL);
|
||||
}
|
||||
|
||||
const char *ps_status_to_str(int status, unsigned cookie);
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t oc_strlcpy(char *dst, char const *src, size_t siz);
|
||||
# define strlcpy oc_strlcpy
|
||||
|
||||
@@ -279,5 +279,28 @@ message secm_session_reply_msg
|
||||
required bool tls_auth_ok = 10;
|
||||
}
|
||||
|
||||
/* SEC_BAN_IP: sent from sec-mod to main */
|
||||
/* internal struct */
|
||||
message cookie_int_msg
|
||||
{
|
||||
required bytes sid = 1;
|
||||
required bool session_is_open = 2;
|
||||
required bool tls_auth_ok = 3;
|
||||
required uint32 last_modified = 4;
|
||||
required string username = 5;
|
||||
optional string groupname = 6;
|
||||
required string user_agent = 7;
|
||||
required string remote_ip = 8;
|
||||
required string psid = 9; /* printable form of sid */
|
||||
optional string status = 10; /* printable version of auth status */
|
||||
}
|
||||
|
||||
/* SECM_LIST_COOKIES - no content */
|
||||
/* SECM_LIST_COOKIES_REPLY */
|
||||
message secm_list_cookies_reply_msg
|
||||
{
|
||||
repeated cookie_int_msg cookies = 1;
|
||||
}
|
||||
|
||||
|
||||
/* SECM_BAN_IP: sent from sec-mod to main */
|
||||
/* same as: ban_ip_msg */
|
||||
|
||||
@@ -67,6 +67,8 @@ static void method_id_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_list_banned(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_list_cookies(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
|
||||
typedef void (*method_func) (method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
@@ -91,6 +93,7 @@ static const ctl_method_st methods[] = {
|
||||
ENTRY(CTL_CMD_STOP, method_stop),
|
||||
ENTRY(CTL_CMD_LIST, method_list_users),
|
||||
ENTRY(CTL_CMD_LIST_BANNED, method_list_banned),
|
||||
ENTRY(CTL_CMD_LIST_COOKIES, method_list_cookies),
|
||||
ENTRY(CTL_CMD_USER_INFO, method_user_info),
|
||||
ENTRY(CTL_CMD_ID_INFO, method_id_info),
|
||||
ENTRY(CTL_CMD_UNBAN_IP, method_unban_ip),
|
||||
@@ -348,17 +351,7 @@ static int append_user_info(method_ctx *ctx,
|
||||
rep->hostname = ctmp->hostname;
|
||||
rep->user_agent = ctmp->user_agent;
|
||||
|
||||
if (ctmp->status == PS_AUTH_COMPLETED)
|
||||
strtmp = "connected";
|
||||
else if (ctmp->status == PS_AUTH_INIT)
|
||||
strtmp = "auth";
|
||||
else if (ctmp->status == PS_AUTH_INACTIVE)
|
||||
strtmp = "pre-auth";
|
||||
else if (ctmp->status == PS_AUTH_FAILED)
|
||||
strtmp = "auth failed";
|
||||
else
|
||||
strtmp = "unknown";
|
||||
rep->status = strtmp;
|
||||
rep->status = (char*)ps_status_to_str(ctmp->status, 0);
|
||||
|
||||
rep->tls_ciphersuite = ctmp->tls_ciphersuite;
|
||||
rep->dtls_ciphersuite = ctmp->dtls_ciphersuite;
|
||||
@@ -516,6 +509,27 @@ static void method_list_banned(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
return;
|
||||
}
|
||||
|
||||
static void method_list_cookies(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: list-cookies");
|
||||
|
||||
ret = send_msg16(ctx->pool, ctx->s->sec_mod_fd_sync, CMD_SECM_LIST_COOKIES,
|
||||
NULL, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending list cookies to sec-mod!");
|
||||
}
|
||||
|
||||
ret = forward_msg32(ctx->pool, ctx->s->sec_mod_fd_sync, CMD_SECM_LIST_COOKIES_REPLY,
|
||||
cfd, CTL_CMD_LIST_COOKIES_REP, MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending list cookies reply");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void single_info_common(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size, const char *user, unsigned id)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ int handle_sec_mod_commands(main_server_st * s)
|
||||
struct iovec iov[3];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
uint16_t length;
|
||||
uint32_t length;
|
||||
uint8_t *raw;
|
||||
int ret, raw_len, e;
|
||||
void *pool = talloc_new(s);
|
||||
@@ -73,7 +73,7 @@ int handle_sec_mod_commands(main_server_st * s)
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = &length;
|
||||
iov[1].iov_len = 2;
|
||||
iov[1].iov_len = 4;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_iov = iov;
|
||||
@@ -95,7 +95,7 @@ int handle_sec_mod_commands(main_server_st * s)
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
if (ret < 3 || cmd <= MIN_SECM_CMD || cmd >= MAX_SECM_CMD) {
|
||||
if (ret < 5 || cmd <= MIN_SECM_CMD || cmd >= MAX_SECM_CMD) {
|
||||
mslog(s, NULL, LOG_ERR, "main received invalid message from sec-mod of %u bytes (cmd: %u)\n",
|
||||
(unsigned)length, (unsigned)cmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
@@ -440,7 +440,7 @@ int session_open(main_server_st * s, struct proc_st *proc, const uint8_t *cookie
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = recv_msg16(proc, s->sec_mod_fd_sync, CMD_SECM_SESSION_REPLY,
|
||||
ret = recv_msg32(proc, s->sec_mod_fd_sync, CMD_SECM_SESSION_REPLY,
|
||||
(void *)&msg, (unpack_func) secm_session_reply_msg__unpack, MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
@@ -522,7 +522,7 @@ int session_close(main_server_st * s, struct proc_st *proc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = recv_msg16(proc, s->sec_mod_fd_sync, CMD_SECM_CLI_STATS,
|
||||
ret = recv_msg32(proc, s->sec_mod_fd_sync, CMD_SECM_CLI_STATS,
|
||||
(void *)&msg, (unpack_func) cli_stats_msg__unpack, MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
|
||||
@@ -79,14 +79,6 @@ struct script_wait_st {
|
||||
struct proc_st* proc;
|
||||
};
|
||||
|
||||
enum {
|
||||
PS_AUTH_INACTIVE, /* no comm with worker */
|
||||
PS_AUTH_FAILED, /* no tried authenticated but failed */
|
||||
PS_AUTH_INIT, /* worker has sent an auth init msg */
|
||||
PS_AUTH_CONT, /* worker has sent an auth cont msg */
|
||||
PS_AUTH_COMPLETED /* successful authentication */
|
||||
};
|
||||
|
||||
/* Each worker process maps to a unique proc_st structure.
|
||||
*/
|
||||
typedef struct proc_st {
|
||||
|
||||
@@ -16,7 +16,7 @@ EXTRA_DIST = args.def
|
||||
bin_PROGRAMS = occtl
|
||||
|
||||
occtl_SOURCES = occtl.c pager.c occtl.h time.c cache.c ip-cache.c \
|
||||
nl.c ctl.h print.c json.c json.h
|
||||
nl.c ctl.h print.c json.c json.h hex.c hex.h
|
||||
occtl_LDADD = ../../gl/libgnu.a ../common/libcommon.a $(LIBREADLINE_LIBS) \
|
||||
$(LIBNL3_LIBS) $(LIBPROTOBUF_C_LIBS) $(LIBTALLOC_LIBS) ../ccan/libccan.a \
|
||||
../libipc.a
|
||||
|
||||
@@ -15,6 +15,7 @@ enum {
|
||||
CTL_CMD_LIST_BANNED,
|
||||
CTL_CMD_UNBAN_IP,
|
||||
CTL_CMD_TOP,
|
||||
CTL_CMD_LIST_COOKIES,
|
||||
|
||||
CTL_CMD_STATUS_REP = 101,
|
||||
CTL_CMD_RELOAD_REP,
|
||||
@@ -24,7 +25,8 @@ enum {
|
||||
CTL_CMD_DISCONNECT_ID_REP,
|
||||
CTL_CMD_UNBAN_IP_REP,
|
||||
CTL_CMD_LIST_BANNED_REP,
|
||||
CTL_CMD_TOP_UPDATE_REP
|
||||
CTL_CMD_TOP_UPDATE_REP,
|
||||
CTL_CMD_LIST_COOKIES_REP
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
71
src/occtl/hex.c
Normal file
71
src/occtl/hex.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/* CC0 license (public domain) - see LICENSE file for details */
|
||||
#include <config.h>
|
||||
#include <hex.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static bool char_to_hex(unsigned char *val, char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
*val = c - '0';
|
||||
return true;
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
*val = c - 'a' + 10;
|
||||
return true;
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
*val = c - 'A' + 10;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize)
|
||||
{
|
||||
unsigned char v1, v2;
|
||||
unsigned char *p = buf;
|
||||
|
||||
while (slen > 1) {
|
||||
if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1]))
|
||||
return false;
|
||||
if (!bufsize)
|
||||
return false;
|
||||
*(p++) = (v1 << 4) | v2;
|
||||
str += 2;
|
||||
slen -= 2;
|
||||
bufsize--;
|
||||
}
|
||||
return slen == 0 && bufsize == 0;
|
||||
}
|
||||
|
||||
static char hexchar(unsigned int val)
|
||||
{
|
||||
if (val < 10)
|
||||
return '0' + val;
|
||||
if (val < 16)
|
||||
return 'a' + val - 10;
|
||||
abort();
|
||||
}
|
||||
|
||||
bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize)
|
||||
{
|
||||
size_t used = 0;
|
||||
|
||||
if (destsize < 1)
|
||||
return false;
|
||||
|
||||
while (used < bufsize) {
|
||||
unsigned int c = ((const unsigned char *)buf)[used];
|
||||
if (destsize < 3)
|
||||
return false;
|
||||
*(dest++) = hexchar(c >> 4);
|
||||
*(dest++) = hexchar(c & 0xF);
|
||||
used++;
|
||||
destsize -= 2;
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
return used + 1;
|
||||
}
|
||||
73
src/occtl/hex.h
Normal file
73
src/occtl/hex.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_HEX_H
|
||||
#define CCAN_HEX_H
|
||||
#include "config.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* hex_decode - Unpack a hex string.
|
||||
* @str: the hexidecimal string
|
||||
* @slen: the length of @str
|
||||
* @buf: the buffer to write the data into
|
||||
* @bufsize: the length of @buf
|
||||
*
|
||||
* Returns false if there are any characters which aren't 0-9, a-f or A-F,
|
||||
* of the string wasn't the right length for @bufsize.
|
||||
*
|
||||
* Example:
|
||||
* unsigned char data[20];
|
||||
*
|
||||
* if (!hex_decode(argv[1], strlen(argv[1]), data, 20))
|
||||
* printf("String is malformed!\n");
|
||||
*/
|
||||
bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* hex_encode - Create a nul-terminated hex string
|
||||
* @buf: the buffer to read the data from
|
||||
* @bufsize: the length of @buf
|
||||
* @dest: the string to fill
|
||||
* @destsize: the max size of the string
|
||||
*
|
||||
* Returns true if the string, including terminator, fit in @destsize;
|
||||
*
|
||||
* Example:
|
||||
* unsigned char buf[] = { 0x1F, 0x2F };
|
||||
* char str[5];
|
||||
*
|
||||
* if (!hex_encode(buf, sizeof(buf), str, sizeof(str)))
|
||||
* abort();
|
||||
*/
|
||||
bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize);
|
||||
|
||||
/**
|
||||
* hex_str_size - Calculate how big a nul-terminated hex string is
|
||||
* @bytes: bytes of data to represent
|
||||
*
|
||||
* Example:
|
||||
* unsigned char buf[] = { 0x1F, 0x2F };
|
||||
* char str[hex_str_size(sizeof(buf))];
|
||||
*
|
||||
* hex_encode(buf, sizeof(buf), str, sizeof(str));
|
||||
*/
|
||||
static inline size_t hex_str_size(size_t bytes)
|
||||
{
|
||||
return 2 * bytes + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* hex_data_size - Calculate how many bytes of data in a hex string
|
||||
* @strlen: the length of the string (with or without NUL)
|
||||
*
|
||||
* Example:
|
||||
* const char str[] = "1F2F";
|
||||
* unsigned char buf[hex_data_size(sizeof(str))];
|
||||
*
|
||||
* hex_decode(str, strlen(str), buf, sizeof(buf));
|
||||
*/
|
||||
static inline size_t hex_data_size(size_t strlen)
|
||||
{
|
||||
return strlen / 2;
|
||||
}
|
||||
#endif /* PETTYCOIN_HEX_H */
|
||||
@@ -65,6 +65,8 @@ static const commands_st commands[] = {
|
||||
"Prints all the known IP addresses which have points", 1, 1),
|
||||
ENTRY("show iroutes", NULL, handle_list_iroutes_cmd,
|
||||
"Prints the routes provided by users of the server", 1, 1),
|
||||
ENTRY("show cookies", NULL, handle_list_cookies_cmd,
|
||||
"Prints all the cookies", 1, 1),
|
||||
ENTRY("show user", "[NAME]", handle_show_user_cmd,
|
||||
"Prints information on the specified user", 1, 1),
|
||||
ENTRY("show id", "[ID]", handle_show_id_cmd,
|
||||
|
||||
@@ -80,6 +80,7 @@ int handle_status_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_users_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_iroutes_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_banned_ips_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_cookies_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_banned_points_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_show_user_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_show_id_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
|
||||
165
src/occtl/unix.c
165
src/occtl/unix.c
@@ -33,7 +33,6 @@
|
||||
#include <common.h>
|
||||
#include <c-strcase.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <system.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
@@ -44,9 +43,12 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include "hex.h"
|
||||
|
||||
static
|
||||
int common_info_cmd(UserListRep *args, FILE *out, cmd_params_st *params);
|
||||
static
|
||||
int cookie_info_cmd(SecmListCookiesReplyMsg * args, FILE *out, cmd_params_st *params);
|
||||
|
||||
struct unix_ctx {
|
||||
int fd;
|
||||
@@ -59,6 +61,7 @@ static uint8_t msg_map[] = {
|
||||
[CTL_CMD_RELOAD] = CTL_CMD_RELOAD_REP,
|
||||
[CTL_CMD_STOP] = CTL_CMD_STOP_REP,
|
||||
[CTL_CMD_LIST] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_LIST_COOKIES] = CTL_CMD_LIST_COOKIES_REP,
|
||||
[CTL_CMD_LIST_BANNED] = CTL_CMD_LIST_BANNED_REP,
|
||||
[CTL_CMD_USER_INFO] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_TOP] = CTL_CMD_LIST_REP,
|
||||
@@ -642,6 +645,86 @@ int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cookie_list(struct unix_ctx *ctx, SecmListCookiesReplyMsg *rep, FILE *out, cmd_params_st *params)
|
||||
{
|
||||
unsigned i;
|
||||
const char *groupname, *username;
|
||||
char tmpbuf[MAX_TMPSTR_SIZE];
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
char str_since[65];
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
cookie_info_cmd(rep, out, params);
|
||||
} else for (i=0;i<rep->n_cookies;i++) {
|
||||
username = rep->cookies[i]->username;
|
||||
if (username == NULL || username[0] == 0)
|
||||
username = NO_USER;
|
||||
|
||||
/* add header */
|
||||
if (i == 0) {
|
||||
fprintf(out, "%6s %8s %8s %14s %24s %8s %8s\n",
|
||||
"cookie", "user", "group", "ip", "user agent", "updated", "status");
|
||||
}
|
||||
|
||||
t = rep->cookies[i]->last_modified;
|
||||
tm = localtime(&t);
|
||||
strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
|
||||
|
||||
groupname = rep->cookies[i]->groupname;
|
||||
if (groupname == NULL || groupname[0] == 0)
|
||||
groupname = NO_GROUP;
|
||||
|
||||
print_time_ival7(tmpbuf, time(0), t);
|
||||
|
||||
fprintf(out, "%.6s %8s %8s %14s %.24s %8s %8s\n",
|
||||
rep->cookies[i]->psid, username, groupname, rep->cookies[i]->remote_ip,
|
||||
rep->cookies[i]->user_agent, tmpbuf, rep->cookies[i]->status);
|
||||
}
|
||||
}
|
||||
|
||||
int handle_list_cookies_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
|
||||
{
|
||||
int ret;
|
||||
struct cmd_reply_st raw;
|
||||
SecmListCookiesReplyMsg *rep = NULL;
|
||||
FILE *out;
|
||||
PROTOBUF_ALLOCATOR(pa, ctx);
|
||||
|
||||
init_reply(&raw);
|
||||
|
||||
entries_clear();
|
||||
|
||||
out = pager_start(params);
|
||||
|
||||
ret = send_cmd(ctx, CTL_CMD_LIST_COOKIES, NULL, NULL, NULL, &raw);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rep = secm_list_cookies_reply_msg__unpack(&pa, raw.data_size, raw.data);
|
||||
if (rep == NULL)
|
||||
goto error;
|
||||
|
||||
cookie_list(ctx, rep, out, params);
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
error:
|
||||
ret = 1;
|
||||
fprintf(stderr, ERR_SERVER_UNREACHABLE);
|
||||
|
||||
cleanup:
|
||||
if (rep != NULL)
|
||||
secm_list_cookies_reply_msg__free_unpacked(rep, &pa);
|
||||
|
||||
free_reply(&raw);
|
||||
pager_stop(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_list_iroutes_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
|
||||
{
|
||||
int ret;
|
||||
@@ -1004,6 +1087,86 @@ int common_info_cmd(UserListRep * args, FILE *out, cmd_params_st *params)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int cookie_info_cmd(SecmListCookiesReplyMsg * args, FILE *out, cmd_params_st *params)
|
||||
{
|
||||
char *username = "";
|
||||
char *groupname = "";
|
||||
char str_since[65];
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
unsigned at_least_one = 0;
|
||||
int ret = 1;
|
||||
unsigned i;
|
||||
unsigned init_pager = 0;
|
||||
|
||||
if (out == NULL) {
|
||||
out = pager_start(params);
|
||||
init_pager = 1;
|
||||
}
|
||||
|
||||
if (HAVE_JSON(params))
|
||||
fprintf(out, "[\n");
|
||||
|
||||
for (i=0;i<args->n_cookies;i++) {
|
||||
if (at_least_one > 0)
|
||||
fprintf(out, "\n");
|
||||
|
||||
print_start_block(out, params);
|
||||
|
||||
print_single_value_int(out, params, "session_is_open", args->cookies[i]->session_is_open, 1);
|
||||
print_single_value_int(out, params, "tls_auth_ok", args->cookies[i]->tls_auth_ok, 1);
|
||||
print_single_value(out, params, "State", args->cookies[i]->status, 1);
|
||||
|
||||
t = args->cookies[i]->last_modified;
|
||||
tm = localtime(&t);
|
||||
strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
|
||||
|
||||
username = args->cookies[i]->username;
|
||||
if (username == NULL || username[0] == 0)
|
||||
username = NO_USER;
|
||||
|
||||
groupname = args->cookies[i]->groupname;
|
||||
if (groupname == NULL || groupname[0] == 0)
|
||||
groupname = NO_GROUP;
|
||||
|
||||
print_pair_value(out, params, "Username", username, "Groupname", groupname, 1);
|
||||
print_single_value(out, params, "User-Agent", args->cookies[i]->user_agent, 1);
|
||||
print_single_value(out, params, "Remote IP", args->cookies[i]->remote_ip, 1);
|
||||
|
||||
print_single_value(out, params, "Last Modified", str_since, 1);
|
||||
|
||||
str_since[0] = 0;
|
||||
hex_encode(args->cookies[i]->sid.data, args->cookies[i]->sid.len, str_since, sizeof(str_since));
|
||||
print_single_value(out, params, "cookie", str_since, 1);
|
||||
|
||||
print_single_value(out, params, "Printable cookie", args->cookies[i]->psid, 1);
|
||||
|
||||
print_single_value(out, params, "Last Modified", str_since, 0);
|
||||
|
||||
print_end_block(out, params, i<(args->n_cookies-1)?1:0);
|
||||
|
||||
at_least_one = 1;
|
||||
}
|
||||
|
||||
if (HAVE_JSON(params))
|
||||
fprintf(out, "]\n");
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
if (at_least_one == 0) {
|
||||
if (NO_JSON(params))
|
||||
fprintf(out, "user or ID not found\n");
|
||||
ret = 2;
|
||||
}
|
||||
if (init_pager)
|
||||
pager_stop(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_show_user_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -93,7 +93,7 @@ void sec_mod_add_score_to_ip(sec_mod_st *sec, client_entry_st *e, const char *ip
|
||||
return;
|
||||
}
|
||||
|
||||
ret = send_msg16(lpool, sec->cmd_fd, CMD_SECM_BAN_IP, &msg,
|
||||
ret = send_msg32(lpool, sec->cmd_fd, CMD_SECM_BAN_IP, &msg,
|
||||
(pack_size_func) ban_ip_msg__get_packed_size,
|
||||
(pack_func) ban_ip_msg__pack);
|
||||
if (ret < 0) {
|
||||
@@ -343,7 +343,7 @@ int send_failed_session_open_reply(sec_mod_st *sec, int fd)
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = send_msg16(lpool, fd, CMD_SECM_SESSION_REPLY, &rep,
|
||||
ret = send_msg32(lpool, fd, CMD_SECM_SESSION_REPLY, &rep,
|
||||
(pack_size_func) secm_session_reply_msg__get_packed_size,
|
||||
(pack_func) secm_session_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
@@ -439,7 +439,7 @@ int handle_secm_session_open_cmd(sec_mod_st *sec, int fd, const SecmSessionOpenM
|
||||
}
|
||||
}
|
||||
|
||||
ret = send_msg16(lpool, fd, CMD_SECM_SESSION_REPLY, &rep,
|
||||
ret = send_msg32(lpool, fd, CMD_SECM_SESSION_REPLY, &rep,
|
||||
(pack_size_func) secm_session_reply_msg__get_packed_size,
|
||||
(pack_func) secm_session_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
@@ -472,14 +472,14 @@ int handle_secm_session_close_cmd(sec_mod_st *sec, int fd, const SecmSessionClos
|
||||
char tmp[BASE64_ENCODE_RAW_LENGTH(SID_SIZE) + 1];
|
||||
oc_base64_encode((char *)req->sid.data, req->sid.len, (char *)tmp, sizeof(tmp));
|
||||
seclog(sec, LOG_INFO, "session close but with non-existing SID: %s", tmp);
|
||||
return send_msg16(e, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
return send_msg32(e, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
(pack_size_func) cli_stats_msg__get_packed_size,
|
||||
(pack_func) cli_stats_msg__pack);
|
||||
}
|
||||
|
||||
if (e->status < PS_AUTH_COMPLETED) {
|
||||
seclog(sec, LOG_DEBUG, "session close received in unauthenticated client %s "SESSION_STR"!", e->acct_info.username, e->acct_info.psid);
|
||||
return send_msg16(e, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
return send_msg32(e, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
(pack_size_func) cli_stats_msg__get_packed_size,
|
||||
(pack_func) cli_stats_msg__pack);
|
||||
}
|
||||
@@ -506,7 +506,7 @@ int handle_secm_session_close_cmd(sec_mod_st *sec, int fd, const SecmSessionClos
|
||||
rep.secmod_tlsdb_entries = sec->tls_db.entries;
|
||||
rep.has_secmod_tlsdb_entries = 1;
|
||||
|
||||
ret = send_msg16(e, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
ret = send_msg32(e, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
(pack_size_func) cli_stats_msg__get_packed_size,
|
||||
(pack_func) cli_stats_msg__pack);
|
||||
if (ret < 0) {
|
||||
|
||||
104
src/sec-mod-cookies.c
Normal file
104
src/sec-mod-cookies.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Nikos Mavrogiannopoulos
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <vpn.h>
|
||||
#include <main.h>
|
||||
#include <sec-mod.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
#include <ccan/htable/htable.h>
|
||||
|
||||
static void send_empty_reply(void *pool, int fd, sec_mod_st *sec)
|
||||
{
|
||||
SecmListCookiesReplyMsg msg = SECM_LIST_COOKIES_REPLY_MSG__INIT;
|
||||
int ret;
|
||||
|
||||
ret = send_msg32(pool, fd, CMD_SECM_LIST_COOKIES_REPLY, &msg,
|
||||
(pack_size_func) secm_list_cookies_reply_msg__get_packed_size,
|
||||
(pack_func) secm_list_cookies_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "Error sending empty show cookies reply to main");
|
||||
}
|
||||
}
|
||||
|
||||
void handle_secm_list_cookies_reply(void *pool, int fd, sec_mod_st *sec)
|
||||
{
|
||||
SecmListCookiesReplyMsg msg = SECM_LIST_COOKIES_REPLY_MSG__INIT;
|
||||
struct htable *db = sec->client_db;
|
||||
client_entry_st *t;
|
||||
struct htable_iter iter;
|
||||
CookieIntMsg *cookies;
|
||||
int ret;
|
||||
|
||||
if (db == NULL) {
|
||||
send_empty_reply(pool, fd, sec);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.cookies = talloc_size(pool, sizeof(CookieIntMsg*)*db->elems);
|
||||
if (msg.cookies == NULL) {
|
||||
send_empty_reply(pool, fd, sec);
|
||||
return;
|
||||
}
|
||||
|
||||
cookies = talloc_size(pool, sizeof(CookieIntMsg)*db->elems);
|
||||
if (cookies == NULL) {
|
||||
send_empty_reply(pool, fd, sec);
|
||||
return;
|
||||
}
|
||||
|
||||
t = htable_first(db, &iter);
|
||||
while (t != NULL) {
|
||||
if (msg.n_cookies >= db->elems)
|
||||
break;
|
||||
|
||||
cookie_int_msg__init(&cookies[msg.n_cookies]);
|
||||
cookies[msg.n_cookies].sid.data = t->sid;
|
||||
cookies[msg.n_cookies].sid.len = sizeof(t->sid);
|
||||
|
||||
cookies[msg.n_cookies].session_is_open = t->session_is_open;
|
||||
cookies[msg.n_cookies].tls_auth_ok = t->tls_auth_ok;
|
||||
cookies[msg.n_cookies].last_modified = t->time;
|
||||
cookies[msg.n_cookies].username = t->acct_info.username;
|
||||
cookies[msg.n_cookies].groupname = t->acct_info.groupname;
|
||||
cookies[msg.n_cookies].user_agent = t->acct_info.user_agent;
|
||||
cookies[msg.n_cookies].remote_ip = t->acct_info.remote_ip;
|
||||
cookies[msg.n_cookies].psid = t->acct_info.psid;
|
||||
cookies[msg.n_cookies].status = (char*)ps_status_to_str(t->status, 1);
|
||||
|
||||
msg.cookies[msg.n_cookies] = &cookies[msg.n_cookies];
|
||||
msg.n_cookies++;
|
||||
|
||||
t = htable_next(db, &iter);
|
||||
}
|
||||
|
||||
ret = send_msg32(pool, fd, CMD_SECM_LIST_COOKIES_REPLY, &msg,
|
||||
(pack_size_func) secm_list_cookies_reply_msg__get_packed_size,
|
||||
(pack_func) secm_list_cookies_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "Error sending show cookies reply to main");
|
||||
}
|
||||
|
||||
talloc_free(msg.cookies);
|
||||
talloc_free(cookies);
|
||||
}
|
||||
|
||||
@@ -425,6 +425,10 @@ int process_packet_from_main(void *pool, int fd, sec_mod_st * sec, cmd_request_t
|
||||
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;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <nettle/base64.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
#define SESSION_STR "(session: %.5s)"
|
||||
#define SESSION_STR "(session: %.6s)"
|
||||
|
||||
typedef struct sec_mod_st {
|
||||
struct cfg_st *config;
|
||||
@@ -130,6 +130,7 @@ void seclog_hex(const struct sec_mod_st* sec, int priority,
|
||||
|
||||
void sec_auth_init(sec_mod_st *sec, struct perm_cfg_st *config);
|
||||
|
||||
void handle_secm_list_cookies_reply(void *pool, int fd, sec_mod_st *sec);
|
||||
void handle_sec_auth_ban_ip_reply(sec_mod_st *sec, const BanIpReplyMsg *msg);
|
||||
int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg * req, pid_t pid);
|
||||
int handle_sec_auth_cont(int cfd, sec_mod_st *sec, const SecAuthContMsg * req);
|
||||
|
||||
10
src/vpn.h
10
src/vpn.h
@@ -50,6 +50,14 @@
|
||||
|
||||
#define MAX_MSG_SIZE 16*1024
|
||||
|
||||
enum {
|
||||
PS_AUTH_INACTIVE, /* no comm with worker */
|
||||
PS_AUTH_FAILED, /* no tried authenticated but failed */
|
||||
PS_AUTH_INIT, /* worker has sent an auth init msg */
|
||||
PS_AUTH_CONT, /* worker has sent an auth cont msg */
|
||||
PS_AUTH_COMPLETED /* successful authentication */
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SOCK_TYPE_TCP,
|
||||
SOCK_TYPE_UDP,
|
||||
@@ -214,6 +222,8 @@ typedef enum {
|
||||
CMD_SECM_BAN_IP,
|
||||
CMD_SECM_BAN_IP_REPLY,
|
||||
CMD_SECM_CLI_STATS,
|
||||
CMD_SECM_LIST_COOKIES,
|
||||
CMD_SECM_LIST_COOKIES_REPLY,
|
||||
|
||||
MAX_SECM_CMD,
|
||||
} cmd_request_t;
|
||||
|
||||
Reference in New Issue
Block a user