Unable to send a response packet to client browser
Hi,
I tried to implement a simple HTTPS server using openssl.
The Server establishes an SSL connection, receives input and searches
the input for GET string. If string is found it is supposed to send a
"static" response to the client.
The client here can be any browser.
I am able to establish the connection with client, read request
containing GET string. But the response could not be sent to the
client.
Please point the error in my program. Below is the server code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#define CADIR NULL
#define CAFILE "cacert.pem"
#define CERTFILE "mycert.pem"
#define KEYFILE "myprivkey.pem"
#define int_error(msg) handle_error(__FILE__, __LINE__, msg)
int seed_prng(int bytes)
{
if( !RAND_load_file("/dev/random", bytes))
return 0;
return 1;
}
void handle_error(const char *file, int lineno, const char *msg)
{
fprintf(stderr, "** %s:%i %s\n", file, lineno, msg);
ERR_print_errors_fp(stderr);
exit(-1);
}
int verify_callback(int ok, X509_STORE_CTX *store)
{
char data[256];
if (!ok)
{
X509 *cert = X509_STORE_CTX_get_current_cert(store);
int depth = X509_STORE_CTX_get_error_depth(store);
int err = X509_STORE_CTX_get_error(store);
fprintf(stderr, "-Error with certificate at depth: %i\n",
depth);
X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
fprintf(stderr, " issuer = %s\n", data);
X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
fprintf(stderr, " subject = %s\n", data);
fprintf(stderr, " err %i:%s\n", err,
X509_verify_cert_error_string(err));
}
return ok;
}
SSL_CTX *set_server_context(void)
{
SSL_CTX *ctx;
ctx = SSL_CTX_new(SSLv23_method());
if (SSL_CTX_load_verify_locations(ctx, CAFILE, CADIR) != 1)
int_error("Error loading CA file and/or directory");
if (SSL_CTX_set_default_verify_paths(ctx) != 1)
int_error("Error loading default CA file and/or directory");
ctx = SSL_CTX_new(SSLv23_method());
if(SSL_CTX_use_certificate_chain_file(ctx, CERTFILE) != 1)
int_error("Error loading server certificate from file");
if(SSL_CTX_use_PrivateKey_file(ctx, KEYFILE,SSL_FILETYPE_PEM) != 1)
int_error("Error loading private key from file");
SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE, verify_callback);
// SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER, verify_callback);
SSL_CTX_set_verify_depth(ctx, 4);
return ctx;
}
void init_OpenSSL(void)
{
if(! SSL_library_init())
{
fprintf(stderr, "** OpenSSL initialization failed!\n");
exit(-1);
}
SSL_load_error_strings();
}
int processClient(SSL *client_conn)
{
int err, nread, nwrite, werr,i=1;
char buf[1024];
do
{
for (nread = 0; nread < sizeof(buf); nread += err)
{
err = SSL_read(client_conn, buf + nread, sizeof(buf) - nread);
if (err <= 0)
break;
}
printf ("String Read = %s\n", buf);
if (strstr(buf,"GET"))
{
printf("GET Found\n");
strcpy(buf, "HTTP/1.1 200 OK\r\nServer:
Microsoft-IIS/5.0\r\nContent-Location:
[url]http://172.16.1.75/index.htm\r\nDate:[/url] Thu, 19 Jun 2008 10:07:37
GMT\r\nContent-Type: text/html\r\nAccept-Ranges:
bytes\r\nLast-Modified: Tue, 27 May 2008 12:22:48
GMT\r\nContent-Length: 47\r\n\r\n<html><body> Hello.. Main Page..
</body></html>\r\n");
for ( nwrite = 0; nwrite <= strlen(buf) ; )
{
werr = SSL_write(client_conn,buf,strlen(buf));
printf ("Loop = %d", i++);
if (werr <= 0 )
{
printf ("Write Error \n");
continue;
}
nwrite += werr;
}
if (werr>0)
{
printf ("Written HTML Page to socket\n");
// break;
}
break;
}
}
while (err > 0);
printf("Exited While loop and closing the ssl client connection\n");
return (SSL_get_shutdown(client_conn) & SSL_RECEIVED_SHUTDOWN) ? 1 : 0;
}
int main (int argc, char **argv)
{
int listenSock, clientSock, iRet;
struct sockaddr_in serverAddr, clientAddr;
int clientLength;
BIO *clientBIO;
SSL *ssl_client_conn;
SSL_CTX *ctx;
long ret_seed;
init_OpenSSL();
ret_seed=seed_prng(1024);
if(!ret_seed)
int_error("Error while seeding the prng");
ctx = set_server_context();
clientLength = sizeof(clientAddr);
listenSock=socket(AF_INET,SOCK_STREAM,0);
bzero(&serverAddr,sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);
serverAddr.sin_port=htons(443);
bind(listenSock,(struct sockaddr *)&serverAddr,sizeof(serverAddr));
listen(listenSock,1024);
for(;;)
{
clientSock = accept ( listenSock, (struct sockaddr*) &clientAddr,
&(clientLength) );
printf ("Accepted connection from client \n");
ssl_client_conn = SSL_new(ctx);
clientBIO = BIO_new_socket(clientSock, BIO_CLOSE);
SSL_set_bio(ssl_client_conn, clientBIO, clientBIO);
if ( SSL_accept(ssl_client_conn) != 1 )
{
printf("Error accepting ssl connection\n");
close (listenSock);
SSL_CTX_free(ctx);
exit (0);
}
if (processClient(ssl_client_conn))
printf ("Client Connection closed without errors\n");
// SSL_free(ssl_client_conn);
// BIO_free(clientBIO);
}
SSL_CTX_free (ctx);
close (listenSock);
}
--
thanks,
Lakshmi Prasanna
______________________________________________________________________
OpenSSL Project [url]http://www.openssl.org[/url]
User Support Mailing List [email]openssl-users@openssl.org[/email]
Automated List Manager [email]majordomo@openssl.org[/email]
Re: Unable to send a response packet to client browser
Uh, what is the actual behavior? Have you attempted to debug it with
openssl s_client? Have you attempted to figure out what a real
webserver, such as Apache, does with the same input?
This is not a general "we will debug your code for you" list, but we
can point you in the directions to look for the solutions.
I would also suggest that you read the relevant HTTP standards to
understand just what each of the headers you're sending means. It
would also probably be a good thing to avoid sending a false Server
header, and most clients won't allow IPs as server canonical-names
when there are certificates involved (since there is no means of
specifying an IP as a canonical name in the certificate).
-Kyle H
On Thu, Jun 19, 2008 at 5:39 AM, lakshmi prasanna <alakshmi@intoto.com> wrote:[color=blue]
> Hi,
>
> I tried to implement a simple HTTPS server using openssl.
> The Server establishes an SSL connection, receives input and searches
> the input for GET string. If string is found it is supposed to send a
> "static" response to the client.
> The client here can be any browser.
>
> I am able to establish the connection with client, read request
> containing GET string. But the response could not be sent to the
> client.
>
> Please point the error in my program. Below is the server code:
>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <unistd.h>
> #include <stdio.h>
> #include <openssl/bio.h>
> #include <openssl/err.h>
> #include <openssl/rand.h>
> #include <openssl/ssl.h>
> #include <openssl/x509v3.h>
>
> #define CADIR NULL
> #define CAFILE "cacert.pem"
> #define CERTFILE "mycert.pem"
> #define KEYFILE "myprivkey.pem"
>
> #define int_error(msg) handle_error(__FILE__, __LINE__, msg)
>
> int seed_prng(int bytes)
> {
> if( !RAND_load_file("/dev/random", bytes))
> return 0;
> return 1;
> }
> void handle_error(const char *file, int lineno, const char *msg)
> {
> fprintf(stderr, "** %s:%i %s\n", file, lineno, msg);
> ERR_print_errors_fp(stderr);
> exit(-1);
> }
>
> int verify_callback(int ok, X509_STORE_CTX *store)
> {
> char data[256];
> if (!ok)
> {
> X509 *cert = X509_STORE_CTX_get_current_cert(store);
> int depth = X509_STORE_CTX_get_error_depth(store);
> int err = X509_STORE_CTX_get_error(store);
> fprintf(stderr, "-Error with certificate at depth: %i\n",
> depth);
> X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
> fprintf(stderr, " issuer = %s\n", data);
> X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
> fprintf(stderr, " subject = %s\n", data);
> fprintf(stderr, " err %i:%s\n", err,
> X509_verify_cert_error_string(err));
> }
> return ok;
> }
>
> SSL_CTX *set_server_context(void)
> {
> SSL_CTX *ctx;
> ctx = SSL_CTX_new(SSLv23_method());
> if (SSL_CTX_load_verify_locations(ctx, CAFILE, CADIR) != 1)
> int_error("Error loading CA file and/or directory");
> if (SSL_CTX_set_default_verify_paths(ctx) != 1)
> int_error("Error loading default CA file and/or directory");
> ctx = SSL_CTX_new(SSLv23_method());
> if(SSL_CTX_use_certificate_chain_file(ctx, CERTFILE) != 1)
> int_error("Error loading server certificate from file");
> if(SSL_CTX_use_PrivateKey_file(ctx, KEYFILE,SSL_FILETYPE_PEM) != 1)
> int_error("Error loading private key from file");
> SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE, verify_callback);
> // SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER, verify_callback);
> SSL_CTX_set_verify_depth(ctx, 4);
> return ctx;
> }
>
> void init_OpenSSL(void)
> {
> if(! SSL_library_init())
> {
> fprintf(stderr, "** OpenSSL initialization failed!\n");
> exit(-1);
> }
> SSL_load_error_strings();
> }
>
>
> int processClient(SSL *client_conn)
> {
>
> int err, nread, nwrite, werr,i=1;
> char buf[1024];
>
> do
> {
> for (nread = 0; nread < sizeof(buf); nread += err)
> {
> err = SSL_read(client_conn, buf + nread, sizeof(buf) - nread);
> if (err <= 0)
> break;
> }
>
> printf ("String Read = %s\n", buf);
>
> if (strstr(buf,"GET"))
> {
> printf("GET Found\n");
> strcpy(buf, "HTTP/1.1 200 OK\r\nServer:
> Microsoft-IIS/5.0\r\nContent-Location:
> [url]http://172.16.1.75/index.htm\r\nDate:[/url] Thu, 19 Jun 2008 10:07:37
> GMT\r\nContent-Type: text/html\r\nAccept-Ranges:
> bytes\r\nLast-Modified: Tue, 27 May 2008 12:22:48
> GMT\r\nContent-Length: 47\r\n\r\n<html><body> Hello.. Main Page..
> </body></html>\r\n");
> for ( nwrite = 0; nwrite <= strlen(buf) ; )
> {
>
> werr = SSL_write(client_conn,buf,strlen(buf));
> printf ("Loop = %d", i++);
> if (werr <= 0 )
> {
> printf ("Write Error \n");
> continue;
> }
> nwrite += werr;
> }
> if (werr>0)
> {
> printf ("Written HTML Page to socket\n");
> // break;
> }
> break;
> }
> }
> while (err > 0);
> printf("Exited While loop and closing the ssl client connection\n");
> return (SSL_get_shutdown(client_conn) & SSL_RECEIVED_SHUTDOWN) ? 1 : 0;
>
>
> }
>
> int main (int argc, char **argv)
> {
>
> int listenSock, clientSock, iRet;
> struct sockaddr_in serverAddr, clientAddr;
> int clientLength;
> BIO *clientBIO;
> SSL *ssl_client_conn;
> SSL_CTX *ctx;
>
> long ret_seed;
>
> init_OpenSSL();
>
> ret_seed=seed_prng(1024);
> if(!ret_seed)
> int_error("Error while seeding the prng");
>
> ctx = set_server_context();
>
> clientLength = sizeof(clientAddr);
> listenSock=socket(AF_INET,SOCK_STREAM,0);
> bzero(&serverAddr,sizeof(serverAddr));
> serverAddr.sin_family = AF_INET;
> serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);
> serverAddr.sin_port=htons(443);
>
> bind(listenSock,(struct sockaddr *)&serverAddr,sizeof(serverAddr));
> listen(listenSock,1024);
>
> for(;;)
> {
> clientSock = accept ( listenSock, (struct sockaddr*) &clientAddr,
> &(clientLength) );
> printf ("Accepted connection from client \n");
> ssl_client_conn = SSL_new(ctx);
> clientBIO = BIO_new_socket(clientSock, BIO_CLOSE);
> SSL_set_bio(ssl_client_conn, clientBIO, clientBIO);
>
> if ( SSL_accept(ssl_client_conn) != 1 )
> {
> printf("Error accepting ssl connection\n");
> close (listenSock);
> SSL_CTX_free(ctx);
> exit (0);
> }
> if (processClient(ssl_client_conn))
> printf ("Client Connection closed without errors\n");
> // SSL_free(ssl_client_conn);
> // BIO_free(clientBIO);
> }
>
> SSL_CTX_free (ctx);
> close (listenSock);
>
>
>
> }
>
>
> --
> thanks,
> Lakshmi Prasanna
> ______________________________________________________________________
> OpenSSL Project [url]http://www.openssl.org[/url]
> User Support Mailing List [email]openssl-users@openssl.org[/email]
> Automated List Manager [email]majordomo@openssl.org[/email]
>[/color]
______________________________________________________________________
OpenSSL Project [url]http://www.openssl.org[/url]
User Support Mailing List [email]openssl-users@openssl.org[/email]
Automated List Manager [email]majordomo@openssl.org[/email]
RE: Unable to send a response packet to client browser
[color=blue]
> for (nread = 0; nread < sizeof(buf); nread += err)
> {
> err = SSL_read(client_conn, buf + nread,
> sizeof(buf) - nread);
> if (err <= 0)
> break;
> }[/color]
Umm, this doesn't look like an HTTP protocol implementation. This looks like
code to read 1,024 bytes. Who says an HTTP request is exactly 1,024 bytes?
[color=blue]
> for ( nwrite = 0; nwrite <= strlen(buf) ; )
> {
>
> werr =
> SSL_write(client_conn,buf,strlen(buf));
> printf ("Loop = %d", i++);
> if (werr <= 0 )
> {
> printf ("Write Error \n");
> continue;
> }
> nwrite += werr;
> }[/color]
This doesn't write all the data. It keeps writing the beginning of the data
as many times as needed to send a number of bytes equal to the total length
of the data. That doesn't seem to make much sense.
DS
______________________________________________________________________
OpenSSL Project [url]http://www.openssl.org[/url]
User Support Mailing List [email]openssl-users@openssl.org[/email]
Automated List Manager [email]majordomo@openssl.org[/email]