Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Always
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
Expand Down Expand Up @@ -65,3 +65,4 @@ SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: ForContinuationAndIndentation
AlignConsecutiveMacros: true
36 changes: 36 additions & 0 deletions common/struct_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ typedef enum Status {
#define IsCAPNegotiation(x) (MyConnect(x) && (x)->cap_negotation)
#define HasCap(x, y) (MyConnect(x) && (x)->caps & y)
#define IsSASLAuthed(x) ((x)->flags & FLAGS_SASL)
#define IsPP2(x) (!IN6_IS_ADDR_UNSPECIFIED(&x->pp2_dip) && x->pp2_dport != 0)
/*
* defined debugging levels
*/
Expand Down Expand Up @@ -405,10 +406,13 @@ struct ListItem {
#define PFLAG_DELAYED 0x00001
#define PFLAG_SERVERONLY 0x00002
#define PFLAG_TLS 0x00004
#define PFLAG_PP2 0x00008

#define IsConfDelayed(x) ((x)->flags & PFLAG_DELAYED)
#define IsConfServeronly(x) ((x)->flags & PFLAG_SERVERONLY)
#define IsConfTLS(x) ((x)->flags & PFLAG_TLS)
#define IsConfPP2(x) ((x)->flags & PFLAG_PP2)
#define DoingPP2(x) ((x)->pp2_state && (x)->pp2_state->phase != PROXY_DONE)

#define IsIllegal(x) ((x)->status & CONF_ILLEGAL)

Expand Down Expand Up @@ -444,6 +448,35 @@ struct LineItem
struct LineItem *next;
};

/* PROXY protocol v2 structures */
typedef enum
{
/* waiting for 16-byte header */
PROXY_NEED_HDR = 1,
/* waiting for payload bytes */
PROXY_NEED_PAYLOAD = 2,
/* parsing complete */
PROXY_DONE = 3
} PP2Phase;

typedef struct {
/* current parsing phase (see PP2Phase enum) */
PP2Phase phase;
/* buffer for header and payload data */
unsigned char buf[512];
/* number of bytes currently stored in 'buf' */
size_t buflen;
/* number of bytes still required to finish the current phase:
* - starts at 16 (header size)
* - after header is parsed: payload length
* - becomes 0 once that phase is satisfied */
size_t need;
/* payload length field as advertised in header */
uint16_t fam_len;
/* family/protocol byte, identifies AF_INET / AF_INET6 / etc. */
uint8_t fam;
} PP2State;

/*
* Client structures
*/
Expand Down Expand Up @@ -588,6 +621,9 @@ struct Client {
int cap_negotation; /* CAP negotiation is in progress. Registration must wait for "CAP END" */
aClient *sasl_service; /* The SASL service that is responsible for this user. */
char *cloak_tmp; /* Contains the cloaked hostname until it was applied to the user */
PP2State *pp2_state; /* PROXY protocol v2: parser state */
struct in6_addr pp2_dip; /* PROXY protocol v2: destination IP address */
uint16_t pp2_dport; /* PROXY protocol v2: destination port */
};

#define CLIENT_LOCAL_SIZE sizeof(aClient)
Expand Down
1 change: 1 addition & 0 deletions ircd/ircd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,7 @@ int main(int argc, char *argv[])
open_debugfile();
timeofday = time(NULL);
(void)init_sys();
init_trusted_proxy_ips();

#ifdef USE_SYSLOG
openlog(mybasename(myargv[0]), LOG_PID|LOG_NDELAY, LOG_FACILITY);
Expand Down
9 changes: 8 additions & 1 deletion ircd/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ aClient *make_client(aClient *from)
cptr->sasl_service = NULL;
cptr->cloak_tmp = NULL;
memset(&cptr->cloak_ip, 0, sizeof(cptr->cloak_ip));
cptr->pp2_state = NULL;
memset(&cptr->pp2_dip, 0, sizeof(cptr->pp2_dip));
cptr->pp2_dport = 0;
}
return (cptr);
}
Expand Down Expand Up @@ -182,10 +185,14 @@ void free_client(aClient *cptr)
if (cptr->user3)
MyFree(cptr->user3);
#endif
if(cptr->sasl_user)
if (cptr->sasl_user)
{
MyFree(cptr->sasl_user);
}
if (cptr->pp2_state)
{
pp2_free(cptr);
}
}
MyFree(cptr);
}
Expand Down
154 changes: 110 additions & 44 deletions ircd/s_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,16 +560,33 @@ void start_auth(aClient *cptr)

