995
}
996
#endif
997
998
+/*
999
+ * ---------------------------------------------------------------------------------------------------------------------
1000
+ * connection_allowed() - if there is an access list then check the connection matches a pattern.
1001
+ * Numeric patterns are checked against the IP address first, only if they
1002
+ * do not match is the hostname resolved (reverse-DNS) and checked. If the
1003
+ * hostname matches then we perform forward DNS resolution to check the IP
1004
+ * is really associated with the DNS record. This call is repeatable: the
1005
+ * web server may check more refined matches against the connection. Will
1006
+ * update the client_host if uninitialized - ensure the hostsize is the number
1007
+ * of *writable* bytes (i.e. be aware of the strdup used to compact the pollinfo).
1008
+ */
1009
+extern int connection_allowed(int fd, char *client_ip, char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list,
1010
+ const char *patname) {
1011
+ if (!access_list)
1012
+ return 1;
1013
+ if (simple_pattern_matches(access_list, client_ip))
1014
+ return 1;
1015
+ // If the hostname is unresolved (and needed) then attempt the DNS lookups.
1016
+ if (client_host[0]==0)
1017
+ {
1018
+ struct sockaddr_storage sadr;
1019
+ socklen_t addrlen = sizeof(sadr);
1020
+ int err = getpeername(fd, (struct sockaddr*)&sadr, &addrlen);
1021
+ if (err != 0 ||
1022
+ (err = getnameinfo((struct sockaddr *)&sadr, addrlen, client_host, (socklen_t)hostsize,
1023
+ NULL, 0, NI_NAMEREQD)) != 0) {
1024
+ error("Incoming connection on '%s' does not match a numeric pattern, "
1025
+ "and host could not be resolved (err=%s)", client_ip, gai_strerror(err));
1026
+ if (hostsize >= 8)
1027
+ strcpy(client_host,"UNKNOWN");
1028
+ return 0;
1029
+ }
1030
+ struct addrinfo *addr_infos = NULL;
1031
+ if (getaddrinfo(client_host, NULL, NULL, &addr_infos) !=0 ) {
1032
+ error("LISTENER: cannot validate hostname '%s' from '%s' by resolving it",
1033
+ client_host, client_ip);
1034
+ if (hostsize >= 8)
1035
+ strcpy(client_host,"UNKNOWN");
1036
+ return 0;
1037
+ }
1038
+ struct addrinfo *scan = addr_infos;
1039
+ int validated = 0;
1040
+ while (scan) {
1041
+ char address[INET6_ADDRSTRLEN];
1042
+ address[0] = 0;
1043
+ switch (scan->ai_addr->sa_family) {
1044
+ case AF_INET:
1045
+ inet_ntop(AF_INET, &((struct sockaddr_in*)(scan->ai_addr))->sin_addr, address, INET6_ADDRSTRLEN);
1046
+ break;
1047
+ case AF_INET6:
1048
+ inet_ntop(AF_INET6, &((struct sockaddr_in6*)(scan->ai_addr))->sin6_addr, address, INET6_ADDRSTRLEN);
1049
+ break;
1050
+ }
1051
+ debug(D_LISTENER, "Incoming ip %s rev-resolved onto %s, validating against forward-resolution %s",
1052
+ client_ip, client_host, address);
1053
+ if (!strcmp(client_ip, address)) {
1054
+ validated = 1;
1055
+ break;
1056
+ }
1057
+ scan = scan->ai_next;
1058
+ }
1059
+ if (!validated) {
1060
+ error("LISTENER: Cannot validate '%s' as ip of '%s', not listed in DNS", client_ip, client_host);
1061
+ if (hostsize >= 8)
1062
+ strcpy(client_host,"UNKNOWN");
1063
+ }
1064
+ if (addr_infos!=NULL)
1065
+ freeaddrinfo(addr_infos);
1066
+ }
1067
+ if (!simple_pattern_matches(access_list, client_host)) {
1068
+ debug(D_LISTENER, "Incoming connection on '%s' (%s) does not match allowed pattern for %s",
1069
+ client_ip, client_host, patname);
1070
+ return 0;
1071
+ }
1072
+ return 1;
1073
+}
1074
1075
// --------------------------------------------------------------------------------------------------------------------
1076
// accept_socket() - accept a socket and store client IP and port
1077
1002
-int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list) {
1078
+int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize,
1079
+ char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list) {
1080
struct sockaddr_storage sadr;
1081
socklen_t addrlen = sizeof(sadr);
1082
1083
int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags);
1084
if (likely(nfd >= 0)) {
1008
- if (getnameinfo((struct sockaddr *)&sadr, addrlen, client_ip, (socklen_t)ipsize, client_port, (socklen_t)portsize, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
1085
+ if (getnameinfo((struct sockaddr *)&sadr, addrlen, client_ip, (socklen_t)ipsize,
1086
+ client_port, (socklen_t)portsize, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
1087
error("LISTENER: cannot getnameinfo() on received client connection.");
1088
strncpyz(client_ip, "UNKNOWN", ipsize - 1);
1089
strncpyz(client_port, "UNKNOWN", portsize - 1);
1090
}
1091
+ if(!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) {
1092
+ strncpy(client_ip, "localhost", ipsize);
1093
+ client_ip[ipsize - 1] = '\0';
1094
+ }
1095
1096
#ifdef __FreeBSD__
1097
if(((struct sockaddr *)&sadr)->sa_family == AF_LOCAL)
1126
debug(D_LISTENER, "New UNKNOWN web client from %s port %s on socket %d.", client_ip, client_port, fd);
1127
break;
1128
}
1047
-
1048
- if(access_list) {
1049
- if(!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) {
1050
- strncpy(client_ip, "localhost", ipsize);
1051
- client_ip[ipsize - 1] = '\0';
1052
- }
1053
-
1054
- if(unlikely(!simple_pattern_matches(access_list, client_ip))) {
1055
- errno = 0;
1056
- debug(D_LISTENER, "Permission denied for client '%s', port '%s'", client_ip, client_port);
1057
- error("DENIED ACCESS to client '%s'", client_ip);
1058
- close(nfd);
1059
- nfd = -1;
1060
- errno = EPERM;
1061
- }
1129
+ if(!connection_allowed(nfd, client_ip, client_host, hostsize, access_list, "connection")) {
1130
+ errno = 0;
1131
+ error("Permission denied for client '%s', port '%s'", client_ip, client_port);
1132
+ close(nfd);
1133
+ nfd = -1;
1134
+ errno = EPERM;
1135
}
1136
}
1137
#ifdef HAVE_ACCEPT4
1157
, uint32_t flags
1158
, const char *client_ip
1159
, const char *client_port
1160
+ , const char *client_host
1161
, void *(*add_callback)(POLLINFO * /*pi*/, short int * /*events*/, void * /*data*/)
1162
, void (*del_callback)(POLLINFO * /*pi*/)
1163
, int (*rcv_callback)(POLLINFO * /*pi*/, short int * /*events*/)
1197
1198
p->inf[i].client_ip = NULL;
1199
p->inf[i].client_port = NULL;
1200
+ p->inf[i].client_host = NULL;
1201
p->inf[i].del_callback = p->del_callback;
1202
p->inf[i].rcv_callback = p->rcv_callback;
1203
p->inf[i].snd_callback = p->snd_callback;
1228
pi->port_acl = port_acl;
1229
pi->flags = flags;
1230
pi->next = NULL;
1156
- pi->client_ip = strdupz(client_ip);
1231
+ pi->client_ip = strdupz(client_ip);
1232
pi->client_port = strdupz(client_port);
1233
+ pi->client_host = strdupz(client_host);
1234
1235
pi->del_callback = del_callback;
1236
pi->rcv_callback = rcv_callback;
1432
1433
int nfd;
1434
do {
1359
- char client_ip[NI_MAXHOST + 1];
1360
- char client_port[NI_MAXSERV + 1];
1361
- client_ip[0] = 0x00;
1362
- client_port[0] = 0x00;
1435
+ char client_ip[INET6_ADDRSTRLEN];
1436
+ char client_port[NI_MAXSERV];
1437
+ char client_host[NI_MAXHOST];
1438
+ client_host[0] = 0;
1439
+ client_ip[0] = 0;
1440
+ client_port[0] = 0;
1441
1442
debug(D_POLLFD, "POLLFD: LISTENER: calling accept4() slot %zu (fd %d)", i, fd);
1365
- nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, NI_MAXHOST + 1, client_port, NI_MAXSERV + 1, p->access_list);
1443
+ nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, INET6_ADDRSTRLEN, client_port, NI_MAXSERV,
1444
+ client_host, NI_MAXHOST, p->access_list);
1445
if (unlikely(nfd < 0)) {
1446
// accept failed
1447
1466
, POLLINFO_FLAG_CLIENT_SOCKET
1467
, client_ip
1468
, client_port
1469
+ , client_host
1470
, p->add_callback
1471
, p->del_callback
1472
, p->rcv_callback
1610
, POLLINFO_FLAG_SERVER_SOCKET
1611
, (sockets->fds_names[i])?sockets->fds_names[i]:"UNKNOWN"
1612
, ""
1613
+ , ""
1614
, p.add_callback
1615
, p.del_callback
1616
, p.rcv_callback