Added an optional validation argument to sim_parse_addr for callers which need to confirm incoming connections come from expected sources
This commit is contained in:
parent
822fedf8ce
commit
7f6a1af5bf
8 changed files with 135 additions and 104 deletions
|
@ -154,7 +154,7 @@ static t_stat net_attach(UNIT *uptr, char *cptr) {
|
||||||
char host[CBUFSIZE], port[CBUFSIZE];
|
char host[CBUFSIZE], port[CBUFSIZE];
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = sim_parse_addr (cptr, host, sizeof(host), "localhost", port, sizeof(port), "3000");
|
r = sim_parse_addr (cptr, host, sizeof(host), "localhost", port, sizeof(port), "3000", NULL);
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
net_reset(&net_dev);
|
net_reset(&net_dev);
|
||||||
|
|
|
@ -581,7 +581,7 @@ if (oldf & UNIT_ATT)
|
||||||
ipl_detach (uptr);
|
ipl_detach (uptr);
|
||||||
if ((sim_switches & SWMASK ('C')) ||
|
if ((sim_switches & SWMASK ('C')) ||
|
||||||
((sim_switches & SIM_SW_REST) && (oldf & UNIT_ACTV))) {
|
((sim_switches & SIM_SW_REST) && (oldf & UNIT_ACTV))) {
|
||||||
r = sim_parse_addr (cptr, host, sizeof(host), "localhost", port, sizeof(port), NULL);
|
r = sim_parse_addr (cptr, host, sizeof(host), "localhost", port, sizeof(port), NULL, NULL);
|
||||||
if ((r != SCPE_OK) || (port[0] == '\0'))
|
if ((r != SCPE_OK) || (port[0] == '\0'))
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
sprintf(hostport, "%s%s%s%s%s", strchr(host, ':') ? "[" : "", host, strchr(host, ':') ? "]" : "", host[0] ? ":" : "", port);
|
sprintf(hostport, "%s%s%s%s%s", strchr(host, ':') ? "[" : "", host, strchr(host, ':') ? "]" : "", host[0] ? ":" : "", port);
|
||||||
|
@ -597,7 +597,7 @@ if ((sim_switches & SWMASK ('C')) ||
|
||||||
uptr->DSOCKET = newsock;
|
uptr->DSOCKET = newsock;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), NULL);
|
r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL);
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
sprintf(hostport, "%s%s%s%s%s", strchr(host, ':') ? "[" : "", host, strchr(host, ':') ? "]" : "", host[0] ? ":" : "", port);
|
sprintf(hostport, "%s%s%s%s%s", strchr(host, ':') ? "[" : "", host, strchr(host, ':') ? "]" : "", host[0] ? ":" : "", port);
|
||||||
|
|
|
@ -462,7 +462,7 @@ static t_stat sca_attach (UNIT *uptr, char *cptr)
|
||||||
detach_unit(&sca_unit);
|
detach_unit(&sca_unit);
|
||||||
|
|
||||||
if (do_listen) { /* if listen mode, string specifies port number (only; otherwise it's a dummy argument) */
|
if (do_listen) { /* if listen mode, string specifies port number (only; otherwise it's a dummy argument) */
|
||||||
r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), SCA_DEFAULT_PORT);
|
r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), SCA_DEFAULT_PORT, NULL);
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return r;
|
return r;
|
||||||
if ((0 == strcmp(port, cptr)) && (0 == strcmp(port, "dummy")))
|
if ((0 == strcmp(port, cptr)) && (0 == strcmp(port, "dummy")))
|
||||||
|
@ -493,7 +493,7 @@ static t_stat sca_attach (UNIT *uptr, char *cptr)
|
||||||
if (! *cptr)
|
if (! *cptr)
|
||||||
return SCPE_2FARG;
|
return SCPE_2FARG;
|
||||||
|
|
||||||
r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), SCA_DEFAULT_PORT);
|
r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), SCA_DEFAULT_PORT, NULL);
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return r;
|
return r;
|
||||||
if ((0 == strcmp(cptr, port)) && (0 == strcmp(host, ""))) {
|
if ((0 == strcmp(cptr, port)) && (0 == strcmp(host, ""))) {
|
||||||
|
|
|
@ -565,7 +565,7 @@ t_stat dmc_setpeer (UNIT* uptr, int32 val, char* cptr, void* desc)
|
||||||
|
|
||||||
if (!cptr) return SCPE_IERR;
|
if (!cptr) return SCPE_IERR;
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
status = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), NULL);
|
status = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL);
|
||||||
if (status != SCPE_OK)
|
if (status != SCPE_OK)
|
||||||
return status;
|
return status;
|
||||||
if (host[0] == '\0')
|
if (host[0] == '\0')
|
||||||
|
@ -1588,8 +1588,7 @@ int dmc_get_receive_socket(CTLR *controller, int forRead)
|
||||||
{
|
{
|
||||||
char host[sizeof(controller->line->transmit_host)];
|
char host[sizeof(controller->line->transmit_host)];
|
||||||
|
|
||||||
sim_parse_addr (controller->line->transmit_host, host, sizeof(host), NULL, NULL, 0, NULL);
|
if (sim_parse_addr (controller->line->transmit_host, host, sizeof(host), NULL, NULL, 0, NULL, ipaddr))
|
||||||
if (strcmp(ipaddr, host))
|
|
||||||
{
|
{
|
||||||
sim_debug(DBG_WRN, controller->device, "Received connection from unexpected source IP %s. Closing the connection.\n", ipaddr);
|
sim_debug(DBG_WRN, controller->device, "Received connection from unexpected source IP %s. Closing the connection.\n", ipaddr);
|
||||||
dmc_close_receive(controller, "Unathorized connection", ipaddr);
|
dmc_close_receive(controller, "Unathorized connection", ipaddr);
|
||||||
|
|
|
@ -498,7 +498,7 @@ while (*cptr != 0) { /* do all mods */
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = sim_parse_addr (gbuf, NULL, 0, NULL, NULL, 0, NULL);
|
r = sim_parse_addr (gbuf, NULL, 0, NULL, NULL, 0, NULL, NULL);
|
||||||
if (r == SCPE_OK) {
|
if (r == SCPE_OK) {
|
||||||
if (sim_con_tmxr.master) /* already open? */
|
if (sim_con_tmxr.master) /* already open? */
|
||||||
sim_set_notelnet (0, NULL); /* close first */
|
sim_set_notelnet (0, NULL); /* close first */
|
||||||
|
|
215
sim_sock.c
215
sim_sock.c
|
@ -75,95 +75,6 @@ extern FILE *sim_log;
|
||||||
sim_msg_sock send message to socket
|
sim_msg_sock send message to socket
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* OS independent routines
|
|
||||||
|
|
||||||
sim_parse_addr parse a hostname/ipaddress from port and apply defaults
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* sim_parse_addr host:port
|
|
||||||
|
|
||||||
Presumption is that the input, if it doesn't contain a ':' character is a port specifier.
|
|
||||||
If the host field contains one or more colon characters (i.e. it is an IPv6 address),
|
|
||||||
the IPv6 address MUST be enclosed in square bracket characters (i.e. Domain Literal format)
|
|
||||||
|
|
||||||
Inputs:
|
|
||||||
cptr = pointer to input string
|
|
||||||
default_host
|
|
||||||
= optional pointer to default host if none specified
|
|
||||||
host_len = length of host buffer
|
|
||||||
default_port
|
|
||||||
= optional pointer to default host if none specified
|
|
||||||
port_len = length of port buffer
|
|
||||||
Outputs:
|
|
||||||
host = pointer to buffer for IP address (may be NULL), 0 = none
|
|
||||||
port = pointer to buffer for IP port (may be NULL), 0 = none
|
|
||||||
result = status
|
|
||||||
*/
|
|
||||||
|
|
||||||
t_stat sim_parse_addr (const char *cptr, char *host, size_t host_len, const char *default_host, char *port, size_t port_len, const char *default_port)
|
|
||||||
{
|
|
||||||
char gbuf[CBUFSIZE];
|
|
||||||
char *hostp, *portp;
|
|
||||||
char *endc;
|
|
||||||
unsigned long portval;
|
|
||||||
|
|
||||||
if ((cptr == NULL) || (*cptr == 0))
|
|
||||||
return SCPE_ARG;
|
|
||||||
if ((host != NULL) && (host_len != 0))
|
|
||||||
memset (host, 0, host_len);
|
|
||||||
if ((port != NULL) && (port_len != 0))
|
|
||||||
memset (port, 0, port_len);
|
|
||||||
strncpy (gbuf, cptr, CBUFSIZE);
|
|
||||||
hostp = gbuf; /* default addr */
|
|
||||||
portp = NULL;
|
|
||||||
if ((portp = strrchr (gbuf, ':')) && /* x:y? split */
|
|
||||||
(NULL == strchr (portp, ']'))) {
|
|
||||||
*portp++ = 0;
|
|
||||||
if (*portp == '\0')
|
|
||||||
portp = (char *)default_port;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (default_port)
|
|
||||||
portp = (char *)default_port;
|
|
||||||
else {
|
|
||||||
portp = gbuf;
|
|
||||||
hostp = NULL;
|
|
||||||
}
|
|
||||||
if (portp != NULL) {
|
|
||||||
portval = strtoul(portp, &endc, 10);
|
|
||||||
if ((*endc == '\0') && ((portval == 0) || (portval > 65535)))
|
|
||||||
return SCPE_ARG; /* value too big */
|
|
||||||
if (*endc != '\0') {
|
|
||||||
struct servent *se = getservbyname(portp, "tcp");
|
|
||||||
|
|
||||||
if (se == NULL)
|
|
||||||
return SCPE_ARG; /* invalid service name */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (port) /* port wanted? */
|
|
||||||
if (portp != NULL) {
|
|
||||||
if (strlen(portp) >= port_len)
|
|
||||||
return SCPE_ARG; /* no room */
|
|
||||||
else
|
|
||||||
strcpy (port, portp);
|
|
||||||
}
|
|
||||||
if (hostp != NULL) {
|
|
||||||
if (']' == hostp[strlen(hostp)-1]) {
|
|
||||||
if ('[' != hostp[0])
|
|
||||||
return SCPE_ARG; /* invalid domain literal */
|
|
||||||
strcpy(hostp, hostp+1); /* remove brackets from domain literal host */
|
|
||||||
hostp[strlen(hostp)-1] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (host) /* host wanted? */
|
|
||||||
if (hostp != NULL)
|
|
||||||
if (strlen(hostp) >= host_len)
|
|
||||||
return SCPE_ARG; /* no room */
|
|
||||||
else
|
|
||||||
strcpy (host, hostp);
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First, all the non-implemented versions */
|
/* First, all the non-implemented versions */
|
||||||
|
|
||||||
#if defined (__OS2__) && !defined (__EMX__)
|
#if defined (__OS2__) && !defined (__EMX__)
|
||||||
|
@ -525,6 +436,128 @@ int load_ws2(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* OS independent routines
|
||||||
|
|
||||||
|
sim_parse_addr parse a hostname/ipaddress from port and apply defaults and
|
||||||
|
optionally validate an address match
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* sim_parse_addr host:port
|
||||||
|
|
||||||
|
Presumption is that the input, if it doesn't contain a ':' character is a port specifier.
|
||||||
|
If the host field contains one or more colon characters (i.e. it is an IPv6 address),
|
||||||
|
the IPv6 address MUST be enclosed in square bracket characters (i.e. Domain Literal format)
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
cptr = pointer to input string
|
||||||
|
default_host
|
||||||
|
= optional pointer to default host if none specified
|
||||||
|
host_len = length of host buffer
|
||||||
|
default_port
|
||||||
|
= optional pointer to default host if none specified
|
||||||
|
port_len = length of port buffer
|
||||||
|
validate_addr = optional name/addr which is checked to be equivalent
|
||||||
|
to the host result of parsing the other input. This
|
||||||
|
address would usually be returned by sim_accept_conn.
|
||||||
|
Outputs:
|
||||||
|
host = pointer to buffer for IP address (may be NULL), 0 = none
|
||||||
|
port = pointer to buffer for IP port (may be NULL), 0 = none
|
||||||
|
result = status (SCPE_OK on complete success or SCPE_ARG if
|
||||||
|
parsing can't happen due to bad syntax, a value is
|
||||||
|
out of range, a result can't fit into a result buffer,
|
||||||
|
a service name doesn't exist, or a validation name
|
||||||
|
doesn't match the parsed host)
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat sim_parse_addr (const char *cptr, char *host, size_t host_len, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr)
|
||||||
|
{
|
||||||
|
char gbuf[CBUFSIZE];
|
||||||
|
char *hostp, *portp;
|
||||||
|
char *endc;
|
||||||
|
unsigned long portval;
|
||||||
|
|
||||||
|
if ((cptr == NULL) || (*cptr == 0))
|
||||||
|
return SCPE_ARG;
|
||||||
|
if ((host != NULL) && (host_len != 0))
|
||||||
|
memset (host, 0, host_len);
|
||||||
|
if ((port != NULL) && (port_len != 0))
|
||||||
|
memset (port, 0, port_len);
|
||||||
|
strncpy (gbuf, cptr, CBUFSIZE);
|
||||||
|
hostp = gbuf; /* default addr */
|
||||||
|
portp = NULL;
|
||||||
|
if ((portp = strrchr (gbuf, ':')) && /* x:y? split */
|
||||||
|
(NULL == strchr (portp, ']'))) {
|
||||||
|
*portp++ = 0;
|
||||||
|
if (*portp == '\0')
|
||||||
|
portp = (char *)default_port;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (default_port)
|
||||||
|
portp = (char *)default_port;
|
||||||
|
else {
|
||||||
|
portp = gbuf;
|
||||||
|
hostp = NULL;
|
||||||
|
}
|
||||||
|
if (portp != NULL) {
|
||||||
|
portval = strtoul(portp, &endc, 10);
|
||||||
|
if ((*endc == '\0') && ((portval == 0) || (portval > 65535)))
|
||||||
|
return SCPE_ARG; /* numeric value too big */
|
||||||
|
if (*endc != '\0') {
|
||||||
|
struct servent *se = getservbyname(portp, "tcp");
|
||||||
|
|
||||||
|
if (se == NULL)
|
||||||
|
return SCPE_ARG; /* invalid service name */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (port) /* port wanted? */
|
||||||
|
if (portp != NULL) {
|
||||||
|
if (strlen(portp) >= port_len)
|
||||||
|
return SCPE_ARG; /* no room */
|
||||||
|
else
|
||||||
|
strcpy (port, portp);
|
||||||
|
}
|
||||||
|
if (hostp != NULL) {
|
||||||
|
if (']' == hostp[strlen(hostp)-1]) {
|
||||||
|
if ('[' != hostp[0])
|
||||||
|
return SCPE_ARG; /* invalid domain literal */
|
||||||
|
strcpy(hostp, hostp+1); /* remove brackets from domain literal host */
|
||||||
|
hostp[strlen(hostp)-1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (host) /* host wanted? */
|
||||||
|
if (hostp != NULL)
|
||||||
|
if (strlen(hostp) >= host_len)
|
||||||
|
return SCPE_ARG; /* no room */
|
||||||
|
else
|
||||||
|
strcpy (host, hostp);
|
||||||
|
if (validate_addr) {
|
||||||
|
struct addrinfo *ai_host, *ai_validate, *ai;
|
||||||
|
t_stat status;
|
||||||
|
|
||||||
|
if (hostp == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (p_getaddrinfo(hostp, NULL, NULL, &ai_host))
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (p_getaddrinfo(validate_addr, NULL, NULL, &ai_validate)) {
|
||||||
|
p_freeaddrinfo (ai_host);
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
|
status = SCPE_ARG;
|
||||||
|
for (ai = ai_host; ai != NULL; ai = ai->ai_next) {
|
||||||
|
if ((ai->ai_addrlen == ai_validate->ai_addrlen) &&
|
||||||
|
(ai->ai_family == ai_validate->ai_family) &&
|
||||||
|
(0 == memcmp (ai->ai_addr, ai_validate->ai_addr, ai->ai_addrlen))) {
|
||||||
|
status = SCPE_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p_freeaddrinfo (ai_host);
|
||||||
|
p_freeaddrinfo (ai_validate);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void sim_init_sock (void)
|
void sim_init_sock (void)
|
||||||
{
|
{
|
||||||
#if defined (_WIN32)
|
#if defined (_WIN32)
|
||||||
|
@ -624,7 +657,7 @@ t_stat r;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result = NULL;
|
struct addrinfo *result = NULL;
|
||||||
|
|
||||||
r = sim_parse_addr (hostport, host, sizeof(host), NULL, port, sizeof(port), NULL);
|
r = sim_parse_addr (hostport, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL);
|
||||||
if (parse_status)
|
if (parse_status)
|
||||||
*parse_status = r;
|
*parse_status = r;
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
|
@ -671,7 +704,7 @@ t_stat r;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result = NULL;
|
struct addrinfo *result = NULL;
|
||||||
|
|
||||||
r = sim_parse_addr (hostport, host, sizeof(host), default_host, port, sizeof(port), default_port);
|
r = sim_parse_addr (hostport, host, sizeof(host), default_host, port, sizeof(port), default_port, NULL);
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return newsock;
|
return newsock;
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
t_stat sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, const char *default_port);
|
t_stat sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr);
|
||||||
SOCKET sim_master_sock (const char *hostport, t_stat *parse_status);
|
SOCKET sim_master_sock (const char *hostport, t_stat *parse_status);
|
||||||
SOCKET sim_connect_sock (const char *hostport, const char *default_host, const char *default_port);
|
SOCKET sim_connect_sock (const char *hostport, const char *default_host, const char *default_port);
|
||||||
SOCKET sim_accept_conn (SOCKET master, char **connectaddr);
|
SOCKET sim_accept_conn (SOCKET master, char **connectaddr);
|
||||||
|
|
|
@ -791,8 +791,7 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se
|
||||||
if (lp->destination) { /* Virtual Null Modem Cable? */
|
if (lp->destination) { /* Virtual Null Modem Cable? */
|
||||||
char host[CBUFSIZE];
|
char host[CBUFSIZE];
|
||||||
|
|
||||||
sim_parse_addr (lp->destination, host, sizeof(host), NULL, NULL, 0, NULL);
|
if (sim_parse_addr (lp->destination, host, sizeof(host), NULL, NULL, 0, NULL, address)) {
|
||||||
if (strcmp(address, host)) {
|
|
||||||
tmxr_msg (newsock, "Rejecting connection from unexpected source\r\n");
|
tmxr_msg (newsock, "Rejecting connection from unexpected source\r\n");
|
||||||
sprintf (msg, "tmxr_poll_conn() - Rejecting line connection from: %s, Expected: %s", address, host);
|
sprintf (msg, "tmxr_poll_conn() - Rejecting line connection from: %s, Expected: %s", address, host);
|
||||||
tmxr_debug_trace_line (lp, msg);
|
tmxr_debug_trace_line (lp, msg);
|
||||||
|
@ -1459,7 +1458,7 @@ while (*tptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cptr = get_glyph (gbuf, port, ';');
|
cptr = get_glyph (gbuf, port, ';');
|
||||||
if (SCPE_OK != sim_parse_addr (port, NULL, 0, NULL, NULL, 0, NULL))
|
if (SCPE_OK != sim_parse_addr (port, NULL, 0, NULL, NULL, 0, NULL, NULL))
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
if (cptr)
|
if (cptr)
|
||||||
get_glyph (cptr, cptr, 0); /* upcase this string */
|
get_glyph (cptr, cptr, 0); /* upcase this string */
|
||||||
|
|
Loading…
Add table
Reference in a new issue