Newer
Older
BIO_printf(bio_s_out,"Client certificate\n");
PEM_write_bio_X509(bio_s_out,peer);
X509_NAME_oneline(X509_get_subject_name(peer),buf,BUFSIZ);
BIO_printf(bio_s_out,"subject=%s\n",buf);
X509_NAME_oneline(X509_get_issuer_name(peer),buf,BUFSIZ);
BIO_printf(bio_s_out,"issuer=%s\n",buf);
X509_free(peer);
}
if (SSL_get_shared_ciphers(con,buf,BUFSIZ) != NULL)
BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf);
str=SSL_CIPHER_get_name(SSL_get_current_cipher(con));
BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)");
if (con->hit) BIO_printf(bio_s_out,"Reused session-id\n");
if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) &
TLS1_FLAGS_TLS_PADDING_BUG)
BIO_printf(bio_s_out,"Peer has incorrect TLSv1 block padding\n");
return(1);
}
{
DH *ret=NULL;
BIO *bio;
if ((bio=BIO_new_file(DH_PARAM,"r")) == NULL)
goto err;
ret=PEM_read_bio_DHparams(bio,NULL,NULL);
err:
if (bio != NULL) BIO_free(bio);
return(ret);
}
{
FILE *in;
X509 *x=NULL;
if ((in=fopen(file,"r")) == NULL)
return(0);
for (;;)
{
if (PEM_read_X509(in,&x,NULL) == NULL)
break;
SSL_CTX_add_client_CA(ctx,x);
}
if (x != NULL) X509_free(x);
fclose(in);
return(1);
}
#endif
static int www_body(char *hostname, int s, unsigned char *context)
char *buf=NULL;
int ret=1;
int i,j,k,blank,dot;
struct stat st_buf;
SSL *con;
SSL_CIPHER *c;
BIO *io,*ssl_bio,*sbio;
buf=Malloc(bufsize);
if (buf == NULL) return(0);
io=BIO_new(BIO_f_buffer());
ssl_bio=BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL)) goto err;
#ifdef FIONBIO
if (s_nbio)
{
if (!s_quiet)
BIO_printf(bio_err,"turning on non blocking io\n");
if (BIO_socket_ioctl(s,FIONBIO,&sl) < 0)
ERR_print_errors(bio_err);
}
#endif
/* lets make the output buffer a reasonable size */
if (!BIO_set_write_buffer_size(io,bufsize)) goto err;
if ((con=(SSL *)SSL_new(ctx)) == NULL) goto err;
if(context) SSL_set_session_id_context(con, context,
strlen((char *)context));
sbio=BIO_new_socket(s,BIO_NOCLOSE);
if (s_nbio_test)
{
BIO *test;
test=BIO_new(BIO_f_nbio_test());
sbio=BIO_push(test,sbio);
}
SSL_set_bio(con,sbio,sbio);
SSL_set_accept_state(con);
/* SSL_set_fd(con,s); */
BIO_set_ssl(ssl_bio,con,BIO_CLOSE);
BIO_push(io,ssl_bio);
#ifdef CHARSET_EBCDIC
io = BIO_push(BIO_new(BIO_f_ebcdic_filter()),io);
#endif
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
if (s_debug)
{
con->debug=1;
BIO_set_callback(SSL_get_rbio(con),bio_dump_cb);
BIO_set_callback_arg(SSL_get_rbio(con),bio_s_out);
}
blank=0;
for (;;)
{
if (hack)
{
i=SSL_accept(con);
switch (SSL_get_error(con,i))
{
case SSL_ERROR_NONE:
break;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_X509_LOOKUP:
continue;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
case SSL_ERROR_ZERO_RETURN:
ret=1;
goto err;
/* break; */
}
SSL_renegotiate(con);
SSL_write(con,NULL,0);
}
i=BIO_gets(io,buf,bufsize-1);
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
if (i < 0) /* error */
{
if (!BIO_should_retry(io))
{
if (!s_quiet)
ERR_print_errors(bio_err);
goto err;
}
else
{
BIO_printf(bio_s_out,"read R BLOCK\n");
#ifndef MSDOS
sleep(1);
#endif
continue;
}
}
else if (i == 0) /* end of input */
{
ret=1;
goto end;
}
/* else we have data */
if ( ((www == 1) && (strncmp("GET ",buf,4) == 0)) ||
((www == 2) && (strncmp("GET /stats ",buf,10) == 0)))
{
char *p;
X509 *peer;
static char *space=" ";
BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
BIO_puts(io,"<HTML><BODY BGCOLOR=\"#ffffff\">\n");
BIO_puts(io,"<pre>\n");
/* BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/
BIO_puts(io,"\n");
for (i=0; i<local_argc; i++)
{
BIO_puts(io,local_argv[i]);
BIO_write(io," ",1);
}
BIO_puts(io,"\n");
/* The following is evil and should not really
* be done */
BIO_printf(io,"Ciphers supported in s_server binary\n");
sk=SSL_get_ciphers(con);
for (i=0; i<j; i++)
{
BIO_printf(io,"%-11s:%-25s",
SSL_CIPHER_get_version(c),
SSL_CIPHER_get_name(c));
if ((((i+1)%2) == 0) && (i+1 != j))
BIO_puts(io,"\n");
}
BIO_puts(io,"\n");
p=SSL_get_shared_ciphers(con,buf,bufsize);
if (p != NULL)
{
BIO_printf(io,"---\nCiphers common between both SSL end points:\n");
j=i=0;
while (*p)
{
if (*p == ':')
{
BIO_write(io,space,26-j);
i++;
j=0;
BIO_write(io,((i%3)?" ":"\n"),1);
}
else
{
BIO_write(io,p,1);
j++;
}
p++;
}
BIO_puts(io,"\n");
}
BIO_printf(io,((con->hit)
?"---\nReused, "
:"---\nNew, "));
c=SSL_get_current_cipher(con);
BIO_printf(io,"%s, Cipher is %s\n",
SSL_CIPHER_get_version(c),
SSL_CIPHER_get_name(c));
SSL_SESSION_print(io,SSL_get_session(con));
BIO_printf(io,"---\n");
print_stats(io,SSL_get_SSL_CTX(con));
BIO_printf(io,"---\n");
peer=SSL_get_peer_certificate(con);
if (peer != NULL)
{
BIO_printf(io,"Client certificate\n");
X509_print(io,peer);
PEM_write_bio_X509(io,peer);
}
else
BIO_puts(io,"no client certificate available\n");
BIO_puts(io,"</BODY></HTML>\r\n\r\n");
else if ((www == 2) && (strncmp("GET /",buf,5) == 0))
{
BIO *file;
char *p,*e;
static char *text="HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n";
/* skip the '/' */
p= &(buf[5]);
dot=0;
for (e=p; *e != '\0'; e++)
{
if (e[0] == ' ') break;
if ( (e[0] == '.') &&
(strncmp(&(e[-1]),"/../",4) == 0))
dot=1;
}
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
if (*e == '\0')
{
BIO_puts(io,text);
BIO_printf(io,"'%s' is an invalid file name\r\n",p);
break;
}
*e='\0';
if (dot)
{
BIO_puts(io,text);
BIO_printf(io,"'%s' contains '..' reference\r\n",p);
break;
}
if (*p == '/')
{
BIO_puts(io,text);
BIO_printf(io,"'%s' is an invalid path\r\n",p);
break;
}
/* append if a directory lookup */
if (e[-1] == '/')
strcat(p,"index.html");
/* if a directory, do the index thang */
if (stat(p,&st_buf) < 0)
{
BIO_puts(io,text);
BIO_printf(io,"Error accessing '%s'\r\n",p);
ERR_print_errors(io);
break;
}
if (S_ISDIR(st_buf.st_mode))
{
strcat(p,"/index.html");
}
if ((file=BIO_new_file(p,"r")) == NULL)
{
BIO_puts(io,text);
BIO_printf(io,"Error opening '%s'\r\n",p);
ERR_print_errors(io);
break;
}
if (!s_quiet)
BIO_printf(bio_err,"FILE:%s\n",p);
i=strlen(p);
if ( ((i > 5) && (strcmp(&(p[i-5]),".html") == 0)) ||
((i > 4) && (strcmp(&(p[i-4]),".php") == 0)) ||
((i > 4) && (strcmp(&(p[i-4]),".htm") == 0)))
BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
else
BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
/* send the file */
i=BIO_read(file,buf,bufsize);
if (i <= 0) break;
#ifdef RENEG
total_bytes+=i;
fprintf(stderr,"%d\n",i);
if (total_bytes > 3*1024)
{
total_bytes=0;
fprintf(stderr,"RENEGOTIATE\n");
SSL_renegotiate(con);
}
for (j=0; j<i; )
{
#ifdef RENEG
{ static count=0; if (++count == 13) { SSL_renegotiate(con); } }
#endif
k=BIO_write(io,&(buf[j]),i-j);
if (k <= 0)
{
if (!BIO_should_retry(io))
else
{
BIO_printf(bio_s_out,"rwrite W BLOCK\n");
}
}
else
{
j+=k;
}
}
}
BIO_free(file);
break;
}
}
for (;;)
{
i=(int)BIO_flush(io);
if (i <= 0)
{
if (!BIO_should_retry(io))
break;
}
else
break;
}
end:
/* make sure we re-use sessions */
SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
#else
/* This kills performace */
/* SSL_shutdown(con); A shutdown gets sent in the
* BIO_free_all(io) procession */
#endif
err:
if (ret >= 0)
BIO_printf(bio_s_out,"ACCEPT\n");
if (buf != NULL) Free(buf);
if (io != NULL) BIO_free_all(io);
/* if (ssl_bio != NULL) BIO_free(ssl_bio);*/
return(ret);
}
static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
{
static RSA *rsa_tmp=NULL;
if (rsa_tmp == NULL)
{
if (!s_quiet)
{
BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength);
rsa_tmp=RSA_generate_key(keylength,RSA_F4,NULL,NULL);
if (!s_quiet)
{
BIO_printf(bio_err,"\n");
}
}
return(rsa_tmp);
}