X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=demos%2Fstate_machine%2Fstate_machine.c;h=2ec196afffde42b5f50cbac8601b05b449300315;hb=40720ce3caf44294b5b87a18856b7aef06123314;hp=9cede29350631deff1f4dd4c05725b6810489ff6;hpb=cd26e6c79d1251262ad1742efb1510e1b7a900d3;p=thirdparty%2Fopenssl.git diff --git a/demos/state_machine/state_machine.c b/demos/state_machine/state_machine.c index 9cede29350..2ec196afff 100644 --- a/demos/state_machine/state_machine.c +++ b/demos/state_machine/state_machine.c @@ -6,7 +6,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -83,313 +83,325 @@ #include #include -/* die_unless is intended to work like assert, except that it happens - always, even if NDEBUG is defined. Use assert as a stopgap. */ +/* + * die_unless is intended to work like assert, except that it happens always, + * even if NDEBUG is defined. Use assert as a stopgap. + */ -#define die_unless(x) assert(x) +#define die_unless(x) assert(x) -typedef struct - { +typedef struct { SSL_CTX *pCtx; BIO *pbioRead; BIO *pbioWrite; SSL *pSSL; - } SSLStateMachine; +} SSLStateMachine; -void SSLStateMachine_print_error(SSLStateMachine *pMachine,const char *szErr) - { +void SSLStateMachine_print_error(SSLStateMachine * pMachine, + const char *szErr) +{ unsigned long l; - fprintf(stderr,"%s\n",szErr); - while((l=ERR_get_error())) - { - char buf[1024]; + fprintf(stderr, "%s\n", szErr); + while ((l = ERR_get_error())) { + char buf[1024]; - ERR_error_string_n(l,buf,sizeof buf); - fprintf(stderr,"Error %lx: %s\n",l,buf); - } + ERR_error_string_n(l, buf, sizeof buf); + fprintf(stderr, "Error %lx: %s\n", l, buf); } +} SSLStateMachine *SSLStateMachine_new(const char *szCertificateFile, - const char *szKeyFile) - { - SSLStateMachine *pMachine=malloc(sizeof *pMachine); + const char *szKeyFile) +{ + SSLStateMachine *pMachine = malloc(sizeof *pMachine); int n; die_unless(pMachine); - pMachine->pCtx=SSL_CTX_new(SSLv23_server_method()); + pMachine->pCtx = SSL_CTX_new(SSLv23_server_method()); die_unless(pMachine->pCtx); - n=SSL_CTX_use_certificate_file(pMachine->pCtx,szCertificateFile, - SSL_FILETYPE_PEM); + n = SSL_CTX_use_certificate_file(pMachine->pCtx, szCertificateFile, + SSL_FILETYPE_PEM); die_unless(n > 0); - n=SSL_CTX_use_PrivateKey_file(pMachine->pCtx,szKeyFile,SSL_FILETYPE_PEM); + n = SSL_CTX_use_PrivateKey_file(pMachine->pCtx, szKeyFile, + SSL_FILETYPE_PEM); die_unless(n > 0); - pMachine->pSSL=SSL_new(pMachine->pCtx); + pMachine->pSSL = SSL_new(pMachine->pCtx); die_unless(pMachine->pSSL); - pMachine->pbioRead=BIO_new(BIO_s_mem()); + pMachine->pbioRead = BIO_new(BIO_s_mem()); - pMachine->pbioWrite=BIO_new(BIO_s_mem()); + pMachine->pbioWrite = BIO_new(BIO_s_mem()); - SSL_set_bio(pMachine->pSSL,pMachine->pbioRead,pMachine->pbioWrite); + SSL_set_bio(pMachine->pSSL, pMachine->pbioRead, pMachine->pbioWrite); SSL_set_accept_state(pMachine->pSSL); return pMachine; - } - -void SSLStateMachine_read_inject(SSLStateMachine *pMachine, - const unsigned char *aucBuf,int nBuf) - { - int n=BIO_write(pMachine->pbioRead,aucBuf,nBuf); - /* If it turns out this assert fails, then buffer the data here - * and just feed it in in churn instead. Seems to me that it - * should be guaranteed to succeed, though. +} + +void SSLStateMachine_read_inject(SSLStateMachine * pMachine, + const unsigned char *aucBuf, int nBuf) +{ + int n = BIO_write(pMachine->pbioRead, aucBuf, nBuf); + /* + * If it turns out this assert fails, then buffer the data here and just + * feed it in in churn instead. Seems to me that it should be guaranteed + * to succeed, though. */ assert(n == nBuf); - fprintf(stderr,"%d bytes of encrypted data fed to state machine\n",n); - } + fprintf(stderr, "%d bytes of encrypted data fed to state machine\n", n); +} -int SSLStateMachine_read_extract(SSLStateMachine *pMachine, - unsigned char *aucBuf,int nBuf) - { +int SSLStateMachine_read_extract(SSLStateMachine * pMachine, + unsigned char *aucBuf, int nBuf) +{ int n; - if(!SSL_is_init_finished(pMachine->pSSL)) - { - fprintf(stderr,"Doing SSL_accept\n"); - n=SSL_accept(pMachine->pSSL); - if(n == 0) - fprintf(stderr,"SSL_accept returned zero\n"); - if(n < 0) - { - int err; - - if((err=SSL_get_error(pMachine->pSSL,n)) == SSL_ERROR_WANT_READ) - { - fprintf(stderr,"SSL_accept wants more data\n"); - return 0; - } - - SSLStateMachine_print_error(pMachine,"SSL_accept error"); - exit(7); - } - return 0; - } - - n=SSL_read(pMachine->pSSL,aucBuf,nBuf); - if(n < 0) - { - int err=SSL_get_error(pMachine->pSSL,n); - - if(err == SSL_ERROR_WANT_READ) - { - fprintf(stderr,"SSL_read wants more data\n"); - return 0; - } - } - - fprintf(stderr,"%d bytes of decrypted data read from state machine\n",n); - return n; + if (!SSL_is_init_finished(pMachine->pSSL)) { + fprintf(stderr, "Doing SSL_accept\n"); + n = SSL_accept(pMachine->pSSL); + if (n == 0) + fprintf(stderr, "SSL_accept returned zero\n"); + if (n < 0) { + int err; + + if ((err = + SSL_get_error(pMachine->pSSL, n)) == SSL_ERROR_WANT_READ) { + fprintf(stderr, "SSL_accept wants more data\n"); + return 0; + } + + SSLStateMachine_print_error(pMachine, "SSL_accept error"); + exit(7); + } + return 0; } -int SSLStateMachine_write_can_extract(SSLStateMachine *pMachine) - { - int n=BIO_pending(pMachine->pbioWrite); - if(n) - fprintf(stderr,"There is encrypted data available to write\n"); + n = SSL_read(pMachine->pSSL, aucBuf, nBuf); + if (n < 0) { + int err = SSL_get_error(pMachine->pSSL, n); + + if (err == SSL_ERROR_WANT_READ) { + fprintf(stderr, "SSL_read wants more data\n"); + return 0; + } + + SSLStateMachine_print_error(pMachine, "SSL_read error"); + exit(8); + } + + fprintf(stderr, "%d bytes of decrypted data read from state machine\n", + n); + return n; +} + +int SSLStateMachine_write_can_extract(SSLStateMachine * pMachine) +{ + int n = BIO_pending(pMachine->pbioWrite); + if (n) + fprintf(stderr, "There is encrypted data available to write\n"); else - fprintf(stderr,"There is no encrypted data available to write\n"); + fprintf(stderr, "There is no encrypted data available to write\n"); return n; - } +} -int SSLStateMachine_write_extract(SSLStateMachine *pMachine, - unsigned char *aucBuf,int nBuf) - { +int SSLStateMachine_write_extract(SSLStateMachine * pMachine, + unsigned char *aucBuf, int nBuf) +{ int n; - n=BIO_read(pMachine->pbioWrite,aucBuf,nBuf); - fprintf(stderr,"%d bytes of encrypted data read from state machine\n",n); + n = BIO_read(pMachine->pbioWrite, aucBuf, nBuf); + fprintf(stderr, "%d bytes of encrypted data read from state machine\n", + n); return n; - } - -void SSLStateMachine_write_inject(SSLStateMachine *pMachine, - const unsigned char *aucBuf,int nBuf) - { - int n=SSL_write(pMachine->pSSL,aucBuf,nBuf); - /* If it turns out this assert fails, then buffer the data here - * and just feed it in in churn instead. Seems to me that it - * should be guaranteed to succeed, though. +} + +void SSLStateMachine_write_inject(SSLStateMachine * pMachine, + const unsigned char *aucBuf, int nBuf) +{ + int n = SSL_write(pMachine->pSSL, aucBuf, nBuf); + /* + * If it turns out this assert fails, then buffer the data here and just + * feed it in in churn instead. Seems to me that it should be guaranteed + * to succeed, though. */ assert(n == nBuf); - fprintf(stderr,"%d bytes of unencrypted data fed to state machine\n",n); - } + fprintf(stderr, "%d bytes of unencrypted data fed to state machine\n", n); +} int OpenSocket(int nPort) - { +{ int nSocket; struct sockaddr_in saServer; struct sockaddr_in saClient; - int one=1; + int one = 1; int nSize; int nFD; int nLen; - nSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); - if(nSocket < 0) - { - perror("socket"); - exit(1); - } + nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (nSocket < 0) { + perror("socket"); + exit(1); + } - if(setsockopt(nSocket,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof one) < 0) - { - perror("setsockopt"); + if (setsockopt + (nSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof one) < 0) { + perror("setsockopt"); exit(2); - } - - memset(&saServer,0,sizeof saServer); - saServer.sin_family=AF_INET; - saServer.sin_port=htons(nPort); - nSize=sizeof saServer; - if(bind(nSocket,(struct sockaddr *)&saServer,nSize) < 0) - { - perror("bind"); - exit(3); - } - - if(listen(nSocket,512) < 0) - { - perror("listen"); - exit(4); - } - - nLen=sizeof saClient; - nFD=accept(nSocket,(struct sockaddr *)&saClient,&nLen); - if(nFD < 0) - { - perror("accept"); - exit(5); - } - - fprintf(stderr,"Incoming accepted on port %d\n",nPort); + } - return nFD; + memset(&saServer, 0, sizeof saServer); + saServer.sin_family = AF_INET; + saServer.sin_port = htons(nPort); + nSize = sizeof saServer; + if (bind(nSocket, (struct sockaddr *)&saServer, nSize) < 0) { + perror("bind"); + exit(3); + } + + if (listen(nSocket, 512) < 0) { + perror("listen"); + exit(4); + } + + nLen = sizeof saClient; + nFD = accept(nSocket, (struct sockaddr *)&saClient, &nLen); + if (nFD < 0) { + perror("accept"); + exit(5); } -int main(int argc,char **argv) - { + fprintf(stderr, "Incoming accepted on port %d\n", nPort); + + return nFD; +} + +int main(int argc, char **argv) +{ SSLStateMachine *pMachine; int nPort; int nFD; const char *szCertificateFile; const char *szKeyFile; + char rbuf[1]; + int nrbuf = 0; - if(argc != 4) - { - fprintf(stderr,"%s \n",argv[0]); - exit(6); - } + if (argc != 4) { + fprintf(stderr, "%s \n", argv[0]); + exit(6); + } - nPort=atoi(argv[1]); - szCertificateFile=argv[2]; - szKeyFile=argv[3]; + nPort = atoi(argv[1]); + szCertificateFile = argv[2]; + szKeyFile = argv[3]; SSL_library_init(); OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); ERR_load_crypto_strings(); - nFD=OpenSocket(nPort); - - pMachine=SSLStateMachine_new(szCertificateFile,szKeyFile); - - for( ; ; ) - { - fd_set rfds,wfds; - unsigned char buf[1024]; - int n; - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - - /* Select socket for input */ - FD_SET(nFD,&rfds); - - /* Select socket for output */ - if(SSLStateMachine_write_can_extract(pMachine)) - FD_SET(nFD,&wfds); - - /* Select stdin for input */ - FD_SET(0,&rfds); - - /* Wait for something to do something */ - n=select(nFD+1,&rfds,&wfds,NULL,NULL); - assert(n > 0); - - /* Socket is ready for input */ - if(FD_ISSET(nFD,&rfds)) - { - n=read(nFD,buf,sizeof buf); - if(n == 0) - { - fprintf(stderr,"Got EOF on socket\n"); - exit(0); - } - assert(n > 0); - - SSLStateMachine_read_inject(pMachine,buf,n); - } - - /* FIXME: we should only extract if stdout is ready */ - n=SSLStateMachine_read_extract(pMachine,buf,sizeof buf); - if(n < 0) - { - SSLStateMachine_print_error(pMachine,"read extract failed"); - break; - } - assert(n >= 0); - if(n > 0) - { - int w; - - w=write(1,buf,n); - /* FIXME: we should push back any unwritten data */ - assert(w == n); - } - - /* Socket is ready for output (and therefore we have output to send) */ - if(FD_ISSET(nFD,&wfds)) - { - int w; - - n=SSLStateMachine_write_extract(pMachine,buf,sizeof buf); - assert(n > 0); - - w=write(nFD,buf,n); - /* FIXME: we should push back any unwritten data */ - assert(w == n); - } - - /* Stdin is ready for input */ - if(FD_ISSET(0,&rfds)) - { - n=read(0,buf,sizeof buf); - if(n == 0) - { - fprintf(stderr,"Got EOF on stdin\n"); - exit(0); - } - assert(n > 0); - - SSLStateMachine_write_inject(pMachine,buf,n); - } - } + nFD = OpenSocket(nPort); + + pMachine = SSLStateMachine_new(szCertificateFile, szKeyFile); + + for (;;) { + fd_set rfds, wfds; + unsigned char buf[1024]; + int n; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + /* Select socket for input */ + FD_SET(nFD, &rfds); + + /* check whether there's decrypted data */ + if (!nrbuf) + nrbuf = SSLStateMachine_read_extract(pMachine, rbuf, 1); + + /* if there's decrypted data, check whether we can write it */ + if (nrbuf) + FD_SET(1, &wfds); + + /* Select socket for output */ + if (SSLStateMachine_write_can_extract(pMachine)) + FD_SET(nFD, &wfds); + + /* Select stdin for input */ + FD_SET(0, &rfds); + + /* Wait for something to do something */ + n = select(nFD + 1, &rfds, &wfds, NULL, NULL); + assert(n > 0); + + /* Socket is ready for input */ + if (FD_ISSET(nFD, &rfds)) { + n = read(nFD, buf, sizeof buf); + if (n == 0) { + fprintf(stderr, "Got EOF on socket\n"); + exit(0); + } + assert(n > 0); + + SSLStateMachine_read_inject(pMachine, buf, n); + } + + /* stdout is ready for output (and hence we have some to send it) */ + if (FD_ISSET(1, &wfds)) { + assert(nrbuf == 1); + buf[0] = rbuf[0]; + nrbuf = 0; + + n = SSLStateMachine_read_extract(pMachine, buf + 1, + sizeof buf - 1); + if (n < 0) { + SSLStateMachine_print_error(pMachine, "read extract failed"); + break; + } + assert(n >= 0); + ++n; + if (n > 0) { /* FIXME: has to be true now */ + int w; + + w = write(1, buf, n); + /* FIXME: we should push back any unwritten data */ + assert(w == n); + } + } + + /* + * Socket is ready for output (and therefore we have output to send) + */ + if (FD_ISSET(nFD, &wfds)) { + int w; + + n = SSLStateMachine_write_extract(pMachine, buf, sizeof buf); + assert(n > 0); + + w = write(nFD, buf, n); + /* FIXME: we should push back any unwritten data */ + assert(w == n); + } + + /* Stdin is ready for input */ + if (FD_ISSET(0, &rfds)) { + n = read(0, buf, sizeof buf); + if (n == 0) { + fprintf(stderr, "Got EOF on stdin\n"); + exit(0); + } + assert(n > 0); + + SSLStateMachine_write_inject(pMachine, buf, n); + } + } /* not reached */ return 0; - } +}