diff options
author | Cy Schubert <cy@FreeBSD.org> | 2020-05-21 05:01:52 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2020-05-21 05:01:52 +0000 |
commit | 6a53c00e64c4cf911eb00846733d9e6a47b2e7f4 (patch) | |
tree | 60a7720d2d4edfe62b094e2665743e8879ebb911 /util/net_help.c | |
parent | e2fe726866d062155f6b1aae749375475ef19191 (diff) |
Diffstat (limited to 'util/net_help.c')
-rw-r--r-- | util/net_help.c | 123 |
1 files changed, 121 insertions, 2 deletions
diff --git a/util/net_help.c b/util/net_help.c index 9747b5d55a781..0869f91f954e3 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -284,6 +284,113 @@ int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, return 1; } +/* RPZ format address dname to network byte order address */ +static int ipdnametoaddr(uint8_t* dname, size_t dnamelen, + struct sockaddr_storage* addr, socklen_t* addrlen, int* af) +{ + uint8_t* ia; + size_t dnamelabs = dname_count_labels(dname); + uint8_t lablen; + char* e = NULL; + int z = 0; + size_t len = 0; + int i; + *af = AF_INET; + + /* need 1 byte for label length */ + if(dnamelen < 1) + return 0; + + if(dnamelabs > 6 || + dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) { + *af = AF_INET6; + } + len = *dname; + lablen = *dname++; + i = (*af == AF_INET) ? 3 : 15; + if(*af == AF_INET6) { + struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; + *addrlen = (socklen_t)sizeof(struct sockaddr_in6); + memset(sa, 0, *addrlen); + sa->sin6_family = AF_INET6; + ia = (uint8_t*)&sa->sin6_addr; + } else { /* ip4 */ + struct sockaddr_in* sa = (struct sockaddr_in*)addr; + *addrlen = (socklen_t)sizeof(struct sockaddr_in); + memset(sa, 0, *addrlen); + sa->sin_family = AF_INET; + ia = (uint8_t*)&sa->sin_addr; + } + while(lablen && i >= 0 && len <= dnamelen) { + char buff[LDNS_MAX_LABELLEN+1]; + uint16_t chunk; /* big enough to not overflow on IPv6 hextet */ + if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) || + (*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) { + return 0; + } + if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) { + /* Add one or more 0 labels. Address is initialised at + * 0, so just skip the zero part. */ + int zl = 11 - dnamelabs; + if(z || zl < 0) + return 0; + z = 1; + i -= (zl*2); + } else { + memcpy(buff, dname, lablen); + buff[lablen] = '\0'; + chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16); + if(!e || *e != '\0' || (*af == AF_INET && chunk > 255)) + return 0; + if(*af == AF_INET) { + log_assert(i < 4 && i >= 0); + ia[i] = (uint8_t)chunk; + i--; + } else { + log_assert(i < 16 && i >= 1); + /* ia in network byte order */ + ia[i-1] = (uint8_t)(chunk >> 8); + ia[i] = (uint8_t)(chunk & 0x00FF); + i -= 2; + } + } + dname += lablen; + lablen = *dname++; + len += lablen; + } + if(i != -1) + /* input too short */ + return 0; + return 1; +} + +int netblockdnametoaddr(uint8_t* dname, size_t dnamelen, + struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af) +{ + char buff[3 /* 3 digit netblock */ + 1]; + size_t nlablen; + if(dnamelen < 1 || *dname > 3) + /* netblock invalid */ + return 0; + nlablen = *dname; + + if(dnamelen < 1 + nlablen) + return 0; + + memcpy(buff, dname+1, nlablen); + buff[nlablen] = '\0'; + *net = atoi(buff); + if(*net == 0 && strcmp(buff, "0") != 0) + return 0; + dname += nlablen; + dname++; + if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af)) + return 0; + if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32)) + return 0; + return 1; +} + int authextstrtoaddr(char* str, struct sockaddr_storage* addr, socklen_t* addrlen, char** auth_name) { @@ -728,11 +835,13 @@ listen_sslctx_setup(void* ctxt) #ifdef HAVE_SSL SSL_CTX* ctx = (SSL_CTX*)ctxt; /* no SSLv2, SSLv3 because has defects */ +#if SSL_OP_NO_SSLv2 != 0 if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) != SSL_OP_NO_SSLv2){ log_crypto_err("could not set SSL_OP_NO_SSLv2"); return 0; } +#endif if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) != SSL_OP_NO_SSLv3){ log_crypto_err("could not set SSL_OP_NO_SSLv3"); @@ -968,12 +1077,14 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert) log_crypto_err("could not allocate SSL_CTX pointer"); return NULL; } +#if SSL_OP_NO_SSLv2 != 0 if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) != SSL_OP_NO_SSLv2) { log_crypto_err("could not set SSL_OP_NO_SSLv2"); SSL_CTX_free(ctx); return NULL; } +#endif if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) != SSL_OP_NO_SSLv3) { log_crypto_err("could not set SSL_OP_NO_SSLv3"); @@ -1160,13 +1271,21 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses s++; } keys = calloc(s, sizeof(struct tls_session_ticket_key)); + if(!keys) + return 0; memset(keys, 0, s*sizeof(*keys)); ticket_keys = keys; for(p = tls_session_ticket_keys; p; p = p->next) { size_t n; - unsigned char *data = (unsigned char *)malloc(80); - FILE *f = fopen(p->str, "r"); + unsigned char *data; + FILE *f; + + data = (unsigned char *)malloc(80); + if(!data) + return 0; + + f = fopen(p->str, "r"); if(!f) { log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno)); free(data); |