]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/bio/b_sock.c
Accept NULL in *_free.
[thirdparty/openssl.git] / crypto / bio / b_sock.c
1 /* crypto/bio/b_sock.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59 #ifndef NO_SOCK
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <errno.h>
64 #define USE_SOCKETS
65 #include "cryptlib.h"
66 #include "bio.h"
67
68 /* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */
69
70 #ifdef WIN16
71 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
72 #else
73 #define SOCKET_PROTOCOL IPPROTO_TCP
74 #endif
75
76 #ifdef SO_MAXCONN
77 #define MAX_LISTEN SOMAXCONN
78 #elif defined(SO_MAXCONN)
79 #define MAX_LISTEN SO_MAXCONN
80 #else
81 #define MAX_LISTEN 32
82 #endif
83
84 #ifdef WINDOWS
85 static int wsa_init_done=0;
86 #endif
87
88 static unsigned long BIO_ghbn_hits=0L;
89 static unsigned long BIO_ghbn_miss=0L;
90
91 #define GHBN_NUM 4
92 static struct ghbn_cache_st
93 {
94 char name[129];
95 struct hostent *ent;
96 unsigned long order;
97 } ghbn_cache[GHBN_NUM];
98
99 #ifndef NOPROTO
100 static int get_ip(char *str,unsigned char *ip);
101 static void ghbn_free(struct hostent *a);
102 static struct hostent *ghbn_dup(struct hostent *a);
103 #else
104 static int get_ip();
105 static void ghbn_free();
106 static struct hostent *ghbn_dup();
107 #endif
108
109 int BIO_get_host_ip(str,ip)
110 char *str;
111 unsigned char *ip;
112 {
113 int i;
114 struct hostent *he;
115
116 i=get_ip(str,ip);
117 if (i > 0) return(1);
118 if (i < 0)
119 {
120 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
121 ERR_add_error_data(2,"host=",str);
122 return(0);
123 }
124 else
125 { /* do a gethostbyname */
126 if (!BIO_sock_init()) return(0);
127
128 he=BIO_gethostbyname(str);
129 if (he == NULL)
130 {
131 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
132 ERR_add_error_data(2,"host=",str);
133 return(0);
134 }
135
136 /* cast to short because of win16 winsock definition */
137 if ((short)he->h_addrtype != AF_INET)
138 {
139 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
140 ERR_add_error_data(2,"host=",str);
141 return(0);
142 }
143 for (i=0; i<4; i++)
144 ip[i]=he->h_addr_list[0][i];
145 }
146 return(1);
147 }
148
149 int BIO_get_port(str,port_ptr)
150 char *str;
151 unsigned short *port_ptr;
152 {
153 int i;
154 struct servent *s;
155
156 if (str == NULL)
157 {
158 BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED);
159 return(0);
160 }
161 i=atoi(str);
162 if (i != 0)
163 *port_ptr=(unsigned short)i;
164 else
165 {
166 s=getservbyname(str,"tcp");
167 if (s == NULL)
168 {
169 if (strcmp(str,"http") == 0)
170 *port_ptr=80;
171 else if (strcmp(str,"telnet") == 0)
172 *port_ptr=23;
173 else if (strcmp(str,"socks") == 0)
174 *port_ptr=1080;
175 else if (strcmp(str,"https") == 0)
176 *port_ptr=443;
177 else if (strcmp(str,"ssl") == 0)
178 *port_ptr=443;
179 else if (strcmp(str,"ftp") == 0)
180 *port_ptr=21;
181 else if (strcmp(str,"gopher") == 0)
182 *port_ptr=70;
183 #if 0
184 else if (strcmp(str,"wais") == 0)
185 *port_ptr=21;
186 #endif
187 else
188 {
189 SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error());
190 ERR_add_error_data(3,"service='",str,"'");
191 return(0);
192 }
193 return(1);
194 }
195 *port_ptr=htons((unsigned short)s->s_port);
196 }
197 return(1);
198 }
199
200 int BIO_sock_error(sock)
201 int sock;
202 {
203 int j,i,size;
204
205 size=sizeof(int);
206
207 i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,&size);
208 if (i < 0)
209 return(1);
210 else
211 return(j);
212 }
213
214 long BIO_ghbn_ctrl(cmd,iarg,parg)
215 int cmd;
216 int iarg;
217 char *parg;
218 {
219 int i;
220 char **p;
221
222 switch (cmd)
223 {
224 case BIO_GHBN_CTRL_HITS:
225 return(BIO_ghbn_hits);
226 /* break; */
227 case BIO_GHBN_CTRL_MISSES:
228 return(BIO_ghbn_miss);
229 /* break; */
230 case BIO_GHBN_CTRL_CACHE_SIZE:
231 return(GHBN_NUM);
232 /* break; */
233 case BIO_GHBN_CTRL_GET_ENTRY:
234 if ((iarg >= 0) && (iarg <GHBN_NUM) &&
235 (ghbn_cache[iarg].order > 0))
236 {
237 p=(char **)parg;
238 if (p == NULL) return(0);
239 *p=ghbn_cache[iarg].name;
240 ghbn_cache[iarg].name[128]='\0';
241 return(1);
242 }
243 return(0);
244 /* break; */
245 case BIO_GHBN_CTRL_FLUSH:
246 for (i=0; i<GHBN_NUM; i++)
247 ghbn_cache[i].order=0;
248 break;
249 default:
250 return(0);
251 }
252 return(1);
253 }
254
255 static struct hostent *ghbn_dup(a)
256 struct hostent *a;
257 {
258 struct hostent *ret;
259 int i,j;
260
261 MemCheck_off();
262 ret=(struct hostent *)Malloc(sizeof(struct hostent));
263 if (ret == NULL) return(NULL);
264 memset(ret,0,sizeof(struct hostent));
265
266 for (i=0; a->h_aliases[i] != NULL; i++)
267 ;
268 i++;
269 ret->h_aliases=(char **)Malloc(sizeof(char *)*i);
270 memset(ret->h_aliases,0,sizeof(char *)*i);
271 if (ret == NULL) goto err;
272
273 for (i=0; a->h_addr_list[i] != NULL; i++)
274 ;
275 i++;
276 ret->h_addr_list=(char **)Malloc(sizeof(char *)*i);
277 memset(ret->h_addr_list,0,sizeof(char *)*i);
278 if (ret->h_addr_list == NULL) goto err;
279
280 j=strlen(a->h_name)+1;
281 if ((ret->h_name=Malloc(j)) == NULL) goto err;
282 memcpy((char *)ret->h_name,a->h_name,j+1);
283 for (i=0; a->h_aliases[i] != NULL; i++)
284 {
285 j=strlen(a->h_aliases[i])+1;
286 if ((ret->h_aliases[i]=Malloc(j)) == NULL) goto err;
287 memcpy(ret->h_aliases[i],a->h_aliases[i],j+1);
288 }
289 ret->h_length=a->h_length;
290 ret->h_addrtype=a->h_addrtype;
291 for (i=0; a->h_addr_list[i] != NULL; i++)
292 {
293 if ((ret->h_addr_list[i]=Malloc(a->h_length)) == NULL)
294 goto err;
295 memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
296 }
297 if (0)
298 {
299 err:
300 if (ret != NULL)
301 ghbn_free(ret);
302 ret=NULL;
303 }
304 MemCheck_on();
305 return(ret);
306 }
307
308 static void ghbn_free(a)
309 struct hostent *a;
310 {
311 int i;
312
313 if(a == NULL)
314 return;
315
316 if (a->h_aliases != NULL)
317 {
318 for (i=0; a->h_aliases[i] != NULL; i++)
319 Free(a->h_aliases[i]);
320 Free(a->h_aliases);
321 }
322 if (a->h_addr_list != NULL)
323 {
324 for (i=0; a->h_addr_list[i] != NULL; i++)
325 Free(a->h_addr_list[i]);
326 Free(a->h_addr_list);
327 }
328 if (a->h_name != NULL) Free((char *)a->h_name);
329 Free(a);
330 }
331
332 struct hostent *BIO_gethostbyname(name)
333 char *name;
334 {
335 struct hostent *ret;
336 int i,lowi=0,j;
337 unsigned long low= (unsigned long)-1;
338
339 /* return(gethostbyname(name)); */
340
341 CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
342 j=strlen(name);
343 if (j < 128)
344 {
345 for (i=0; i<GHBN_NUM; i++)
346 {
347 if (low > ghbn_cache[i].order)
348 {
349 low=ghbn_cache[i].order;
350 lowi=i;
351 }
352 if (ghbn_cache[i].order > 0)
353 {
354 if (strncmp(name,ghbn_cache[i].name,128) == 0)
355 break;
356 }
357 }
358 }
359 else
360 i=GHBN_NUM;
361
362 if (i == GHBN_NUM) /* no hit*/
363 {
364 BIO_ghbn_miss++;
365 ret=gethostbyname(name);
366
367 if (ret == NULL) return(NULL);
368 if (j > 128) return(ret); /* too big to cache */
369
370 /* else add to cache */
371 if (ghbn_cache[lowi].ent != NULL)
372 ghbn_free(ghbn_cache[lowi].ent);
373
374 strncpy(ghbn_cache[lowi].name,name,128);
375 ghbn_cache[lowi].ent=ghbn_dup(ret);
376 ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
377 }
378 else
379 {
380 BIO_ghbn_hits++;
381 ret= ghbn_cache[i].ent;
382 ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
383 }
384 CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
385 return(ret);
386 }
387
388 int BIO_sock_init()
389 {
390 #ifdef WINDOWS
391 static struct WSAData wsa_state;
392
393 if (!wsa_init_done)
394 {
395 int err;
396
397 #ifdef SIGINT
398 signal(SIGINT,(void (*)(int))BIO_sock_cleanup);
399 #endif
400 wsa_init_done=1;
401 memset(&wsa_state,0,sizeof(wsa_state));
402 if (WSAStartup(0x0101,&wsa_state)!=0)
403 {
404 err=WSAGetLastError();
405 SYSerr(SYS_F_WSASTARTUP,err);
406 BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
407 return(-1);
408 }
409 }
410 #endif /* WINDOWS */
411 return(1);
412 }
413
414 void BIO_sock_cleanup()
415 {
416 #ifdef WINDOWS
417 if (wsa_init_done)
418 {
419 wsa_init_done=0;
420 WSACancelBlockingCall();
421 WSACleanup();
422 }
423 #endif
424 }
425
426 int BIO_socket_ioctl(fd,type,arg)
427 int fd;
428 long type;
429 unsigned long *arg;
430 {
431 int i;
432
433 i=ioctlsocket(fd,type,arg);
434 if (i < 0)
435 SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error());
436 return(i);
437 }
438
439 /* The reason I have implemented this instead of using sscanf is because
440 * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
441 static int get_ip(str,ip)
442 char *str;
443 unsigned char ip[4];
444 {
445 unsigned int tmp[4];
446 int num=0,c,ok=0;
447
448 tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
449
450 for (;;)
451 {
452 c= *(str++);
453 if ((c >= '0') && (c <= '9'))
454 {
455 ok=1;
456 tmp[num]=tmp[num]*10+c-'0';
457 if (tmp[num] > 255) return(-1);
458 }
459 else if (c == '.')
460 {
461 if (!ok) return(-1);
462 if (num == 3) break;
463 num++;
464 ok=0;
465 }
466 else if ((num == 3) && ok)
467 break;
468 else
469 return(0);
470 }
471 ip[0]=tmp[0];
472 ip[1]=tmp[1];
473 ip[2]=tmp[2];
474 ip[3]=tmp[3];
475 return(1);
476 }
477
478 int BIO_get_accept_socket(host,bind_mode)
479 char *host;
480 int bind_mode;
481 {
482 int ret=0;
483 struct sockaddr_in server,client;
484 int s= -1,cs;
485 unsigned char ip[4];
486 short port;
487 char *str,*h,*p,*e;
488 unsigned long l;
489 int err_num;
490
491 if (!BIO_sock_init()) return(INVALID_SOCKET);
492
493 if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
494
495 h=p=NULL;
496 h=str;
497 for (e=str; *e; e++)
498 {
499 if (*e == ':')
500 {
501 p= &(e[1]);
502 *e='\0';
503 }
504 else if (*e == '/')
505 {
506 *e='\0';
507 break;
508 }
509 }
510
511 if (p == NULL)
512 {
513 p=h;
514 h="*";
515 }
516
517 if (!BIO_get_port(p,&port)) return(INVALID_SOCKET);
518
519 memset((char *)&server,0,sizeof(server));
520 server.sin_family=AF_INET;
521 server.sin_port=htons((unsigned short)port);
522
523 if (strcmp(h,"*") == 0)
524 server.sin_addr.s_addr=INADDR_ANY;
525 else
526 {
527 if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET);
528 l=(unsigned long)
529 ((unsigned long)ip[0]<<24L)|
530 ((unsigned long)ip[1]<<16L)|
531 ((unsigned long)ip[2]<< 8L)|
532 ((unsigned long)ip[3]);
533 server.sin_addr.s_addr=htonl(l);
534 }
535
536 again:
537 s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
538 if (s == INVALID_SOCKET)
539 {
540 SYSerr(SYS_F_SOCKET,get_last_socket_error());
541 ERR_add_error_data(3,"port='",host,"'");
542 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
543 goto err;
544 }
545
546 #ifdef SO_REUSEADDR
547 if (bind_mode == BIO_BIND_REUSEADDR)
548 {
549 int i=1;
550
551 ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
552 bind_mode=BIO_BIND_NORMAL;
553 }
554 #endif
555 if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
556 {
557 #ifdef SO_REUSEADDR
558 err_num=get_last_socket_error();
559 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
560 (err_num == EADDRINUSE))
561 {
562 memcpy((char *)&client,(char *)&server,sizeof(server));
563 if (strcmp(h,"*") == 0)
564 client.sin_addr.s_addr=htonl(0x7F000001);
565 cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
566 if (cs != INVALID_SOCKET)
567 {
568 int ii;
569 ii=connect(cs,(struct sockaddr *)&client,
570 sizeof(client));
571 closesocket(cs);
572 if (ii == INVALID_SOCKET)
573 {
574 bind_mode=BIO_BIND_REUSEADDR;
575 closesocket(s);
576 goto again;
577 }
578 /* else error */
579 }
580 /* else error */
581 }
582 #endif
583 SYSerr(SYS_F_BIND,err_num);
584 ERR_add_error_data(3,"port='",host,"'");
585 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
586 goto err;
587 }
588 if (listen(s,MAX_LISTEN) == -1)
589 {
590 SYSerr(SYS_F_BIND,get_last_socket_error());
591 ERR_add_error_data(3,"port='",host,"'");
592 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
593 goto err;
594 }
595 ret=1;
596 err:
597 if (str != NULL) Free(str);
598 if ((ret == 0) && (s != INVALID_SOCKET))
599 {
600 closesocket(s);
601 s= INVALID_SOCKET;
602 }
603 return(s);
604 }
605
606 int BIO_accept(sock,addr)
607 int sock;
608 char **addr;
609 {
610 int ret=INVALID_SOCKET;
611 static struct sockaddr_in from;
612 unsigned long l;
613 short port;
614 int len;
615 char *p;
616
617 memset((char *)&from,0,sizeof(from));
618 len=sizeof(from);
619 ret=accept(sock,(struct sockaddr *)&from,&len);
620 if (ret == INVALID_SOCKET)
621 {
622 SYSerr(SYS_F_ACCEPT,get_last_socket_error());
623 BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
624 goto end;
625 }
626
627 if (addr == NULL) goto end;
628
629 l=ntohl(from.sin_addr.s_addr);
630 port=ntohs(from.sin_port);
631 if (*addr == NULL)
632 {
633 if ((p=Malloc(24)) == NULL)
634 {
635 BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
636 goto end;
637 }
638 *addr=p;
639 }
640 sprintf(*addr,"%d.%d.%d.%d:%d",
641 (unsigned char)(l>>24L)&0xff,
642 (unsigned char)(l>>16L)&0xff,
643 (unsigned char)(l>> 8L)&0xff,
644 (unsigned char)(l )&0xff,
645 port);
646 end:
647 return(ret);
648 }
649
650 int BIO_set_tcp_ndelay(s,on)
651 int s;
652 int on;
653 {
654 int ret=0;
655 #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
656 int opt;
657
658 #ifdef SOL_TCP
659 opt=SOL_TCP;
660 #else
661 #ifdef IPPROTO_TCP
662 opt=IPPROTO_TCP;
663 #endif
664 #endif
665
666 ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on));
667 #endif
668 return(ret == 0);
669 }
670 #endif
671
672 int BIO_socket_nbio(s,mode)
673 int s;
674 int mode;
675 {
676 int ret= -1;
677 unsigned long l;
678
679 l=mode;
680 #ifdef FIONBIO
681 ret=BIO_socket_ioctl(s,FIONBIO,&l);
682 #endif
683 return(ret == 0);
684 }