bss_acpt.c revision 59191
1185573Srwatson/* crypto/bio/bss_acpt.c */ 2185573Srwatson/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3155131Srwatson * All rights reserved. 4155131Srwatson * 5155131Srwatson * This package is an SSL implementation written 6155131Srwatson * by Eric Young (eay@cryptsoft.com). 7155131Srwatson * The implementation was written so as to conform with Netscapes SSL. 8155131Srwatson * 9155131Srwatson * This library is free for commercial and non-commercial use as long as 10155131Srwatson * the following conditions are aheared to. The following conditions 11155131Srwatson * apply to all code found in this distribution, be it the RC4, RSA, 12155131Srwatson * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13185573Srwatson * included with this distribution is covered by the same copyright terms 14155131Srwatson * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15155131Srwatson * 16155131Srwatson * Copyright remains Eric Young's, and as such any Copyright notices in 17155131Srwatson * the code are not to be removed. 18155131Srwatson * If this package is used in a product, Eric Young should be given attribution 19155131Srwatson * as the author of the parts of the library used. 20155131Srwatson * This can be in the form of a textual message at program startup or 21155131Srwatson * in documentation (online or textual) provided with the package. 22155131Srwatson * 23155131Srwatson * Redistribution and use in source and binary forms, with or without 24155131Srwatson * modification, are permitted provided that the following conditions 25155131Srwatson * are met: 26155131Srwatson * 1. Redistributions of source code must retain the copyright 27155131Srwatson * notice, this list of conditions and the following disclaimer. 28155131Srwatson * 2. Redistributions in binary form must reproduce the above copyright 29185573Srwatson * notice, this list of conditions and the following disclaimer in the 30155131Srwatson * documentation and/or other materials provided with the distribution. 31155131Srwatson * 3. All advertising materials mentioning features or use of this software 32155518Srwatson * must display the following acknowledgement: 33155518Srwatson * "This product includes cryptographic software written by 34155518Srwatson * Eric Young (eay@cryptsoft.com)" 35155518Srwatson * The word 'cryptographic' can be left out if the rouines from the library 36155131Srwatson * being used are not cryptographic related :-). 37155131Srwatson * 4. If you include any Windows specific code (or a derivative thereof) from 38156283Srwatson * the apps directory (application code) you must include an acknowledgement: 39156283Srwatson * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40156283Srwatson * 41156283Srwatson * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42156283Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43155131Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44155131Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45155131Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46155131Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47155131Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48155131Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49159248Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50155131Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51155131Srwatson * SUCH DAMAGE. 52155131Srwatson * 53155131Srwatson * The licence and distribution terms for any publically available version or 54155131Srwatson * derivative of this code cannot be changed. i.e. this code cannot simply be 55155131Srwatson * copied and put under another distribution licence 56155131Srwatson * [including the GNU Public Licence.] 57159248Srwatson */ 58159248Srwatson 59159248Srwatson#ifndef NO_SOCK 60155131Srwatson 61159248Srwatson#include <stdio.h> 62159248Srwatson#include <errno.h> 63159248Srwatson#define USE_SOCKETS 64159248Srwatson#include "cryptlib.h" 65159248Srwatson#include <openssl/bio.h> 66159248Srwatson 67159248Srwatson#ifdef WIN16 68159248Srwatson#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ 69168777Srwatson#else 70159248Srwatson#define SOCKET_PROTOCOL IPPROTO_TCP 71168777Srwatson#endif 72159248Srwatson 73159248Srwatson#if (defined(VMS) && __VMS_VER < 70000000) 74159248Srwatson/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ 75159248Srwatson#undef FIONBIO 76159248Srwatson#endif 77159248Srwatson 78159248Srwatsontypedef struct bio_accept_st 79159248Srwatson { 80159248Srwatson int state; 81159248Srwatson char *param_addr; 82159248Srwatson 83159248Srwatson int accept_sock; 84159248Srwatson int accept_nbio; 85159248Srwatson 86159248Srwatson char *addr; 87159248Srwatson int nbio; 88168777Srwatson /* If 0, it means normal, if 1, do a connect on bind failure, 89159248Srwatson * and if there is no-one listening, bind with SO_REUSEADDR. 90159248Srwatson * If 2, always use SO_REUSEADDR. */ 91159248Srwatson int bind_mode; 92159248Srwatson BIO *bio_chain; 93159248Srwatson } BIO_ACCEPT; 94159248Srwatson 95159248Srwatsonstatic int acpt_write(BIO *h,char *buf,int num); 96159248Srwatsonstatic int acpt_read(BIO *h,char *buf,int size); 97168777Srwatsonstatic int acpt_puts(BIO *h,char *str); 98168777Srwatsonstatic long acpt_ctrl(BIO *h,int cmd,long arg1,char *arg2); 99168777Srwatsonstatic int acpt_new(BIO *h); 100168777Srwatsonstatic int acpt_free(BIO *data); 101168777Srwatsonstatic int acpt_state(BIO *b, BIO_ACCEPT *c); 102168777Srwatsonstatic void acpt_close_socket(BIO *data); 103168777SrwatsonBIO_ACCEPT *BIO_ACCEPT_new(void ); 104168777Srwatsonvoid BIO_ACCEPT_free(BIO_ACCEPT *a); 105168777Srwatson 106168777Srwatson#define ACPT_S_BEFORE 1 107168777Srwatson#define ACPT_S_GET_ACCEPT_SOCKET 2 108168777Srwatson#define ACPT_S_OK 3 109168777Srwatson 110168777Srwatsonstatic BIO_METHOD methods_acceptp= 111159248Srwatson { 112159248Srwatson BIO_TYPE_ACCEPT, 113159248Srwatson "socket accept", 114159248Srwatson acpt_write, 115159248Srwatson acpt_read, 116159248Srwatson acpt_puts, 117159248Srwatson NULL, /* connect_gets, */ 118168777Srwatson acpt_ctrl, 119168777Srwatson acpt_new, 120168777Srwatson acpt_free, 121168777Srwatson NULL, 122168777Srwatson }; 123168777Srwatson 124159248SrwatsonBIO_METHOD *BIO_s_accept(void) 125159248Srwatson { 126159248Srwatson return(&methods_acceptp); 127159248Srwatson } 128159248Srwatson 129159248Srwatsonstatic int acpt_new(BIO *bi) 130159248Srwatson { 131159248Srwatson BIO_ACCEPT *ba; 132159248Srwatson 133159248Srwatson bi->init=0; 134159248Srwatson bi->num=INVALID_SOCKET; 135159248Srwatson bi->flags=0; 136159248Srwatson if ((ba=BIO_ACCEPT_new()) == NULL) 137159248Srwatson return(0); 138159248Srwatson bi->ptr=(char *)ba; 139159248Srwatson ba->state=ACPT_S_BEFORE; 140159248Srwatson bi->shutdown=1; 141159248Srwatson return(1); 142159248Srwatson } 143159248Srwatson 144159248SrwatsonBIO_ACCEPT *BIO_ACCEPT_new(void) 145159248Srwatson { 146159248Srwatson BIO_ACCEPT *ret; 147159248Srwatson 148159248Srwatson if ((ret=(BIO_ACCEPT *)Malloc(sizeof(BIO_ACCEPT))) == NULL) 149159248Srwatson return(NULL); 150159248Srwatson 151159248Srwatson memset(ret,0,sizeof(BIO_ACCEPT)); 152159248Srwatson ret->accept_sock=INVALID_SOCKET; 153159248Srwatson ret->bind_mode=BIO_BIND_NORMAL; 154159248Srwatson return(ret); 155159248Srwatson } 156159248Srwatson 157159248Srwatsonvoid BIO_ACCEPT_free(BIO_ACCEPT *a) 158159248Srwatson { 159159248Srwatson if(a == NULL) 160159248Srwatson return; 161159248Srwatson 162159248Srwatson if (a->param_addr != NULL) Free(a->param_addr); 163159248Srwatson if (a->addr != NULL) Free(a->addr); 164159248Srwatson if (a->bio_chain != NULL) BIO_free(a->bio_chain); 165159248Srwatson Free(a); 166159248Srwatson } 167159248Srwatson 168159248Srwatsonstatic void acpt_close_socket(BIO *bio) 169159248Srwatson { 170159248Srwatson BIO_ACCEPT *c; 171159248Srwatson 172159248Srwatson c=(BIO_ACCEPT *)bio->ptr; 173159248Srwatson if (c->accept_sock != INVALID_SOCKET) 174159248Srwatson { 175159248Srwatson shutdown(c->accept_sock,2); 176159248Srwatson closesocket(c->accept_sock); 177159248Srwatson c->accept_sock=INVALID_SOCKET; 178159248Srwatson bio->num=INVALID_SOCKET; 179159248Srwatson } 180159248Srwatson } 181159248Srwatson 182159248Srwatsonstatic int acpt_free(BIO *a) 183159248Srwatson { 184159248Srwatson BIO_ACCEPT *data; 185159248Srwatson 186155131Srwatson if (a == NULL) return(0); 187155131Srwatson data=(BIO_ACCEPT *)a->ptr; 188155131Srwatson 189155131Srwatson if (a->shutdown) 190155131Srwatson { 191155131Srwatson acpt_close_socket(a); 192155131Srwatson BIO_ACCEPT_free(data); 193156283Srwatson a->ptr=NULL; 194155131Srwatson a->flags=0; 195156283Srwatson a->init=0; 196156283Srwatson } 197156283Srwatson return(1); 198155131Srwatson } 199155131Srwatson 200155131Srwatsonstatic int acpt_state(BIO *b, BIO_ACCEPT *c) 201155131Srwatson { 202155131Srwatson BIO *bio=NULL,*dbio; 203155131Srwatson int s= -1; 204155131Srwatson int i; 205155131Srwatson 206155131Srwatsonagain: 207155131Srwatson switch (c->state) 208155131Srwatson { 209155131Srwatson case ACPT_S_BEFORE: 210155131Srwatson if (c->param_addr == NULL) 211155131Srwatson { 212155131Srwatson BIOerr(BIO_F_ACPT_STATE,BIO_R_NO_ACCEPT_PORT_SPECIFIED); 213155131Srwatson return(-1); 214155131Srwatson } 215155131Srwatson s=BIO_get_accept_socket(c->param_addr,c->bind_mode); 216155131Srwatson if (s == INVALID_SOCKET) 217155131Srwatson return(-1); 218155131Srwatson 219156283Srwatson if (c->accept_nbio) 220156283Srwatson { 221155131Srwatson if (!BIO_socket_nbio(s,1)) 222155131Srwatson { 223155131Srwatson closesocket(s); 224155131Srwatson BIOerr(BIO_F_ACPT_STATE,BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET); 225155131Srwatson return(-1); 226155131Srwatson } 227155131Srwatson } 228155131Srwatson c->accept_sock=s; 229155131Srwatson b->num=s; 230155131Srwatson c->state=ACPT_S_GET_ACCEPT_SOCKET; 231155131Srwatson return(1); 232155131Srwatson /* break; */ 233156283Srwatson case ACPT_S_GET_ACCEPT_SOCKET: 234156283Srwatson if (b->next_bio != NULL) 235156283Srwatson { 236156283Srwatson c->state=ACPT_S_OK; 237155131Srwatson goto again; 238155131Srwatson } 239155131Srwatson i=BIO_accept(c->accept_sock,&(c->addr)); 240155131Srwatson if (i < 0) return(i); 241155131Srwatson bio=BIO_new_socket(i,BIO_CLOSE); 242155131Srwatson if (bio == NULL) goto err; 243155131Srwatson 244155131Srwatson BIO_set_callback(bio,BIO_get_callback(b)); 245155131Srwatson BIO_set_callback_arg(bio,BIO_get_callback_arg(b)); 246155131Srwatson 247155131Srwatson if (c->nbio) 248155131Srwatson { 249155131Srwatson if (!BIO_socket_nbio(i,1)) 250155131Srwatson { 251155131Srwatson BIOerr(BIO_F_ACPT_STATE,BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET); 252155131Srwatson goto err; 253155131Srwatson } 254155131Srwatson } 255155131Srwatson 256155131Srwatson /* If the accept BIO has an bio_chain, we dup it and 257155131Srwatson * put the new socket at the end. */ 258155131Srwatson if (c->bio_chain != NULL) 259155131Srwatson { 260155131Srwatson if ((dbio=BIO_dup_chain(c->bio_chain)) == NULL) 261155131Srwatson goto err; 262159248Srwatson if (!BIO_push(dbio,bio)) goto err; 263155131Srwatson bio=dbio; 264155131Srwatson } 265155131Srwatson if (BIO_push(b,bio) == NULL) goto err; 266155131Srwatson 267155131Srwatson c->state=ACPT_S_OK; 268155131Srwatson return(1); 269155131Srwatsonerr: 270155131Srwatson if (bio != NULL) 271155131Srwatson BIO_free(bio); 272155131Srwatson else if (s >= 0) 273155131Srwatson closesocket(s); 274155131Srwatson return(0); 275155131Srwatson /* break; */ 276155131Srwatson case ACPT_S_OK: 277155131Srwatson if (b->next_bio == NULL) 278155131Srwatson { 279155131Srwatson c->state=ACPT_S_GET_ACCEPT_SOCKET; 280155131Srwatson goto again; 281155131Srwatson } 282155131Srwatson return(1); 283155131Srwatson /* break; */ 284155131Srwatson default: 285155131Srwatson return(0); 286155131Srwatson /* break; */ 287155131Srwatson } 288185573Srwatson 289155131Srwatson } 290155131Srwatson 291155131Srwatsonstatic int acpt_read(BIO *b, char *out, int outl) 292155131Srwatson { 293155131Srwatson int ret=0; 294155131Srwatson BIO_ACCEPT *data; 295155131Srwatson 296159248Srwatson BIO_clear_retry_flags(b); 297155131Srwatson data=(BIO_ACCEPT *)b->ptr; 298155131Srwatson 299155131Srwatson while (b->next_bio == NULL) 300155131Srwatson { 301155131Srwatson ret=acpt_state(b,data); 302155131Srwatson if (ret <= 0) return(ret); 303159248Srwatson } 304155131Srwatson 305155131Srwatson ret=BIO_read(b->next_bio,out,outl); 306155131Srwatson BIO_copy_next_retry(b); 307155131Srwatson return(ret); 308155131Srwatson } 309155131Srwatson 310159248Srwatsonstatic int acpt_write(BIO *b, char *in, int inl) 311155131Srwatson { 312155131Srwatson int ret; 313155131Srwatson BIO_ACCEPT *data; 314155131Srwatson 315155131Srwatson BIO_clear_retry_flags(b); 316159248Srwatson data=(BIO_ACCEPT *)b->ptr; 317155131Srwatson 318155131Srwatson while (b->next_bio == NULL) 319159248Srwatson { 320155131Srwatson ret=acpt_state(b,data); 321155131Srwatson if (ret <= 0) return(ret); 322155131Srwatson } 323155131Srwatson 324155131Srwatson ret=BIO_write(b->next_bio,in,inl); 325155131Srwatson BIO_copy_next_retry(b); 326155131Srwatson return(ret); 327155131Srwatson } 328155131Srwatson 329155131Srwatsonstatic long acpt_ctrl(BIO *b, int cmd, long num, char *ptr) 330155131Srwatson { 331155131Srwatson BIO *dbio; 332155131Srwatson int *ip; 333155131Srwatson long ret=1; 334155131Srwatson BIO_ACCEPT *data; 335155131Srwatson char **pp; 336155131Srwatson 337155131Srwatson data=(BIO_ACCEPT *)b->ptr; 338155131Srwatson 339155131Srwatson switch (cmd) 340155131Srwatson { 341155131Srwatson case BIO_CTRL_RESET: 342155131Srwatson ret=0; 343155131Srwatson data->state=ACPT_S_BEFORE; 344155131Srwatson acpt_close_socket(b); 345155131Srwatson b->flags=0; 346155131Srwatson break; 347155131Srwatson case BIO_C_DO_STATE_MACHINE: 348155131Srwatson /* use this one to start the connection */ 349155131Srwatson ret=(long)acpt_state(b,data); 350155131Srwatson break; 351155131Srwatson case BIO_C_SET_ACCEPT: 352155131Srwatson if (ptr != NULL) 353155131Srwatson { 354155131Srwatson if (num == 0) 355155131Srwatson { 356155131Srwatson b->init=1; 357155131Srwatson if (data->param_addr != NULL) 358155131Srwatson Free(data->param_addr); 359155131Srwatson data->param_addr=BUF_strdup(ptr); 360155131Srwatson } 361155131Srwatson else if (num == 1) 362155131Srwatson { 363155131Srwatson data->accept_nbio=(ptr != NULL); 364155131Srwatson } 365155131Srwatson else if (num == 2) 366155131Srwatson { 367155131Srwatson if (data->bio_chain != NULL) 368155131Srwatson BIO_free(data->bio_chain); 369155131Srwatson data->bio_chain=(BIO *)ptr; 370155131Srwatson } 371155131Srwatson } 372155131Srwatson break; 373155131Srwatson case BIO_C_SET_NBIO: 374155131Srwatson data->nbio=(int)num; 375155131Srwatson break; 376155131Srwatson case BIO_C_SET_FD: 377155131Srwatson b->init=1; 378155131Srwatson b->num= *((int *)ptr); 379155131Srwatson data->accept_sock=b->num; 380155131Srwatson data->state=ACPT_S_GET_ACCEPT_SOCKET; 381155131Srwatson b->shutdown=(int)num; 382155131Srwatson b->init=1; 383155131Srwatson break; 384155131Srwatson case BIO_C_GET_FD: 385155131Srwatson if (b->init) 386155131Srwatson { 387155131Srwatson ip=(int *)ptr; 388155131Srwatson if (ip != NULL) 389155131Srwatson *ip=data->accept_sock; 390155131Srwatson ret=data->accept_sock; 391155131Srwatson } 392155131Srwatson else 393155131Srwatson ret= -1; 394155131Srwatson break; 395155131Srwatson case BIO_C_GET_ACCEPT: 396155131Srwatson if (b->init) 397155131Srwatson { 398155131Srwatson if (ptr != NULL) 399155131Srwatson { 400155131Srwatson pp=(char **)ptr; 401155131Srwatson *pp=data->param_addr; 402155131Srwatson } 403155131Srwatson else 404155131Srwatson ret= -1; 405155131Srwatson } 406155131Srwatson else 407155131Srwatson ret= -1; 408155131Srwatson break; 409155131Srwatson case BIO_CTRL_GET_CLOSE: 410155131Srwatson ret=b->shutdown; 411155131Srwatson break; 412155131Srwatson case BIO_CTRL_SET_CLOSE: 413155131Srwatson b->shutdown=(int)num; 414155131Srwatson break; 415155131Srwatson case BIO_CTRL_PENDING: 416155131Srwatson case BIO_CTRL_WPENDING: 417155131Srwatson ret=0; 418155131Srwatson break; 419155131Srwatson case BIO_CTRL_FLUSH: 420155131Srwatson break; 421155131Srwatson case BIO_C_SET_BIND_MODE: 422155131Srwatson data->bind_mode=(int)num; 423155131Srwatson break; 424155131Srwatson case BIO_C_GET_BIND_MODE: 425155131Srwatson ret=(long)data->bind_mode; 426155131Srwatson break; 427155131Srwatson case BIO_CTRL_DUP: 428155131Srwatson dbio=(BIO *)ptr; 429155131Srwatson/* if (data->param_port) EAY EAY 430155131Srwatson BIO_set_port(dbio,data->param_port); 431155131Srwatson if (data->param_hostname) 432155131Srwatson BIO_set_hostname(dbio,data->param_hostname); 433155131Srwatson BIO_set_nbio(dbio,data->nbio); */ 434155131Srwatson break; 435155131Srwatson 436155131Srwatson default: 437155131Srwatson ret=0; 438155131Srwatson break; 439155131Srwatson } 440155131Srwatson return(ret); 441155131Srwatson } 442155131Srwatson 443155131Srwatsonstatic int acpt_puts(BIO *bp, char *str) 444155131Srwatson { 445155131Srwatson int n,ret; 446155131Srwatson 447155131Srwatson n=strlen(str); 448155131Srwatson ret=acpt_write(bp,str,n); 449155131Srwatson return(ret); 450155131Srwatson } 451155131Srwatson 452155131SrwatsonBIO *BIO_new_accept(char *str) 453155131Srwatson { 454155131Srwatson BIO *ret; 455155131Srwatson 456155131Srwatson ret=BIO_new(BIO_s_accept()); 457155131Srwatson if (ret == NULL) return(NULL); 458155131Srwatson if (BIO_set_accept_port(ret,str)) 459155131Srwatson return(ret); 460155131Srwatson else 461155131Srwatson { 462155131Srwatson BIO_free(ret); 463155131Srwatson return(NULL); 464155131Srwatson } 465155131Srwatson } 466155131Srwatson 467155131Srwatson#endif 468155131Srwatson