set_non_blocking(cptr->authfd, cptr);

/* get remote host peer - so that we get right interface -- jrg */
tlen = ulen = sizeof(us);
if (getpeername(cptr->fd, (struct sockaddr *)&them, &tlen) < 0)
{
/* we probably don't need this error message -kalt */
report_error("getpeername for auth request %s:%s", cptr);
close(cptr->authfd);
cptr->authfd = -1;
return;
}

if (IsPP2(cptr))
{
char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN];
memset(&them, 0, sizeof(them));
them.SIN_FAMILY = AFINET;
memcpy(&them.sin6_addr, &cptr->ip, sizeof(cptr->ip));
them.SIN_PORT = htons(cptr->port);

Debug((DEBUG_INFO, "start_auth(%x) pp2 applied: src %s:%u dst %s:%u",
cptr, inetntop(AF_INET6, (char *) &cptr->ip, src, sizeof(src)),
(unsigned) cptr->port,
inetntop(AF_INET6, (char *) &cptr->pp2_dip, dst, sizeof(dst)),
(unsigned) cptr->pp2_dport));
}
else
{
if (getpeername(cptr->fd, (struct sockaddr *) &them, &tlen) < 0)
{
/* we probably don't need this error message -kalt */
report_error("getpeername for auth request %s:%s", cptr);
close(cptr->authfd);
cptr->authfd = -1;
return;
}
}
them.SIN_FAMILY = AFINET;

/* We must bind the local end to the interface that they connected
Expand All @@ -579,31 +596,60 @@ void start_auth(aClient *cptr)
(void)getsockname(cptr->fd, (struct sockaddr *)&us, &ulen);
us.SIN_FAMILY = AFINET;

// Check if a source IP has been set in P-Line (usually if an SSL proxy is used)
if (cptr->acpt->confs && IsConfTLS(cptr->acpt->confs->value.aconf)
&& !BadPtr(cptr->acpt->confs->value.aconf->source_ip))
if (IsPP2(cptr))
{
inetpton(AF_INET6, cptr->acpt->confs->value.aconf->source_ip, us.sin6_addr.s6_addr);
memset(&us, 0, sizeof(us));
us.SIN_FAMILY = AFINET;
memcpy(&us.sin6_addr, &cptr->pp2_dip, sizeof(cptr->pp2_dip));
}
else
{
if (getsockname(cptr->fd, (struct sockaddr *) &us, &ulen) < 0)
{
report_error("getsockname for auth request %s:%s", cptr);
close(cptr->authfd);
cptr->authfd = -1;
return;
}
us.SIN_FAMILY = AFINET;

/*
* Check if a source IP has been set in P-Line (usually if an
* SSL proxy is used)
*/
if (cptr->acpt->confs && IsConfTLS(cptr->acpt->confs->value.aconf) &&
!BadPtr(cptr->acpt->confs->value.aconf->source_ip))
{
inetpton(AF_INET6, cptr->acpt->confs->value.aconf->source_ip,
us.sin6_addr.s6_addr);
}
}

