summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bio/bss_conn.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/bss_conn.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/bss_conn.c')
-rw-r--r--src/lib/libcrypto/bio/bss_conn.c648
1 files changed, 648 insertions, 0 deletions
diff --git a/src/lib/libcrypto/bio/bss_conn.c b/src/lib/libcrypto/bio/bss_conn.c
new file mode 100644
index 0000000000..6e547bf866
--- /dev/null
+++ b/src/lib/libcrypto/bio/bss_conn.c
@@ -0,0 +1,648 @@
1/* crypto/bio/bss_conn.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 <errno.h>
63#define USE_SOCKETS
64#include "cryptlib.h"
65#include "bio.h"
66
67/* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */
68
69#ifdef WIN16
70#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
71#else
72#define SOCKET_PROTOCOL IPPROTO_TCP
73#endif
74
75typedef struct bio_connect_st
76 {
77 int state;
78
79 char *param_hostname;
80 char *param_port;
81 int nbio;
82
83 unsigned char ip[4];
84 short port;
85
86 struct sockaddr_in them;
87
88 /* int socket; this will be kept in bio->num so that it is
89 * compatable with the bss_sock bio */
90 int error;
91
92 /* called when the connection is initially made
93 * callback(BIO,state,ret); The callback should return
94 * 'ret'. state is for compatablity with the ssl info_callback */
95 int (*info_callback)();
96 } BIO_CONNECT;
97
98#ifndef NOPROTO
99static int conn_write(BIO *h,char *buf,int num);
100static int conn_read(BIO *h,char *buf,int size);
101static int conn_puts(BIO *h,char *str);
102static long conn_ctrl(BIO *h,int cmd,long arg1,char *arg2);
103static int conn_new(BIO *h);
104static int conn_free(BIO *data);
105#else
106static int conn_write();
107static int conn_read();
108static int conn_puts();
109static long conn_ctrl();
110static int conn_new();
111static int conn_free();
112#endif
113
114#ifndef NOPROTO
115
116static int conn_state(BIO *b, BIO_CONNECT *c);
117static void conn_close_socket(BIO *data);
118BIO_CONNECT *BIO_CONNECT_new(void );
119void BIO_CONNECT_free(BIO_CONNECT *a);
120
121#else
122
123static int conn_state();
124static void conn_close_socket();
125BIO_CONNECT *BIO_CONNECT_new();
126void BIO_CONNECT_free();
127
128#endif
129
130static BIO_METHOD methods_connectp=
131 {
132 BIO_TYPE_CONNECT,
133 "socket connect",
134 conn_write,
135 conn_read,
136 conn_puts,
137 NULL, /* connect_gets, */
138 conn_ctrl,
139 conn_new,
140 conn_free,
141 };
142
143static int conn_state(b,c)
144BIO *b;
145BIO_CONNECT *c;
146 {
147 int ret= -1,i;
148 unsigned long l;
149 char *p,*q;
150 int (*cb)()=NULL;
151
152 if (c->info_callback != NULL)
153 cb=c->info_callback;
154
155 for (;;)
156 {
157 switch (c->state)
158 {
159 case BIO_CONN_S_BEFORE:
160 p=c->param_hostname;
161 if (p == NULL)
162 {
163 BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTHNAME_SPECIFIED);
164 goto exit_loop;
165 }
166 for ( ; *p != '\0'; p++)
167 {
168 if ((*p == ':') || (*p == '/')) break;
169 }
170
171 i= *p;
172 if ((i == ':') || (i == '/'))
173 {
174
175 *(p++)='\0';
176 if (i == ':')
177 {
178 for (q=p; *q; q++)
179 if (*q == '/')
180 {
181 *q='\0';
182 break;
183 }
184 if (c->param_port != NULL)
185 Free(c->param_port);
186 c->param_port=BUF_strdup(p);
187 }
188 }
189
190 if (p == NULL)
191 {
192 BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED);
193 ERR_add_error_data(2,"host=",c->param_hostname);
194 goto exit_loop;
195 }
196 c->state=BIO_CONN_S_GET_IP;
197 break;
198
199 case BIO_CONN_S_GET_IP:
200 if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0)
201 goto exit_loop;
202 c->state=BIO_CONN_S_GET_PORT;
203 break;
204
205 case BIO_CONN_S_GET_PORT:
206 if (BIO_get_port(c->param_port,&c->port) <= 0)
207 goto exit_loop;
208 c->state=BIO_CONN_S_CREATE_SOCKET;
209 break;
210
211 case BIO_CONN_S_CREATE_SOCKET:
212 /* now setup address */
213 memset((char *)&c->them,0,sizeof(c->them));
214 c->them.sin_family=AF_INET;
215 c->them.sin_port=htons((unsigned short)c->port);
216 l=(unsigned long)
217 ((unsigned long)c->ip[0]<<24L)|
218 ((unsigned long)c->ip[1]<<16L)|
219 ((unsigned long)c->ip[2]<< 8L)|
220 ((unsigned long)c->ip[3]);
221 c->them.sin_addr.s_addr=htonl(l);
222 c->state=BIO_CONN_S_CREATE_SOCKET;
223
224 ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
225 if (ret == INVALID_SOCKET)
226 {
227 SYSerr(SYS_F_SOCKET,get_last_socket_error());
228 ERR_add_error_data(4,"host=",c->param_hostname,
229 ":",c->param_port);
230 BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET);
231 goto exit_loop;
232 }
233 b->num=ret;
234 c->state=BIO_CONN_S_NBIO;
235 break;
236
237 case BIO_CONN_S_NBIO:
238#ifdef FIONBIO
239 if (c->nbio)
240 {
241 l=1;
242 ret=BIO_socket_ioctl(b->num,FIONBIO,&l);
243 if (ret < 0)
244 {
245 BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO);
246 ERR_add_error_data(4,"host=",
247 c->param_hostname,
248 ":",c->param_port);
249 goto exit_loop;
250 }
251 }
252#endif
253 c->state=BIO_CONN_S_CONNECT;
254
255#ifdef SO_KEEPALIVE
256 i=1;
257 i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
258 if (i < 0)
259 {
260 SYSerr(SYS_F_SOCKET,get_last_socket_error());
261 ERR_add_error_data(4,"host=",c->param_hostname,
262 ":",c->param_port);
263 BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE);
264 goto exit_loop;
265 }
266#endif
267 break;
268
269 case BIO_CONN_S_CONNECT:
270 BIO_clear_retry_flags(b);
271 ret=connect(b->num,
272 (struct sockaddr *)&c->them,
273 sizeof(c->them));
274 b->retry_reason=0;
275 if (ret < 0)
276 {
277 if (BIO_sock_should_retry(ret))
278 {
279 BIO_set_retry_special(b);
280 c->state=BIO_CONN_S_BLOCKED_CONNECT;
281 b->retry_reason=BIO_RR_CONNECT;
282 }
283 else
284 {
285 SYSerr(SYS_F_CONNECT,get_last_socket_error());
286 ERR_add_error_data(4,"host=",
287 c->param_hostname,
288 ":",c->param_port);
289 BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR);
290 }
291 goto exit_loop;
292 }
293 else
294 c->state=BIO_CONN_S_OK;
295 break;
296
297 case BIO_CONN_S_BLOCKED_CONNECT:
298 i=BIO_sock_error(b->num);
299 if (i)
300 {
301 BIO_clear_retry_flags(b);
302 SYSerr(SYS_F_CONNECT,i);
303 ERR_add_error_data(4,"host=",
304 c->param_hostname,
305 ":",c->param_port);
306 BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR);
307 ret=0;
308 goto exit_loop;
309 }
310 else
311 c->state=BIO_CONN_S_OK;
312 break;
313
314 case BIO_CONN_S_OK:
315 ret=1;
316 goto exit_loop;
317 default:
318 abort();
319 goto exit_loop;
320 }
321
322 if (cb != NULL)
323 {
324 if (!(ret=cb((BIO *)b,c->state,ret)))
325 goto end;
326 }
327 }
328
329 if (1)
330 {
331exit_loop:
332 if (cb != NULL)
333 ret=cb((BIO *)b,c->state,ret);
334 }
335end:
336 return(ret);
337 }
338
339BIO_CONNECT *BIO_CONNECT_new()
340 {
341 BIO_CONNECT *ret;
342
343 if ((ret=(BIO_CONNECT *)Malloc(sizeof(BIO_CONNECT))) == NULL)
344 return(NULL);
345 ret->state=BIO_CONN_S_BEFORE;
346 ret->param_hostname=NULL;
347 ret->param_port=NULL;
348 ret->info_callback=NULL;
349 ret->nbio=0;
350 ret->ip[0]=0;
351 ret->ip[1]=0;
352 ret->ip[2]=0;
353 ret->ip[3]=0;
354 ret->port=0;
355 memset((char *)&ret->them,0,sizeof(ret->them));
356 ret->error=0;
357 return(ret);
358 }
359
360void BIO_CONNECT_free(a)
361BIO_CONNECT *a;
362 {
363 if (a->param_hostname != NULL)
364 Free(a->param_hostname);
365 if (a->param_port != NULL)
366 Free(a->param_port);
367 Free(a);
368 }
369
370BIO_METHOD *BIO_s_connect()
371 {
372 return(&methods_connectp);
373 }
374
375static int conn_new(bi)
376BIO *bi;
377 {
378 bi->init=0;
379 bi->num=INVALID_SOCKET;
380 bi->flags=0;
381 if ((bi->ptr=(char *)BIO_CONNECT_new()) == NULL)
382 return(0);
383 else
384 return(1);
385 }
386
387static void conn_close_socket(bio)
388BIO *bio;
389 {
390 BIO_CONNECT *c;
391
392 c=(BIO_CONNECT *)bio->ptr;
393 if (bio->num != INVALID_SOCKET)
394 {
395 /* Only do a shutdown if things were established */
396 if (c->state == BIO_CONN_S_OK)
397 shutdown(bio->num,2);
398# ifdef WINDOWS
399 closesocket(bio->num);
400# else
401 close(bio->num);
402# endif
403 bio->num=INVALID_SOCKET;
404 }
405 }
406
407static int conn_free(a)
408BIO *a;
409 {
410 BIO_CONNECT *data;
411
412 if (a == NULL) return(0);
413 data=(BIO_CONNECT *)a->ptr;
414
415 if (a->shutdown)
416 {
417 conn_close_socket(a);
418 BIO_CONNECT_free(data);
419 a->ptr=NULL;
420 a->flags=0;
421 a->init=0;
422 }
423 return(1);
424 }
425
426static int conn_read(b,out,outl)
427BIO *b;
428char *out;
429int outl;
430 {
431 int ret=0;
432 BIO_CONNECT *data;
433
434 data=(BIO_CONNECT *)b->ptr;
435 if (data->state != BIO_CONN_S_OK)
436 {
437 ret=conn_state(b,data);
438 if (ret <= 0)
439 return(ret);
440 }
441
442 if (out != NULL)
443 {
444 clear_socket_error();
445#if defined(WINDOWS)
446 ret=recv(b->num,out,outl,0);
447#else
448 ret=read(b->num,out,outl);
449#endif
450 BIO_clear_retry_flags(b);
451 if (ret <= 0)
452 {
453 if (BIO_sock_should_retry(ret))
454 BIO_set_retry_read(b);
455 }
456 }
457 return(ret);
458 }
459
460static int conn_write(b,in,inl)
461BIO *b;
462char *in;
463int inl;
464 {
465 int ret;
466 BIO_CONNECT *data;
467
468 data=(BIO_CONNECT *)b->ptr;
469 if (data->state != BIO_CONN_S_OK)
470 {
471 ret=conn_state(b,data);
472 if (ret <= 0) return(ret);
473 }
474
475 clear_socket_error();
476#if defined(WINDOWS)
477 ret=send(b->num,in,inl,0);
478#else
479 ret=write(b->num,in,inl);
480#endif
481 BIO_clear_retry_flags(b);
482 if (ret <= 0)
483 {
484 if (BIO_sock_should_retry(ret))
485 BIO_set_retry_write(b);
486 }
487 return(ret);
488 }
489
490static long conn_ctrl(b,cmd,num,ptr)
491BIO *b;
492int cmd;
493long num;
494char *ptr;
495 {
496 BIO *dbio;
497 int *ip;
498 char **pptr;
499 long ret=1;
500 BIO_CONNECT *data;
501
502 data=(BIO_CONNECT *)b->ptr;
503
504 switch (cmd)
505 {
506 case BIO_CTRL_RESET:
507 ret=0;
508 data->state=BIO_CONN_S_BEFORE;
509 conn_close_socket(b);
510 b->flags=0;
511 break;
512 case BIO_C_DO_STATE_MACHINE:
513 /* use this one to start the connection */
514 if (!data->state != BIO_CONN_S_OK)
515 ret=(long)conn_state(b,data);
516 else
517 ret=1;
518 break;
519 case BIO_C_GET_CONNECT:
520 if (ptr != NULL)
521 {
522 pptr=(char **)ptr;
523 if (num == 0)
524 {
525 *pptr=data->param_hostname;
526
527 }
528 else if (num == 1)
529 {
530 *pptr=data->param_port;
531 }
532 else if (num == 2)
533 {
534 *pptr= (char *)&(data->ip[0]);
535 }
536 else if (num == 3)
537 {
538 *((int *)ptr)=data->port;
539 }
540 if ((!b->init) || (ptr == NULL))
541 *pptr="not initalised";
542 ret=1;
543 }
544 break;
545 case BIO_C_SET_CONNECT:
546 if (ptr != NULL)
547 {
548 b->init=1;
549 if (num == 0)
550 {
551 if (data->param_hostname != NULL)
552 Free(data->param_hostname);
553 data->param_hostname=BUF_strdup(ptr);
554 }
555 else if (num == 1)
556 {
557 if (data->param_port != NULL)
558 Free(data->param_port);
559 data->param_port=BUF_strdup(ptr);
560 }
561 else if (num == 2)
562 memcpy(data->ip,ptr,4);
563 else if (num == 3)
564 data->port= *(int *)ptr;
565 }
566 break;
567 case BIO_C_SET_NBIO:
568 data->nbio=(int)num;
569 break;
570 case BIO_C_GET_FD:
571 if (b->init)
572 {
573 ip=(int *)ptr;
574 if (ip != NULL)
575 *ip=b->num;
576 ret=b->num;
577 }
578 else
579 ret= -1;
580 break;
581 case BIO_CTRL_GET_CLOSE:
582 ret=b->shutdown;
583 break;
584 case BIO_CTRL_SET_CLOSE:
585 b->shutdown=(int)num;
586 break;
587 case BIO_CTRL_PENDING:
588 case BIO_CTRL_WPENDING:
589 ret=0;
590 break;
591 case BIO_CTRL_FLUSH:
592 break;
593 case BIO_CTRL_DUP:
594 dbio=(BIO *)ptr;
595 if (data->param_port)
596 BIO_set_conn_port(dbio,data->param_port);
597 if (data->param_hostname)
598 BIO_set_conn_hostname(dbio,data->param_hostname);
599 BIO_set_nbio(dbio,data->nbio);
600 BIO_set_info_callback(dbio,data->info_callback);
601 break;
602 case BIO_CTRL_SET_CALLBACK:
603 data->info_callback=(int (*)())ptr;
604 break;
605 case BIO_CTRL_GET_CALLBACK:
606 {
607 int (**fptr)();
608
609 fptr=(int (**)())ptr;
610 *fptr=data->info_callback;
611 }
612 break;
613 default:
614 ret=0;
615 break;
616 }
617 return(ret);
618 }
619
620static int conn_puts(bp,str)
621BIO *bp;
622char *str;
623 {
624 int n,ret;
625
626 n=strlen(str);
627 ret=conn_write(bp,str,n);
628 return(ret);
629 }
630
631BIO *BIO_new_connect(str)
632char *str;
633 {
634 BIO *ret;
635
636 ret=BIO_new(BIO_s_connect());
637 if (ret == NULL) return(NULL);
638 if (BIO_set_conn_hostname(ret,str))
639 return(ret);
640 else
641 {
642 BIO_free(ret);
643 return(NULL);
644 }
645 }
646
647#endif
648