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 <openssl/bio.h> 67 68 #ifdef WIN16 69 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ 70 #else 71 #define SOCKET_PROTOCOL IPPROTO_TCP 72 #endif 73 74 #ifdef SO_MAXCONN 75 #define MAX_LISTEN SOMAXCONN 76 #elif defined(SO_MAXCONN) 77 #define MAX_LISTEN SO_MAXCONN 78 #else 79 #define MAX_LISTEN 32 80 #endif 81 82 #ifdef WINDOWS 83 static int wsa_init_done=0; 84 #endif 85 86 static unsigned long BIO_ghbn_hits=0L; 87 static unsigned long BIO_ghbn_miss=0L; 88 89 #define GHBN_NUM 4 90 static struct ghbn_cache_st 91 { 92 char name[129]; 93 struct hostent *ent; 94 unsigned long order; 95 } ghbn_cache[GHBN_NUM]; 96 97 static int get_ip(const char *str,unsigned char *ip); 98 static void ghbn_free(struct hostent *a); 99 static struct hostent *ghbn_dup(struct hostent *a); 100 int BIO_get_host_ip(const char *str, unsigned char *ip) 101 { 102 int i; 103 int err = 1; 104 int locked = 0; 105 struct hostent *he; 106 107 i=get_ip(str,ip); 108 if (i > 0) return(1); 109 if (i < 0) 110 { 111 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); 112 goto err; 113 } 114 115 /* do a gethostbyname */ 116 if (!BIO_sock_init()) 117 return(0); /* don't generate another error code here */ 118 119 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); 120 locked = 1; 121 he=BIO_gethostbyname(str); 122 if (he == NULL) 123 { 124 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); 125 goto err; 126 } 127 128 /* cast to short because of win16 winsock definition */ 129 if ((short)he->h_addrtype != AF_INET) 130 { 131 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); 132 goto err; 133 } 134 for (i=0; i<4; i++) 135 ip[i]=he->h_addr_list[0][i]; 136 err = 0; 137 138 err: 139 if (locked) 140 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); 141 if (err) 142 { 143 ERR_add_error_data(2,"host=",str); 144 return 0; 145 } 146 else 147 return 1; 148 } 149 150 int BIO_get_port(const char *str, unsigned short *port_ptr) 151 { 152 int i; 153 struct servent *s; 154 155 if (str == NULL) 156 { 157 BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED); 158 return(0); 159 } 160 i=atoi(str); 161 if (i != 0) 162 *port_ptr=(unsigned short)i; 163 else 164 { 165 CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); 166 s=getservbyname(str,"tcp"); 167 if(s != NULL) 168 *port_ptr=ntohs((unsigned short)s->s_port); 169 CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); 170 if(s == NULL) 171 { 172 if (strcmp(str,"http") == 0) 173 *port_ptr=80; 174 else if (strcmp(str,"telnet") == 0) 175 *port_ptr=23; 176 else if (strcmp(str,"socks") == 0) 177 *port_ptr=1080; 178 else if (strcmp(str,"https") == 0) 179 *port_ptr=443; 180 else if (strcmp(str,"ssl") == 0) 181 *port_ptr=443; 182 else if (strcmp(str,"ftp") == 0) 183 *port_ptr=21; 184 else if (strcmp(str,"gopher") == 0) 185 *port_ptr=70; 186 #if 0 187 else if (strcmp(str,"wais") == 0) 188 *port_ptr=21; 189 #endif 190 else 191 { 192 SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error()); 193 ERR_add_error_data(3,"service='",str,"'"); 194 return(0); 195 } 196 } 197 } 198 return(1); 199 } 200 201 int BIO_sock_error(int sock) 202 { 203 int j,i; 204 int size; 205 206 size=sizeof(int); 207 /* Note: under Windows the third parameter is of type (char *) 208 * whereas under other systems it is (void *) if you don't have 209 * a cast it will choke the compiler: if you do have a cast then 210 * you can either go for (char *) or (void *). 211 */ 212 i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size); 213 if (i < 0) 214 return(1); 215 else 216 return(j); 217 } 218 219 long BIO_ghbn_ctrl(int cmd, int iarg, char *parg) 220 { 221 int i; 222 char **p; 223 224 switch (cmd) 225 { 226 case BIO_GHBN_CTRL_HITS: 227 return(BIO_ghbn_hits); 228 /* break; */ 229 case BIO_GHBN_CTRL_MISSES: 230 return(BIO_ghbn_miss); 231 /* break; */ 232 case BIO_GHBN_CTRL_CACHE_SIZE: 233 return(GHBN_NUM); 234 /* break; */ 235 case BIO_GHBN_CTRL_GET_ENTRY: 236 if ((iarg >= 0) && (iarg <GHBN_NUM) && 237 (ghbn_cache[iarg].order > 0)) 238 { 239 p=(char **)parg; 240 if (p == NULL) return(0); 241 *p=ghbn_cache[iarg].name; 242 ghbn_cache[iarg].name[128]='\0'; 243 return(1); 244 } 245 return(0); 246 /* break; */ 247 case BIO_GHBN_CTRL_FLUSH: 248 for (i=0; i<GHBN_NUM; i++) 249 ghbn_cache[i].order=0; 250 break; 251 default: 252 return(0); 253 } 254 return(1); 255 } 256 257 static struct hostent *ghbn_dup(struct hostent *a) 258 { 259 struct hostent *ret; 260 int i,j; 261 262 MemCheck_off(); 263 ret=(struct hostent *)Malloc(sizeof(struct hostent)); 264 if (ret == NULL) return(NULL); 265 memset(ret,0,sizeof(struct hostent)); 266 267 for (i=0; a->h_aliases[i] != NULL; i++) 268 ; 269 i++; 270 ret->h_aliases = (char **)Malloc(i*sizeof(char *)); 271 if (ret->h_aliases == NULL) 272 goto err; 273 memset(ret->h_aliases, 0, i*sizeof(char *)); 274 275 for (i=0; a->h_addr_list[i] != NULL; i++) 276 ; 277 i++; 278 ret->h_addr_list=(char **)Malloc(i*sizeof(char *)); 279 if (ret->h_addr_list == NULL) 280 goto err; 281 memset(ret->h_addr_list, 0, i*sizeof(char *)); 282 283 j=strlen(a->h_name)+1; 284 if ((ret->h_name=Malloc(j)) == NULL) goto err; 285 memcpy((char *)ret->h_name,a->h_name,j+1); 286 for (i=0; a->h_aliases[i] != NULL; i++) 287 { 288 j=strlen(a->h_aliases[i])+1; 289 if ((ret->h_aliases[i]=Malloc(j)) == NULL) goto err; 290 memcpy(ret->h_aliases[i],a->h_aliases[i],j+1); 291 } 292 ret->h_length=a->h_length; 293 ret->h_addrtype=a->h_addrtype; 294 for (i=0; a->h_addr_list[i] != NULL; i++) 295 { 296 if ((ret->h_addr_list[i]=Malloc(a->h_length)) == NULL) 297 goto err; 298 memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length); 299 } 300 if (0) 301 { 302 err: 303 if (ret != NULL) 304 ghbn_free(ret); 305 ret=NULL; 306 } 307 MemCheck_on(); 308 return(ret); 309 } 310 311 static void ghbn_free(struct hostent *a) 312 { 313 int i; 314 315 if(a == NULL) 316 return; 317 318 if (a->h_aliases != NULL) 319 { 320 for (i=0; a->h_aliases[i] != NULL; i++) 321 Free(a->h_aliases[i]); 322 Free(a->h_aliases); 323 } 324 if (a->h_addr_list != NULL) 325 { 326 for (i=0; a->h_addr_list[i] != NULL; i++) 327 Free(a->h_addr_list[i]); 328 Free(a->h_addr_list); 329 } 330 if (a->h_name != NULL) Free((char *)a->h_name); 331 Free(a); 332 } 333 334 struct hostent *BIO_gethostbyname(const char *name) 335 { 336 struct hostent *ret; 337 int i,lowi=0,j; 338 unsigned long low= (unsigned long)-1; 339 340 /* return(gethostbyname(name)); */ 341 342 #if 0 /* It doesn't make sense to use locking here: The function interface 343 * is not thread-safe, because threads can never be sure when 344 * some other thread destroys the data they were given a pointer to. 345 */ 346 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); 347 #endif 348 j=strlen(name); 349 if (j < 128) 350 { 351 for (i=0; i<GHBN_NUM; i++) 352 { 353 if (low > ghbn_cache[i].order) 354 { 355 low=ghbn_cache[i].order; 356 lowi=i; 357 } 358 if (ghbn_cache[i].order > 0) 359 { 360 if (strncmp(name,ghbn_cache[i].name,128) == 0) 361 break; 362 } 363 } 364 } 365 else 366 i=GHBN_NUM; 367 368 if (i == GHBN_NUM) /* no hit*/ 369 { 370 BIO_ghbn_miss++; 371 ret=gethostbyname(name); 372 373 if (ret == NULL) 374 goto end; 375 if (j > 128) /* too big to cache */ 376 { 377 #if 0 /* If we were trying to make this function thread-safe (which 378 * is bound to fail), we'd have to give up in this case 379 * (or allocate more memory). */ 380 ret = NULL; 381 #endif 382 goto end; 383 } 384 385 /* else add to cache */ 386 if (ghbn_cache[lowi].ent != NULL) 387 ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ 388 ghbn_cache[lowi].name[0] = '\0'; 389 390 if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL) 391 { 392 BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE); 393 goto end; 394 } 395 strncpy(ghbn_cache[lowi].name,name,128); 396 ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits; 397 } 398 else 399 { 400 BIO_ghbn_hits++; 401 ret= ghbn_cache[i].ent; 402 ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits; 403 } 404 end: 405 #if 0 406 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); 407 #endif 408 return(ret); 409 } 410 411 int BIO_sock_init(void) 412 { 413 #ifdef WINDOWS 414 static struct WSAData wsa_state; 415 416 if (!wsa_init_done) 417 { 418 int err; 419 420 #ifdef SIGINT 421 signal(SIGINT,(void (*)(int))BIO_sock_cleanup); 422 #endif 423 wsa_init_done=1; 424 memset(&wsa_state,0,sizeof(wsa_state)); 425 if (WSAStartup(0x0101,&wsa_state)!=0) 426 { 427 err=WSAGetLastError(); 428 SYSerr(SYS_F_WSASTARTUP,err); 429 BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP); 430 return(-1); 431 } 432 } 433 #endif /* WINDOWS */ 434 return(1); 435 } 436 437 void BIO_sock_cleanup(void) 438 { 439 #ifdef WINDOWS 440 if (wsa_init_done) 441 { 442 wsa_init_done=0; 443 WSACancelBlockingCall(); 444 WSACleanup(); 445 } 446 #endif 447 } 448 449 #if !defined(VMS) || __VMS_VER >= 70000000 450 451 int BIO_socket_ioctl(int fd, long type, unsigned long *arg) 452 { 453 int i; 454 455 i=ioctlsocket(fd,type,arg); 456 if (i < 0) 457 SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); 458 return(i); 459 } 460 #endif /* __VMS_VER */ 461 462 /* The reason I have implemented this instead of using sscanf is because 463 * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ 464 static int get_ip(const char *str, unsigned char ip[4]) 465 { 466 unsigned int tmp[4]; 467 int num=0,c,ok=0; 468 469 tmp[0]=tmp[1]=tmp[2]=tmp[3]=0; 470 471 for (;;) 472 { 473 c= *(str++); 474 if ((c >= '0') && (c <= '9')) 475 { 476 ok=1; 477 tmp[num]=tmp[num]*10+c-'0'; 478 if (tmp[num] > 255) return(-1); 479 } 480 else if (c == '.') 481 { 482 if (!ok) return(-1); 483 if (num == 3) break; 484 num++; 485 ok=0; 486 } 487 else if ((num == 3) && ok) 488 break; 489 else 490 return(0); 491 } 492 ip[0]=tmp[0]; 493 ip[1]=tmp[1]; 494 ip[2]=tmp[2]; 495 ip[3]=tmp[3]; 496 return(1); 497 } 498 499 int BIO_get_accept_socket(char *host, int bind_mode) 500 { 501 int ret=0; 502 struct sockaddr_in server,client; 503 int s= -1,cs; 504 unsigned char ip[4]; 505 unsigned short port; 506 char *str,*e; 507 const char *h,*p; 508 unsigned long l; 509 int err_num; 510 511 if (!BIO_sock_init()) return(INVALID_SOCKET); 512 513 if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); 514 515 h=p=NULL; 516 h=str; 517 for (e=str; *e; e++) 518 { 519 if (*e == ':') 520 { 521 p= &(e[1]); 522 *e='\0'; 523 } 524 else if (*e == '/') 525 { 526 *e='\0'; 527 break; 528 } 529 } 530 531 if (p == NULL) 532 { 533 p=h; 534 h="*"; 535 } 536 537 if (!BIO_get_port(p,&port)) return(INVALID_SOCKET); 538 539 memset((char *)&server,0,sizeof(server)); 540 server.sin_family=AF_INET; 541 server.sin_port=htons(port); 542 543 if (strcmp(h,"*") == 0) 544 server.sin_addr.s_addr=INADDR_ANY; 545 else 546 { 547 if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET); 548 l=(unsigned long) 549 ((unsigned long)ip[0]<<24L)| 550 ((unsigned long)ip[1]<<16L)| 551 ((unsigned long)ip[2]<< 8L)| 552 ((unsigned long)ip[3]); 553 server.sin_addr.s_addr=htonl(l); 554 } 555 556 again: 557 s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 558 if (s == INVALID_SOCKET) 559 { 560 SYSerr(SYS_F_SOCKET,get_last_socket_error()); 561 ERR_add_error_data(3,"port='",host,"'"); 562 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET); 563 goto err; 564 } 565 566 #ifdef SO_REUSEADDR 567 if (bind_mode == BIO_BIND_REUSEADDR) 568 { 569 int i=1; 570 571 ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i)); 572 bind_mode=BIO_BIND_NORMAL; 573 } 574 #endif 575 if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) 576 { 577 #ifdef SO_REUSEADDR 578 err_num=get_last_socket_error(); 579 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && 580 (err_num == EADDRINUSE)) 581 { 582 memcpy((char *)&client,(char *)&server,sizeof(server)); 583 if (strcmp(h,"*") == 0) 584 client.sin_addr.s_addr=htonl(0x7F000001); 585 cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 586 if (cs != INVALID_SOCKET) 587 { 588 int ii; 589 ii=connect(cs,(struct sockaddr *)&client, 590 sizeof(client)); 591 closesocket(cs); 592 if (ii == INVALID_SOCKET) 593 { 594 bind_mode=BIO_BIND_REUSEADDR; 595 closesocket(s); 596 goto again; 597 } 598 /* else error */ 599 } 600 /* else error */ 601 } 602 #endif 603 SYSerr(SYS_F_BIND,err_num); 604 ERR_add_error_data(3,"port='",host,"'"); 605 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET); 606 goto err; 607 } 608 if (listen(s,MAX_LISTEN) == -1) 609 { 610 SYSerr(SYS_F_BIND,get_last_socket_error()); 611 ERR_add_error_data(3,"port='",host,"'"); 612 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET); 613 goto err; 614 } 615 ret=1; 616 err: 617 if (str != NULL) Free(str); 618 if ((ret == 0) && (s != INVALID_SOCKET)) 619 { 620 closesocket(s); 621 s= INVALID_SOCKET; 622 } 623 return(s); 624 } 625 626 int BIO_accept(int sock, char **addr) 627 { 628 int ret=INVALID_SOCKET; 629 static struct sockaddr_in from; 630 unsigned long l; 631 unsigned short port; 632 int len; 633 char *p; 634 635 memset((char *)&from,0,sizeof(from)); 636 len=sizeof(from); 637 /* Note: under VMS with SOCKETSHR the fourth parameter is currently 638 * of type (int *) whereas under other systems it is (void *) if 639 * you don't have a cast it will choke the compiler: if you do 640 * have a cast then you can either go for (int *) or (void *). 641 */ 642 ret=accept(sock,(struct sockaddr *)&from,(void *)&len); 643 if (ret == INVALID_SOCKET) 644 { 645 SYSerr(SYS_F_ACCEPT,get_last_socket_error()); 646 BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR); 647 goto end; 648 } 649 650 if (addr == NULL) goto end; 651 652 l=ntohl(from.sin_addr.s_addr); 653 port=ntohs(from.sin_port); 654 if (*addr == NULL) 655 { 656 if ((p=Malloc(24)) == NULL) 657 { 658 BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); 659 goto end; 660 } 661 *addr=p; 662 } 663 sprintf(*addr,"%d.%d.%d.%d:%d", 664 (unsigned char)(l>>24L)&0xff, 665 (unsigned char)(l>>16L)&0xff, 666 (unsigned char)(l>> 8L)&0xff, 667 (unsigned char)(l )&0xff, 668 port); 669 end: 670 return(ret); 671 } 672 673 int BIO_set_tcp_ndelay(int s, int on) 674 { 675 int ret=0; 676 #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) 677 int opt; 678 679 #ifdef SOL_TCP 680 opt=SOL_TCP; 681 #else 682 #ifdef IPPROTO_TCP 683 opt=IPPROTO_TCP; 684 #endif 685 #endif 686 687 ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on)); 688 #endif 689 return(ret == 0); 690 } 691 #endif 692 693 int BIO_socket_nbio(int s, int mode) 694 { 695 int ret= -1; 696 unsigned long l; 697 698 l=mode; 699 #ifdef FIONBIO 700 ret=BIO_socket_ioctl(s,FIONBIO,&l); 701 #endif 702 return(ret == 0); 703 } 704