summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bio/b_sock.c
diff options
context:
space:
mode:
authorryker <>1998-10-05 20:13:14 +0000
committerryker <>1998-10-05 20:13:14 +0000
commitaeeae06a79815dc190061534d47236cec09f9e32 (patch)
tree851692b9c2f9c04f077666855641900f19fdb217 /src/lib/libcrypto/bio/b_sock.c
parenta4f79641824cbf9f60ca9d1168d1fcc46717a82a (diff)
downloadopenbsd-aeeae06a79815dc190061534d47236cec09f9e32.tar.gz
openbsd-aeeae06a79815dc190061534d47236cec09f9e32.tar.bz2
openbsd-aeeae06a79815dc190061534d47236cec09f9e32.zip
Import of SSLeay-0.9.0b with RSA and IDEA stubbed + OpenBSD build
functionality for shared libs. Note that routines such as sslv2_init and friends that use RSA will not work due to lack of RSA in this library. Needs documentation and help from ports for easy upgrade to full functionality where legally possible.
Diffstat (limited to 'src/lib/libcrypto/bio/b_sock.c')
-rw-r--r--src/lib/libcrypto/bio/b_sock.c628
1 files changed, 628 insertions, 0 deletions
diff --git a/src/lib/libcrypto/bio/b_sock.c b/src/lib/libcrypto/bio/b_sock.c
new file mode 100644
index 0000000000..a45909527c
--- /dev/null
+++ b/src/lib/libcrypto/bio/b_sock.c
@@ -0,0 +1,628 @@
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
85static int wsa_init_done=0;
86#endif
87
88static unsigned long BIO_ghbn_hits=0L;
89static unsigned long BIO_ghbn_miss=0L;
90
91#define GHBN_NUM 4
92static 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
100static int get_ip(char *str,unsigned char *ip);
101static void ghbn_free(struct hostent *a);
102static struct hostent *ghbn_dup(struct hostent *a);
103#else
104static int get_ip();
105static void ghbn_free();
106static struct hostent *ghbn_dup();
107#endif
108
109int BIO_get_host_ip(str,ip)
110char *str;
111unsigned 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
149int BIO_get_port(str,port_ptr)
150char *str;
151short *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
200int BIO_sock_error(sock)
201int 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
214long BIO_ghbn_ctrl(cmd,iarg,parg)
215int cmd;
216int iarg;
217char *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
255static struct hostent *ghbn_dup(a)
256struct hostent *a;
257 {
258 struct hostent *ret;
259 int i,j;
260
261 ret=(struct hostent *)malloc(sizeof(struct hostent));
262 if (ret == NULL) return(NULL);
263 memset(ret,0,sizeof(struct hostent));
264
265 for (i=0; a->h_aliases[i] != NULL; i++)
266 ;
267 i++;
268 ret->h_aliases=(char **)malloc(sizeof(char *)*i);
269 memset(ret->h_aliases,0,sizeof(char *)*i);
270 if (ret == NULL) goto err;
271
272 for (i=0; a->h_addr_list[i] != NULL; i++)
273 ;
274 i++;
275 ret->h_addr_list=(char **)malloc(sizeof(char *)*i);
276 memset(ret->h_addr_list,0,sizeof(char *)*i);
277 if (ret->h_addr_list == NULL) goto err;
278
279 j=strlen(a->h_name)+1;
280 if ((ret->h_name=malloc(j)) == NULL) goto err;
281 memcpy((char *)ret->h_name,a->h_name,j);
282 for (i=0; a->h_aliases[i] != NULL; i++)
283 {
284 j=strlen(a->h_aliases[i])+1;
285 if ((ret->h_aliases[i]=malloc(j)) == NULL) goto err;
286 memcpy(ret->h_aliases[i],a->h_aliases[i],j);
287 }
288 ret->h_length=a->h_length;
289 ret->h_addrtype=a->h_addrtype;
290 for (i=0; a->h_addr_list[i] != NULL; i++)
291 {
292 if ((ret->h_addr_list[i]=malloc(a->h_length)) == NULL)
293 goto err;
294 memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
295 }
296 return(ret);
297err:
298 if (ret != NULL)
299 ghbn_free(ret);
300 return(NULL);
301 }
302
303static void ghbn_free(a)
304struct hostent *a;
305 {
306 int i;
307
308 if (a->h_aliases != NULL)
309 {
310 for (i=0; a->h_aliases[i] != NULL; i++)
311 free(a->h_aliases[i]);
312 free(a->h_aliases);
313 }
314 if (a->h_addr_list != NULL)
315 {
316 for (i=0; a->h_addr_list[i] != NULL; i++)
317 free(a->h_addr_list[i]);
318 free(a->h_addr_list);
319 }
320 if (a->h_name != NULL) free((char *)a->h_name);
321 free(a);
322 }
323
324struct hostent *BIO_gethostbyname(name)
325char *name;
326 {
327 struct hostent *ret;
328 int i,lowi=0,j;
329 unsigned long low= (unsigned long)-1;
330
331/* return(gethostbyname(name)); */
332
333 CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
334 j=strlen(name);
335 if (j < 128)
336 {
337 for (i=0; i<GHBN_NUM; i++)
338 {
339 if (low > ghbn_cache[i].order)
340 {
341 low=ghbn_cache[i].order;
342 lowi=i;
343 }
344 if (ghbn_cache[i].order > 0)
345 {
346 if (strncmp(name,ghbn_cache[i].name,128) == 0)
347 break;
348 }
349 }
350 }
351 else
352 i=GHBN_NUM;
353
354 if (i == GHBN_NUM) /* no hit*/
355 {
356 BIO_ghbn_miss++;
357 ret=gethostbyname(name);
358
359 if (ret == NULL) return(NULL);
360 if (j > 128) return(ret); /* too big to cache */
361
362 /* else add to cache */
363 if (ghbn_cache[lowi].ent != NULL)
364 ghbn_free(ghbn_cache[lowi].ent);
365
366 strncpy(ghbn_cache[lowi].name,name,128);
367 ghbn_cache[lowi].ent=ghbn_dup(ret);
368 ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
369 }
370 else
371 {
372 BIO_ghbn_hits++;
373 ret= ghbn_cache[i].ent;
374 ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
375 }
376 CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
377 return(ret);
378 }
379
380int BIO_sock_init()
381 {
382#ifdef WINDOWS
383 static struct WSAData wsa_state;
384
385 if (!wsa_init_done)
386 {
387 int err;
388
389#ifdef SIGINT
390 signal(SIGINT,(void (*)(int))BIO_sock_cleanup);
391#endif
392 wsa_init_done=1;
393 memset(&wsa_state,0,sizeof(wsa_state));
394 if (WSAStartup(0x0101,&wsa_state)!=0)
395 {
396 err=WSAGetLastError();
397 SYSerr(SYS_F_WSASTARTUP,err);
398 BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
399 return(-1);
400 }
401 }
402#endif /* WINDOWS */
403 return(1);
404 }
405
406void BIO_sock_cleanup()
407 {
408#ifdef WINDOWS
409 if (wsa_init_done)
410 {
411 wsa_init_done=0;
412 WSACancelBlockingCall();
413 WSACleanup();
414 }
415#endif
416 }
417
418int BIO_socket_ioctl(fd,type,arg)
419int fd;
420long type;
421unsigned long *arg;
422 {
423 int i;
424
425 i=ioctlsocket(fd,type,arg);
426 if (i < 0)
427 SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error());
428 return(i);
429 }
430
431/* The reason I have implemented this instead of using sscanf is because
432 * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
433static int get_ip(str,ip)
434char *str;
435unsigned char ip[4];
436 {
437 unsigned int tmp[4];
438 int num=0,c,ok=0;
439
440 tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
441
442 for (;;)
443 {
444 c= *(str++);
445 if ((c >= '0') && (c <= '9'))
446 {
447 ok=1;
448 tmp[num]=tmp[num]*10+c-'0';
449 if (tmp[num] > 255) return(-1);
450 }
451 else if (c == '.')
452 {
453 if (!ok) return(-1);
454 if (num == 3) break;
455 num++;
456 ok=0;
457 }
458 else if ((num == 3) && ok)
459 break;
460 else
461 return(0);
462 }
463 ip[0]=tmp[0];
464 ip[1]=tmp[1];
465 ip[2]=tmp[2];
466 ip[3]=tmp[3];
467 return(1);
468 }
469
470int BIO_get_accept_socket(host)
471char *host;
472 {
473 int ret=0;
474 struct sockaddr_in server;
475 int s= -1;
476 unsigned char ip[4];
477 short port;
478 char *str,*h,*p,*e;
479 unsigned long l;
480
481 if (!BIO_sock_init()) return(INVALID_SOCKET);
482
483 if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
484
485 h=p=NULL;
486 h=str;
487 for (e=str; *e; e++)
488 {
489 if (*e == ':')
490 {
491 p= &(e[1]);
492 *e='\0';
493 }
494 else if (*e == '/')
495 {
496 *e='\0';
497 break;
498 }
499 }
500
501 if (p == NULL)
502 {
503 p=h;
504 h="*";
505 }
506
507 if (!BIO_get_port(p,&port)) return(INVALID_SOCKET);
508
509 memset((char *)&server,0,sizeof(server));
510 server.sin_family=AF_INET;
511 server.sin_port=htons((unsigned short)port);
512
513 if (strcmp(h,"*") == 0)
514 server.sin_addr.s_addr=INADDR_ANY;
515 else
516 {
517 if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET);
518 l=(unsigned long)
519 ((unsigned long)ip[0]<<24L)|
520 ((unsigned long)ip[0]<<16L)|
521 ((unsigned long)ip[0]<< 8L)|
522 ((unsigned long)ip[0]);
523 server.sin_addr.s_addr=htonl(l);
524 }
525
526 s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
527 if (s == INVALID_SOCKET)
528 {
529 SYSerr(SYS_F_SOCKET,get_last_socket_error());
530 ERR_add_error_data(3,"port='",host,"'");
531 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
532 goto err;
533 }
534 if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
535 {
536 SYSerr(SYS_F_BIND,get_last_socket_error());
537 ERR_add_error_data(3,"port='",host,"'");
538 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
539 goto err;
540 }
541 if (listen(s,MAX_LISTEN) == -1)
542 {
543 SYSerr(SYS_F_BIND,get_last_socket_error());
544 ERR_add_error_data(3,"port='",host,"'");
545 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
546 goto err;
547 }
548 ret=1;
549err:
550 if (str != NULL) Free(str);
551 if ((ret == 0) && (s != INVALID_SOCKET))
552 {
553#ifdef WINDOWS
554 closesocket(s);
555#else
556 close(s);
557#endif
558 s= INVALID_SOCKET;
559 }
560 return(s);
561 }
562
563int BIO_accept(sock,addr)
564int sock;
565char **addr;
566 {
567 int ret=INVALID_SOCKET;
568 static struct sockaddr_in from;
569 unsigned long l;
570 short port;
571 int len;
572 char *p;
573
574 memset((char *)&from,0,sizeof(from));
575 len=sizeof(from);
576 ret=accept(sock,(struct sockaddr *)&from,&len);
577 if (ret == INVALID_SOCKET)
578 {
579 SYSerr(SYS_F_ACCEPT,get_last_socket_error());
580 BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
581 goto end;
582 }
583
584 if (addr == NULL) goto end;
585
586 l=ntohl(from.sin_addr.s_addr);
587 port=ntohs(from.sin_port);
588 if (*addr == NULL)
589 {
590 if ((p=Malloc(24)) == NULL)
591 {
592 BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
593 goto end;
594 }
595 *addr=p;
596 }
597 sprintf(*addr,"%d.%d.%d.%d:%d",
598 (unsigned char)(l>>24L)&0xff,
599 (unsigned char)(l>>16L)&0xff,
600 (unsigned char)(l>> 8L)&0xff,
601 (unsigned char)(l )&0xff,
602 port);
603end:
604 return(ret);
605 }
606
607int BIO_set_tcp_ndelay(s,on)
608int s;
609int on;
610 {
611 int ret=0;
612#if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
613 int opt;
614
615#ifdef SOL_TCP
616 opt=SOL_TCP;
617#else
618#ifdef IPPROTO_TCP
619 opt=IPPROTO_TCP;
620#endif
621#endif
622
623 ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on));
624#endif
625 return(ret == 0);
626 }
627#endif
628