rp

simple email tools
git clone https://git.parazyd.org/rp
Log | Files | Refs | README | LICENSE

net.c (5366B)


      1 /* See LICENSE file for copyright and license details */
      2 
      3 #include <unistd.h>
      4 #include <netdb.h>
      5 
      6 #include <openssl/ssl.h>
      7 #include <openssl/err.h>
      8 
      9 #include "ind.h"
     10 #include "net.h"
     11 
     12 /*
     13  * net format:
     14  * net!addr!service
     15  */
     16 enum {
     17 	NET_NET = 0x00,
     18 	NET_TCP,
     19 	NET_TCPS
     20 };
     21 
     22 static char *netnames[] = {
     23 	[NET_NET] = "net",
     24 	[NET_TCP] = "tcp",
     25 	[NET_TCPS] = "tcps"
     26 };
     27 
     28 int net_gettype(char *str) {
     29 	unsigned long int i;
     30 
     31 	for (i = 0; i < nelem(netnames); i++)
     32 		if (!strcmp(netnames[i], str))
     33 			return i;
     34 	return -1;
     35 }
     36 
     37 net_t *net_new(char *desc) {
     38 	net_t *ret;
     39 	int state;
     40 	char *tok, *buf, *toks;
     41 
     42 	state = -1;
     43 	toks = NULL;
     44 	ret = NULL;
     45 	buf = memdup(desc, strlen(desc)+1);
     46 
     47 	tok = strtok_r(buf, "!", &toks);
     48 	if (tok == NULL)
     49 		goto netnewerror;
     50 
     51 	ret = mallocz(sizeof(net_t), 2);
     52 	do {
     53 		state++;
     54 		switch(state) {
     55 		case 0:
     56 			ret->net = memdup(tok, strlen(tok)+1);
     57 			ret->type = net_gettype(ret->net);
     58 			break;
     59 		case 1:
     60 			ret->addr = memdup(tok, strlen(tok)+1);
     61 			break;
     62 		case 2:
     63 			ret->service = memdup(tok, strlen(tok)+1);
     64 			break;
     65 		case 3:
     66 			ret->options = memdup(tok, strlen(tok)+1);
     67 			break;
     68 		default:
     69 			break;
     70 		}
     71 	} while ((tok = strtok_r(NULL, "!", &toks)) != NULL);
     72 	if (state < 2)
     73 		goto netnewerror;
     74 	free(buf);
     75 
     76 	return ret;
     77 netnewerror:
     78 	if (buf != NULL)
     79 		free(buf);
     80 
     81 	switch (state) {
     82 	case 1:
     83 		free(ret->addr);
     84 	case 0:
     85 		free(ret->net);
     86 	default:
     87 		break;
     88 	}
     89 	if (ret != NULL)
     90 		free(ret);
     91 
     92 	return NULL;
     93 }
     94 
     95 void net_free(net_t *net) {
     96 	if (net->net != NULL)
     97 		free(net->net);
     98 	if (net->addr != NULL)
     99 		free(net->addr);
    100 	if (net->service != NULL)
    101 		free(net->service);
    102 	free(net);
    103 }
    104 
    105 int net_connecttcp(net_t *net) {
    106 	struct addrinfo hints, *ai, *rp;
    107 
    108 	memset(&hints, 0, sizeof(hints));
    109 
    110 	hints.ai_family = AF_UNSPEC;
    111 	hints.ai_socktype = SOCK_STREAM;
    112 	hints.ai_protocol = IPPROTO_TCP;
    113 	if (getaddrinfo(net->addr, net->service, &hints, &ai))
    114 		return 1;
    115 	if (ai == NULL)
    116 		return 1;
    117 
    118 	for (rp = ai; rp != NULL; rp = rp->ai_next) {
    119 		net->fd = socket(rp->ai_family, rp->ai_socktype,
    120 				rp->ai_protocol);
    121 		if (net->fd < 0)
    122 			continue;
    123 		if (!connect(net->fd, rp->ai_addr, rp->ai_addrlen))
    124 			break;
    125 		close(net->fd);
    126 	}
    127 	if (rp == NULL)
    128 		return 1;
    129 	freeaddrinfo(ai);
    130 
    131 	return 0;
    132 }
    133 
    134 int net_addssl(net_t *net) {
    135 	SSL *sfd;
    136 	long opts;
    137 
    138 	SSL_library_init();
    139 	OpenSSL_add_all_algorithms();
    140 	net->data[1] = SSL_CTX_new(SSLv23_method());
    141 	if (net->data[1] == NULL)
    142 		goto netaddsslerr;
    143 
    144 	opts = SSL_CTX_get_options(net->data[1]);
    145 	opts |= SSL_OP_NO_SSLv2;
    146 	opts |= SSL_OP_NO_SSLv3;
    147 	opts |= SSL_OP_NO_TLSv1;
    148 	opts |= SSL_OP_NO_TLSv1_1;
    149 	SSL_CTX_set_options((SSL_CTX *)net->data[1], opts);
    150 
    151 	if ((sfd = SSL_new((SSL_CTX *)net->data[1])) == NULL)
    152 		goto netaddsslerr;
    153 	SSL_set_fd(sfd, net->fd);
    154 	if (SSL_connect(sfd) < 1)
    155 		goto netaddsslerr;
    156 
    157 	switch (net->type) {
    158 	case NET_NET:
    159 	case NET_TCP:
    160 		free(net->net);
    161 		net->net = memdup("tcps", 5);
    162 		net->type = net_gettype(net->net);
    163 	case NET_TCPS:
    164 	default:
    165 		break;
    166 	}
    167 
    168 	net->data[0] = sfd;
    169 
    170 	return 0;
    171 netaddsslerr:
    172 	SSL_load_error_strings();
    173 	ERR_print_errors_fp(stderr);
    174 	ERR_free_strings();
    175 	return 1;
    176 }
    177 
    178 int net_connecttcps(net_t *net) {
    179 	if (net_connecttcp(net))
    180 		return 1;
    181 	if (net_addssl(net))
    182 		return 1;
    183 
    184 	return 0;
    185 }
    186 
    187 int net_connect(net_t *net) {
    188 	switch (net->type) {
    189 	case NET_NET:
    190 	case NET_TCP:
    191 		return net_connecttcp(net);
    192 	case NET_TCPS:
    193 		return net_connecttcps(net);
    194 	default:
    195 		return 1;
    196 	}
    197 
    198 	return 0;
    199 }
    200 
    201 void net_closetcp(net_t *net) {
    202 	shutdown(net->fd, SHUT_RDWR);
    203 	close(net->fd);
    204 }
    205 
    206 void net_closetcps(net_t *net) {
    207 	SSL_CTX_free((SSL_CTX *)net->data[1]);
    208 	SSL_free((SSL *)net->data[0]);
    209 	EVP_cleanup();
    210 	CRYPTO_cleanup_all_ex_data();
    211 }
    212 
    213 void net_close(net_t *net) {
    214 	switch (net->type) {
    215 	case NET_NET:
    216 	case NET_TCP:
    217 		net_closetcp(net);
    218 	case NET_TCPS:
    219 		net_closetcps(net);
    220 	default:
    221 		break;
    222 	}
    223 }
    224 
    225 int net_writetcp(net_t *net, char *buf, int len) {
    226 	return send(net->fd, buf, len, MSG_NOSIGNAL);
    227 }
    228 
    229 int net_writetcps(net_t *net, char *buf, int len) {
    230 	return SSL_write((SSL *)net->data[0], buf, len);
    231 }
    232 
    233 int net_write(net_t *net, char *buf, int len) {
    234 	switch (net->type) {
    235 	case NET_NET:
    236 	case NET_TCP:
    237 		return net_writetcp(net, buf, len);
    238 	case NET_TCPS:
    239 		return net_writetcps(net, buf, len);
    240 	default:
    241 		return -1;
    242 	}
    243 	return -1;
    244 }
    245 
    246 
    247 int net_writeall(net_t *net, char *buf, int len) {
    248 
    249 	int olen, nlen;
    250 
    251 	for (olen = 0;
    252 			(nlen = net_write(net, &buf[olen], len-olen))
    253 			&& olen < len; olen += nlen);
    254 
    255 	return 0;
    256 }
    257 
    258 int net_printf(net_t *net, char *fmt, ...) {
    259 	va_list fmtargs;
    260 	char *buf;
    261 	int len;
    262 
    263 	va_start(fmtargs, fmt);
    264 	len = vsnprintf(NULL, 0, fmt, fmtargs);
    265 	va_end(fmtargs);
    266 
    267 	va_start(fmtargs, fmt);
    268 	buf = vsmprintf(fmt, fmtargs, len);
    269 	va_end(fmtargs);
    270 
    271 	len = net_writeall(net, buf, strlen(buf));
    272 	free(buf);
    273 	return len;
    274 }
    275 
    276 int net_readtcp(net_t *net, char *buf, int len) {
    277 	return recv(net->fd, buf, len, 0);
    278 }
    279 
    280 int net_readtcps(net_t *net, char *buf, int len) {
    281 	return SSL_read((SSL *)net->data[0], buf, len);
    282 }
    283 
    284 int net_read(net_t *net, char *buf, int len) {
    285 	switch (net->type) {
    286 	case NET_NET:
    287 	case NET_TCP:
    288 		return net_readtcp(net, buf, len);
    289 	case NET_TCPS:
    290 		return net_readtcps(net, buf, len);
    291 	default:
    292 		return -1;
    293 	}
    294 	return -1;
    295 }
    296 
    297 int net_readall(net_t *net, char *buf, int len) {
    298 	int olen, nlen;
    299 
    300 	for (olen = 0;
    301 			(nlen = net_read(net, &buf[olen], len-olen))
    302 			&& olen < len; olen += nlen);
    303 
    304 	return 0;
    305 }