# if defined(USE_IAUTH)
if (adfd >= 0)
{
{
char abuf[BUFSIZ];
unsigned int iauth_lport = IsPP2(cptr) ? (unsigned) cptr->pp2_dport
: (unsigned) ntohs(us.SIN_PORT);

sprintf(abuf, "%d C %s %u ", cptr->fd,
inetntop(AF_INET6, (char *)&them.sin6_addr, ipv6string,
sizeof(ipv6string)), ntohs(them.SIN_PORT));
sprintf(abuf+strlen(abuf), "%s %u",
inetntop(AF_INET6, (char *)&us.sin6_addr, ipv6string,
sizeof(ipv6string)), ntohs(us.SIN_PORT));
inetntop(AF_INET6, (char *) &them.sin6_addr, ipv6string,
sizeof(ipv6string)),
(unsigned) ntohs(them.SIN_PORT));

sprintf(abuf + strlen(abuf), "%s %u",
inetntop(AF_INET6, (char *) &us.sin6_addr, ipv6string,
sizeof(ipv6string)),
iauth_lport);

if (sendto_iauth(abuf) == 0)
{
{
close(cptr->authfd);
cptr->authfd = -1;
cptr->flags |= FLAGS_XAUTH;
return;
}
}
}
}
# endif
Debug((DEBUG_NOTICE,"auth(%x) from %s %x %x",
cptr, inet_ntop(AF_INET6, (char *)&us.sin6_addr, ipv6string,
Expand Down Expand Up @@ -664,43 +710,63 @@ void start_auth(aClient *cptr)
*/
void send_authports(aClient *cptr)
{
struct SOCKADDR_IN us, them;
struct SOCKADDR_IN us, them;

char authbuf[32];
char authbuf[32];
SOCK_LEN_TYPE ulen, tlen;

Debug((DEBUG_NOTICE,"write_authports(%x) fd %d authfd %d stat %d",
cptr, cptr->fd, cptr->authfd, cptr->status));
Debug((DEBUG_NOTICE, "write_authports(%x) fd %d authfd %d stat %d", cptr,
cptr->fd, cptr->authfd, cptr->status));
tlen = ulen = sizeof(us);
if (getsockname(cptr->fd, (struct SOCKADDR *)&us, &ulen) ||
getpeername(cptr->fd, (struct SOCKADDR *)&them, &tlen))
{
#ifdef USE_SYSLOG
syslog(LOG_ERR, "auth get{sock,peer}name error for %s:%m",
get_client_name(cptr, TRUE));

if (getsockname(cptr->fd, (struct SOCKADDR *) &us, &ulen))
{
#ifdef USE_SYSLOG
syslog(LOG_ERR, "auth getsockname error for %s:%m",
get_client_name(cptr, TRUE));
#endif
goto authsenderr;
}
}

sprintf(authbuf, "%u , %u\r\n",
(unsigned int)ntohs(them.SIN_PORT),
(unsigned int)ntohs(us.SIN_PORT));
if (IsPP2(cptr))
{
memset(&them, 0, sizeof(them));
them.SIN_FAMILY = AFINET;
memcpy(&them.sin6_addr, &cptr->ip, sizeof(cptr->ip));
them.SIN_PORT = htons(cptr->port);
sprintf(authbuf, "%u , %u\r\n", (unsigned int) cptr->port,
(unsigned int) cptr->pp2_dport);
}
else
{
if (getpeername(cptr->fd, (struct SOCKADDR *) &them, &tlen))
{
#ifdef USE_SYSLOG
syslog(LOG_ERR, "auth getpeername error for %s:%m",
get_client_name(cptr, TRUE));
#endif
goto authsenderr;
}

Debug((DEBUG_SEND, "sending [%s] to auth port %s.113",
authbuf, inet_ntop(AF_INET6, (char *)&them.sin6_addr,
ipv6string, sizeof(ipv6string))));
sprintf(authbuf, "%u , %u\r\n", (unsigned int) ntohs(them.SIN_PORT),
(unsigned int) ntohs(us.SIN_PORT));
}

Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", authbuf,
inet_ntop(AF_INET6, (char *) &them.sin6_addr, ipv6string,
sizeof(ipv6string))));
if (write(cptr->authfd, authbuf, strlen(authbuf)) != strlen(authbuf))
{
authsenderr:
{
authsenderr:
ircstp->is_abad++;
(void)close(cptr->authfd);
(void) close(cptr->authfd);
if (cptr->authfd == highest_fd)
while (!local[highest_fd])
highest_fd--;
cptr->authfd = -1;
cptr->flags &= ~(FLAGS_AUTH|FLAGS_WRAUTH);
cptr->flags &= ~(FLAGS_AUTH | FLAGS_WRAUTH);
return;
}
}
cptr->flags &= ~FLAGS_WRAUTH;
return;
}
Expand Down
Loading