Newer
Older
if (strstr(mbuf,"STARTTLS"))
foundit=1;
}
while (mbuf_len>3 && mbuf[3]=='-');
BIO_pop(fbio);
BIO_free(fbio);
if (!foundit)
BIO_printf(bio_err,
"didn't found starttls in server response,"
" try anyway...\n");
BIO_printf(sbio,"STARTTLS\r\n");
BIO_read(sbio,sbuf,BUFSIZZ);
}
else if (starttls_proto == PROTO_POP3)
Lutz Jänicke
committed
{
BIO_read(sbio,mbuf,BUFSIZZ);
BIO_printf(sbio,"STLS\r\n");
BIO_read(sbio,sbuf,BUFSIZZ);
}
else if (starttls_proto == PROTO_IMAP)
{
int foundit=0;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
BIO_gets(fbio,mbuf,BUFSIZZ);
/* STARTTLS command requires CAPABILITY... */
BIO_printf(fbio,". CAPABILITY\r\n");
/* wait for multi-line CAPABILITY response */
do
{
mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
if (strstr(mbuf,"STARTTLS"))
foundit=1;
}
while (mbuf_len>3 && mbuf[0]!='.');
BIO_pop(fbio);
BIO_free(fbio);
if (!foundit)
BIO_printf(bio_err,
"didn't found STARTTLS in server response,"
" try anyway...\n");
BIO_printf(sbio,". STARTTLS\r\n");
BIO_read(sbio,sbuf,BUFSIZZ);
}
else if (starttls_proto == PROTO_FTP)
{
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
/* wait for multi-line response to end from FTP */
do
{
mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
}
while (mbuf_len>3 && mbuf[3]=='-');
BIO_pop(fbio);
BIO_free(fbio);
BIO_printf(sbio,"AUTH TLS\r\n");
BIO_read(sbio,sbuf,BUFSIZZ);
}
for (;;)
{
FD_ZERO(&readfds);
FD_ZERO(&writefds);
if (SSL_in_init(con) && !SSL_total_renegotiations(con))
{
in_init=1;
tty_on=0;
}
else
{
tty_on=1;
if (in_init)
{
in_init=0;
#if 0 /* This test doesn't really work as intended (needs to be fixed) */
#ifndef OPENSSL_NO_TLSEXT
if (servername != NULL && !SSL_session_reused(con))
{
BIO_printf(bio_c_out,"Server did %sacknowledge servername extension.\n",tlsextcbp.ack?"":"not ");
}
Dr. Stephen Henson
committed
if (sess_out)
{
BIO *stmp = BIO_new_file(sess_out, "w");
if (stmp)
{
PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
BIO_free(stmp);
}
else
BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
}
print_stuff(bio_c_out,con,full_log);
if (full_log > 0) full_log--;
Lutz Jänicke
committed
if (starttls_proto)
{
BIO_printf(bio_err,"%s",mbuf);
/* We don't need to know any more */
}
if (reconnect)
{
reconnect--;
BIO_printf(bio_c_out,"drop connection and then reconnect\n");
SSL_shutdown(con);
SSL_set_connect_state(con);
SHUTDOWN(SSL_get_fd(con));
goto re_start;
}
}
}
ssl_pending = read_ssl && SSL_pending(con);
if (!ssl_pending)
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) && !defined (OPENSSL_SYS_BEOS_R5)
if (tty_on)
{
if (read_tty) openssl_fdset(fileno(stdin),&readfds);
if (write_tty) openssl_fdset(fileno(stdout),&writefds);
}
if (read_ssl)
openssl_fdset(SSL_get_fd(con),&readfds);
if (write_ssl)
openssl_fdset(SSL_get_fd(con),&writefds);
Dr. Stephen Henson
committed
#else
if(!tty_on || !write_tty) {
if (read_ssl)
openssl_fdset(SSL_get_fd(con),&readfds);
Dr. Stephen Henson
committed
if (write_ssl)
openssl_fdset(SSL_get_fd(con),&writefds);
Dr. Stephen Henson
committed
}
#endif
/* printf("mode tty(%d %d%d) ssl(%d%d)\n",
tty_on,read_tty,write_tty,read_ssl,write_ssl);*/
/* Note: under VMS with SOCKETSHR the second parameter
* is currently of type (int *) whereas under other
* systems it is (void *) if you don't have a cast it
* will choke the compiler: if you do have a cast then
* you can either go for (int *) or (void *).
*/
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
/* Under Windows/DOS we make the assumption that we can
Dr. Stephen Henson
committed
* always write to the tty: therefore if we need to
* write to the tty we just fall through. Otherwise
* we timeout the select every second and see if there
* are any keypresses. Note: this is a hack, in a proper
* Windows application we wouldn't do this.
*/
Dr. Stephen Henson
committed
if(!write_tty) {
if(read_tty) {
tv.tv_sec = 1;
tv.tv_usec = 0;
i=select(width,(void *)&readfds,(void *)&writefds,
NULL,&tv);
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
if(!i && (!_kbhit() || !read_tty) ) continue;
#else
if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue;
Dr. Stephen Henson
committed
} else i=select(width,(void *)&readfds,(void *)&writefds,
NULL,NULL);
}
#elif defined(OPENSSL_SYS_NETWARE)
if(!write_tty) {
if(read_tty) {
tv.tv_sec = 1;
tv.tv_usec = 0;
i=select(width,(void *)&readfds,(void *)&writefds,
NULL,&tv);
} else i=select(width,(void *)&readfds,(void *)&writefds,
NULL,NULL);
}
#elif defined(OPENSSL_SYS_BEOS_R5)
/* Under BeOS-R5 the situation is similar to DOS */
i=0;
stdin_set = 0;
(void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
if(!write_tty) {
if(read_tty) {
tv.tv_sec = 1;
tv.tv_usec = 0;
i=select(width,(void *)&readfds,(void *)&writefds,
NULL,&tv);
if (read(fileno(stdin), sbuf, 0) >= 0)
stdin_set = 1;
if (!i && (stdin_set != 1 || !read_tty))
continue;
} else i=select(width,(void *)&readfds,(void *)&writefds,
NULL,NULL);
}
(void)fcntl(fileno(stdin), F_SETFL, 0);
Dr. Stephen Henson
committed
#else
i=select(width,(void *)&readfds,(void *)&writefds,
NULL,NULL);
Dr. Stephen Henson
committed
#endif
if ( i < 0)
{
BIO_printf(bio_err,"bad select %d\n",
get_last_socket_error());
goto shut;
/* goto end; */
}
if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
{
k=SSL_write(con,&(cbuf[cbuf_off]),
(unsigned int)cbuf_len);
switch (SSL_get_error(con,k))
{
case SSL_ERROR_NONE:
cbuf_off+=k;
cbuf_len-=k;
if (k <= 0) goto end;
/* we have done a write(con,NULL,0); */
if (cbuf_len <= 0)
{
read_tty=1;
write_ssl=0;
}
else /* if (cbuf_len > 0) */
{
read_tty=0;
write_ssl=1;
}
break;
case SSL_ERROR_WANT_WRITE:
BIO_printf(bio_c_out,"write W BLOCK\n");
write_ssl=1;
read_tty=0;
break;
case SSL_ERROR_WANT_READ:
BIO_printf(bio_c_out,"write R BLOCK\n");
write_tty=0;
read_ssl=1;
write_ssl=0;
break;
case SSL_ERROR_WANT_X509_LOOKUP:
BIO_printf(bio_c_out,"write X BLOCK\n");
break;
case SSL_ERROR_ZERO_RETURN:
if (cbuf_len != 0)
{
BIO_printf(bio_c_out,"shutdown\n");
goto shut;
}
else
{
read_tty=1;
write_ssl=0;
break;
}
case SSL_ERROR_SYSCALL:
if ((k != 0) || (cbuf_len != 0))
{
BIO_printf(bio_err,"write:errno=%d\n",
get_last_socket_error());
goto shut;
}
else
{
read_tty=1;
write_ssl=0;
}
break;
case SSL_ERROR_SSL:
ERR_print_errors(bio_err);
goto shut;
}
}
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5)
/* Assume Windows/DOS/BeOS can always write */
Dr. Stephen Henson
committed
else if (!ssl_pending && write_tty)
#else
else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds))
Dr. Stephen Henson
committed
#endif
#ifdef CHARSET_EBCDIC
ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len);
#endif
i=raw_write_stdout(&(sbuf[sbuf_off]),sbuf_len);
if (i <= 0)
{
BIO_printf(bio_c_out,"DONE\n");
goto shut;
/* goto end; */
}
sbuf_len-=i;;
sbuf_off+=i;
if (sbuf_len <= 0)
{
read_ssl=1;
write_tty=0;
}
}
else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds))
#ifdef RENEG
{ static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } }
#endif
k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ );
#else
/* Demo for pending and peek :-) */
k=SSL_read(con,sbuf,16);
{ char zbuf[10240];
printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240));
}
#endif
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
switch (SSL_get_error(con,k))
{
case SSL_ERROR_NONE:
if (k <= 0)
goto end;
sbuf_off=0;
sbuf_len=k;
read_ssl=0;
write_tty=1;
break;
case SSL_ERROR_WANT_WRITE:
BIO_printf(bio_c_out,"read W BLOCK\n");
write_ssl=1;
read_tty=0;
break;
case SSL_ERROR_WANT_READ:
BIO_printf(bio_c_out,"read R BLOCK\n");
write_tty=0;
read_ssl=1;
if ((read_tty == 0) && (write_ssl == 0))
write_ssl=1;
break;
case SSL_ERROR_WANT_X509_LOOKUP:
BIO_printf(bio_c_out,"read X BLOCK\n");
break;
case SSL_ERROR_SYSCALL:
BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());
goto shut;
case SSL_ERROR_ZERO_RETURN:
BIO_printf(bio_c_out,"closed\n");
goto shut;
case SSL_ERROR_SSL:
ERR_print_errors(bio_err);
goto shut;
/* break; */
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0)))
else if (_kbhit())
#elif defined(OPENSSL_SYS_BEOS_R5)
else if (stdin_set)
Dr. Stephen Henson
committed
#else
else if (FD_ISSET(fileno(stdin),&readfds))
Dr. Stephen Henson
committed
#endif
if (crlf)
{
int j, lf_num;
i=raw_read_stdin(cbuf,BUFSIZZ/2);
lf_num = 0;
/* both loops are skipped when i <= 0 */
for (j = 0; j < i; j++)
if (cbuf[j] == '\n')
lf_num++;
for (j = i-1; j >= 0; j--)
{
cbuf[j+lf_num] = cbuf[j];
if (cbuf[j] == '\n')
{
lf_num--;
i++;
cbuf[j+lf_num] = '\r';
}
}
assert(lf_num == 0);
}
else
i=raw_read_stdin(cbuf,BUFSIZZ);
if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))
{
BIO_printf(bio_err,"DONE\n");
goto shut;
}
if ((!c_ign_eof) && (cbuf[0] == 'R'))
SSL_renegotiate(con);
}
else
{
cbuf_len=i;
cbuf_off=0;
#ifdef CHARSET_EBCDIC
ebcdic2ascii(cbuf, cbuf, i);
#endif
}
write_ssl=1;
if (in_init)
print_stuff(bio_c_out,con,full_log);
SSL_shutdown(con);
SHUTDOWN(SSL_get_fd(con));
ret=0;
end:
if (con != NULL)
{
if (prexit != 0)
print_stuff(bio_c_out,con,1);
SSL_free(con);
}
if (ctx != NULL) SSL_CTX_free(ctx);
if (cert)
X509_free(cert);
if (key)
EVP_PKEY_free(key);
if (pass)
OPENSSL_free(pass);
if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); }
if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); }
if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); }
if (bio_c_out != NULL)
{
BIO_free(bio_c_out);
bio_c_out=NULL;
}
apps_shutdown();
OPENSSL_EXIT(ret);
static void print_stuff(BIO *bio, SSL *s, int full)
STACK_OF(X509) *sk;
STACK_OF(X509_NAME) *sk2;
SSL_CIPHER *c;
X509_NAME *xn;
int j,i;
const COMP_METHOD *comp, *expansion;
if (full)
{
int got_a_chain = 0;
sk=SSL_get_peer_cert_chain(s);
if (sk != NULL)
{
got_a_chain = 1; /* we don't have it for SSL2 (yet) */
BIO_printf(bio,"---\nCertificate chain\n");
sk_X509_value(sk,i)),buf,sizeof buf);
BIO_printf(bio,"%2d s:%s\n",i,buf);
sk_X509_value(sk,i)),buf,sizeof buf);
BIO_printf(bio," i:%s\n",buf);
PEM_write_bio_X509(bio,sk_X509_value(sk,i));
}
}
BIO_printf(bio,"---\n");
peer=SSL_get_peer_certificate(s);
if (peer != NULL)
{
BIO_printf(bio,"Server certificate\n");
if (!(c_showcerts && got_a_chain)) /* Redundant if we showed the whole chain */
X509_NAME_oneline(X509_get_subject_name(peer),
BIO_printf(bio,"subject=%s\n",buf);
X509_NAME_oneline(X509_get_issuer_name(peer),
BIO_printf(bio,"issuer=%s\n",buf);
}
else
BIO_printf(bio,"no peer certificate available\n");
if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0))
{
BIO_printf(bio,"---\nAcceptable client certificate CA names\n");
X509_NAME_oneline(xn,buf,sizeof(buf));
BIO_write(bio,buf,strlen(buf));
BIO_write(bio,"\n",1);
}
}
else
{
BIO_printf(bio,"---\nNo client certificate CA names sent\n");
}
p=SSL_get_shared_ciphers(s,buf,sizeof buf);
if (p != NULL)
{
/* This works only for SSL 2. In later protocol
* versions, the client does not know what other
* ciphers (in addition to the one to be used
* in the current connection) the server supports. */
BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n");
j=i=0;
while (*p)
{
if (*p == ':')
{
BIO_write(bio,space,15-j%25);
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
i++;
j=0;
BIO_write(bio,((i%3)?" ":"\n"),1);
}
else
{
BIO_write(bio,p,1);
j++;
}
p++;
}
BIO_write(bio,"\n",1);
}
BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n",
BIO_number_read(SSL_get_rbio(s)),
BIO_number_written(SSL_get_wbio(s)));
}
BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, "));
c=SSL_get_current_cipher(s);
BIO_printf(bio,"%s, Cipher is %s\n",
SSL_CIPHER_get_version(c),
SSL_CIPHER_get_name(c));
if (peer != NULL) {
EVP_PKEY *pktmp;
pktmp = X509_get_pubkey(peer);
BIO_printf(bio,"Server public key is %d bit\n",
EVP_PKEY_bits(pktmp));
EVP_PKEY_free(pktmp);
}
Richard Levitte
committed
comp=SSL_get_current_compression(s);
expansion=SSL_get_current_expansion(s);
Richard Levitte
committed
BIO_printf(bio,"Compression: %s\n",
comp ? SSL_COMP_get_name(comp) : "NONE");
BIO_printf(bio,"Expansion: %s\n",
expansion ? SSL_COMP_get_name(expansion) : "NONE");
SSL_SESSION_print(bio,SSL_get_session(s));
BIO_printf(bio,"---\n");
if (peer != NULL)
X509_free(peer);
/* flush, or debugging output gets mixed with http response */