Esempio n. 1
0
static void mplex_parse(struct line line) {
	switch (*line.data) {
	case '0' ... '9':
		sqfill(line);
		break;
	case 'I':
		addnet(line);
		break;
	case 'L':
		line_accept(line);
		break;
	case 'F':
		freeze_net(line);
		break;
	case 'D':
		delnet(line);
		break;
	case 'S':
		start_ssl(line);
		break;
	case 'X':
		io_stop = 1;
		break;
	case 'R':
		io_stop = 0;
		reboot(line);
		break;
	default:
		die("Protocol violation: %s", line.data);
	}
}
Esempio n. 2
0
/**
 * Embeds a socket in a ssl connection.
 * @param socket the socket to be used.
 * @return The ssl connection or NULL if an error occured.
 */
int embed_ssl_socket(ssl_connection *ssl, int socket) {
  int ssl_error;
  time_t ssl_time;
  
  if (!ssl)
    return FALSE;
  
  if (!ssl_initialized)
    start_ssl();

  if (socket >= 0) {
    ssl->socket = socket;
  } else {
    LogError("%s: Socket error!\n", prog);
    goto sslerror;
  }

  if ((ssl->handler = SSL_new (ssl->ctx)) == NULL) {
    LogError("%s: Cannot initialize the SSL handler -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  set_noblock(ssl->socket);

  if ((ssl->socket_bio = BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) {
    LogError("%s: Cannot generate IO buffer -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio);
  ssl_time = time(NULL);

  while ((ssl_error = SSL_connect (ssl->handler)) < 0) {
    if ((time(NULL) - ssl_time) > SSL_TIMEOUT) {
      LogError("%s: SSL service timeout!\n", prog);
      goto sslerror;
    }

    if (!handle_error(ssl_error, ssl))
      goto sslerror;

    if (!BIO_should_retry(ssl->socket_bio))
      goto sslerror;
  }

  ssl->cipher = (char *) SSL_get_cipher(ssl->handler);

  if (! update_ssl_cert_data(ssl)) {
    LogError("%s: Cannot get the SSL server certificate!\n", prog);
    goto sslerror;
  }

  return TRUE;

sslerror:
  cleanup_ssl_socket(ssl);
  return FALSE;
} 
Esempio n. 3
0
	bool winsock2_streambuf::start_ssl()
	{
		if (m_sslhandle)
			return do_sslconnect(m_sslhandle);
		else
		{
			const SSL_METHOD * sslm = ::SSLv23_client_method();
			return start_ssl(sslm);
		}
	}
Esempio n. 4
0
/**
 * Initializes a ssl connection for server use.
 * @param pemfilename Filename for the key/cert file
 * @return An ssl connection, or NULL if an error occured.
 */
ssl_server_connection *init_ssl_server(char *pemfile, char *clientpemfile) {
        ASSERT(pemfile);
        if (!ssl_initialized)
                start_ssl();
        ssl_server_connection *ssl_server = new_ssl_server_connection(pemfile, clientpemfile);
        if (!(ssl_server->method = SSLv23_server_method())) {
                LogError("Cannot initialize the SSL method -- %s\n", SSLERROR);
                goto sslerror;
        }
        if (!(ssl_server->ctx = SSL_CTX_new(ssl_server->method))) {
                LogError("Cannot initialize SSL server certificate handler -- %s\n", SSLERROR);
                goto sslerror;
        }
        if (SSL_CTX_use_certificate_chain_file(ssl_server->ctx, pemfile) != 1) {
                LogError("Cannot initialize SSL server certificate -- %s\n", SSLERROR);
                goto sslerror;
        }
        if (SSL_CTX_use_PrivateKey_file(ssl_server->ctx, pemfile, SSL_FILETYPE_PEM) != 1) {
                LogError("Cannot initialize SSL server private key -- %s\n", SSLERROR);
                goto sslerror;
        }
        if (SSL_CTX_check_private_key(ssl_server->ctx) != 1) {
                LogError("The private key doesn't match the certificate public key -- %s\n", SSLERROR);
                goto sslerror;
        }
        if (SSL_CTX_set_cipher_list(ssl_server->ctx, CIPHER_LIST) != 1) {
                LogError("Error setting cipher list '%s' (no valid ciphers)\n", CIPHER_LIST);
                goto sslerror;
        }
        SSL_CTX_set_options(ssl_server->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); // Disable SSLv2 and SSLv3 for security reasons
        SSL_CTX_set_session_cache_mode(ssl_server->ctx, SSL_SESS_CACHE_OFF); // Disable session cache
        /*
         * We need this to force transmission of client certs
         */
        if (!verify_init(ssl_server)) {
                LogError("Verification engine was not properly initialized -- %s\n", SSLERROR);
                goto sslerror;
        }
        if (ssl_server->clientpemfile) {
                STACK_OF(X509_NAME) *stack = SSL_CTX_get_client_CA_list(ssl_server->ctx);
                LogInfo("Found %d client certificates\n", sk_X509_NAME_num(stack));
        }
        return ssl_server;
sslerror:
        delete_ssl_server_socket(ssl_server);
        return NULL;
}
Esempio n. 5
0
/**
 * Creates a server socket (SOCK_STREAM type) and binds it to the
 * specified local port number.  The socket get a ssl layer for
 * data transmission.
 * @param pemfilename Filename for the key/cert file
 * @param port The localhost port number to open
 * @param backlog The maximum queue length for incomming connections
 * @param bindAddr the local address the server will bind to
 * @return An ssl connection ready for accept, or NULL if an error occured.
 */
ssl_server_connection *create_ssl_server_socket(char *pemfile, int port,
        int backlog,
        char *bindAddr,
        char *clientpemfile) {

#ifdef HAVE_OPENSSL

    int socket;
    ssl_server_connection *ssl_server;

    ASSERT(pemfile);
    ASSERT(bindAddr);

    if (!ssl_initilized) {

        start_ssl();

    }

    if ((socket= create_server_socket(port, backlog, bindAddr)) == -1) {

        log("%s: create_ssl_server_socket(): Cannot connect!\n", prog);
        goto sslerror;

    }

    if (( ssl_server= init_ssl_server(pemfile, clientpemfile)) == NULL) {

        goto sslerror;

    }

    ssl_server->server_socket=socket;

    return ssl_server;

sslerror:

    return NULL;

#else

    return FALSE;

#endif

}
Esempio n. 6
0
/**
 * Open a socket against hostname:port with the given protocol.
 * This socket is sent through a ssl connection.
 * The protocol is normaly either SOCK_STREAM or SOCK_DGRAM.
 * @param hostname The host to open a socket at
 * @param port The port number to connect to
 * @param protocol Socket protocol to use (SOCK_STREAM|SOCK_DGRAM)
 * @param sslversion Version of the ssl layer auto, SSLv3, SSLv2 or TLS
 * @return The ssl connection or NULL if an error occured.
 */
ssl_connection *create_ssl_socket(char *hostname, int port, int protocol, int sslversion) {

#ifdef HAVE_OPENSSL

    int socket;
    ssl_connection *ssl = new_ssl_connection(NULL, sslversion);

    ASSERT(hostname);

    if (!ssl_initilized) {

        start_ssl();

    }

    if((socket= create_socket(hostname, port, protocol, NET_TIMEOUT)) == -1) {

        log("%s: create_ssl_socket(): Cannot connect!\n", prog);
        goto sslerror;

    }

    if (! embed_ssl_socket(ssl, socket)) {

        goto sslerror;

    }

    return ssl;

sslerror:

    return NULL;

#else

    return NULL;

#endif

}
Esempio n. 7
0
/**
 * Generate a new ssl server connection
 * @return ssl server connection container
 */
ssl_server_connection *new_ssl_server_connection(char * pemfile,
        char * clientpemfile) {

#ifdef HAVE_OPENSSL

    ssl_server_connection *ssl_server =
        (ssl_server_connection *) NEW(ssl_server);

    ASSERT(pemfile);

    if (!ssl_initilized) {

        start_ssl();

    }

    ssl_server->ctx= NULL;
    ssl_server->method= NULL;
    ssl_server->server_socket= 0;
    ssl_server->ssl_conn_list = NULL;
    ssl_server->pemfile=xstrdup(pemfile);

    if(clientpemfile != NULL) {

        ssl_server->clientpemfile= xstrdup(clientpemfile);

    } else {

        ssl_server->clientpemfile= NULL;

    }

    return ssl_server;

#else

    return NULL;

#endif

}
Esempio n. 8
0
/**
 * Inserts an SSL connection in the connection list of a server.
 * @param ssl_server data for ssl server connection
 * @return new SSL connection for the connection, or NULL if failed
 */
ssl_connection *insert_accepted_ssl_socket(ssl_server_connection *ssl_server) {
  ssl_connection *ssl;

  ASSERT(ssl_server);

  if (!ssl_initialized)
    start_ssl();

  NEW(ssl);
  ssl->method = NULL;
  ssl->handler = NULL;
  ssl->cert = NULL;
  ssl->cipher = NULL;
  ssl->socket = 0;
  ssl->next = NULL;
  ssl->accepted = FALSE;
  ssl->cert_md5= NULL;
  ssl->cert_md5_len = 0;
  ssl->clientpemfile = NULL;

  if (ssl_server->clientpemfile != NULL)
    ssl->clientpemfile = xstrdup(ssl_server->clientpemfile);

  LOCK(ssl_mutex);

  ssl->prev = NULL;
  ssl->next = ssl_server->ssl_conn_list;

  if ( ssl->next != NULL )
    ssl->next->prev = ssl;

  END_LOCK;

  ssl_server->ssl_conn_list = ssl;
  ssl->ctx = ssl_server->ctx;
  ssl->accepted = TRUE;

  return ssl;
}
Esempio n. 9
0
/**
 * Generate a new ssl connection
 * @return ssl connection container
 */
ssl_connection *new_ssl_connection(char *clientpemfile, int sslversion) {
  ssl_connection *ssl;

  if (!ssl_initialized)
    start_ssl();

  NEW(ssl);
  ssl->socket_bio = NULL; 
  ssl->handler = NULL;
  ssl->cert = NULL;
  ssl->cipher = NULL;
  ssl->socket = 0;
  ssl->next = NULL;
  ssl->accepted = FALSE;
  ssl->cert_md5 = NULL;
  ssl->cert_md5_len = 0;
  ssl->clientpemfile = clientpemfile ? xstrdup(clientpemfile) : NULL;
  
  switch (sslversion) {

  case SSL_VERSION_AUTO:
#ifdef OPENSSL_FIPS
    if (FIPS_mode()) {
      ssl->method = TLSv1_client_method();
    } else
#endif
      ssl->method = SSLv23_client_method();
    break;

  case SSL_VERSION_SSLV2:
#ifdef OPENSSL_NO_SSL2
    LogError("SSLv2 is not allowed - use either SSLv3 or TLSv1");
    goto sslerror;
#else
#ifdef OPENSSL_FIPS
    if (FIPS_mode()) {
      LogError("SSLv2 is not allowed in FIPS mode - use TLSv1");
      goto sslerror;
    } else
#endif
      ssl->method = SSLv2_client_method();
#endif
    break;

  case SSL_VERSION_SSLV3:
#ifdef OPENSSL_FIPS
    if (FIPS_mode()) {
      LogError("SSLv3 is not allowed in FIPS mode - use TLSv1");
      goto sslerror;
    } else
#endif
      ssl->method = SSLv3_client_method();
    break;

  case SSL_VERSION_TLS:
    ssl->method = TLSv1_client_method();
    break;

  default:
    LogError("%s: Unknown SSL version!\n", prog);
    goto sslerror;

  }

  if (!ssl->method) {
    LogError("%s: Cannot initialize SSL method -- %s\n", prog, SSLERROR);
    goto sslerror;
  } 

  if (!(ssl->ctx = SSL_CTX_new(ssl->method))) {
    LogError("%s: Cannot initialize SSL server certificate handler -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  if (ssl->clientpemfile) {

    if (SSL_CTX_use_certificate_chain_file(ssl->ctx, ssl->clientpemfile) <= 0) {
      LogError("%s: Cannot initialize SSL server certificate -- %s\n", prog, SSLERROR);
      goto sslerror;
    }

    if (SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->clientpemfile, SSL_FILETYPE_PEM) <= 0) {
      LogError("%s: Cannot initialize SSL server private key -- %s\n", prog, SSLERROR);
      goto sslerror;
    }

    if (!SSL_CTX_check_private_key(ssl->ctx)) {
      LogError("%s: Private key does not match the certificate public key -- %s\n", prog, SSLERROR);
      goto sslerror;
    }

  }

  return ssl;

sslerror:
  delete_ssl_socket(ssl);
  return NULL;
}
Esempio n. 10
0
/**
 * Embeds an accepted server socket in an existing ssl connection.
 * @param ssl ssl connection
 * @param socket the socket to be used.
 * @return TRUE, or FALSE if an error has occured.
 */
int embed_accepted_ssl_socket(ssl_connection *ssl, int socket) {
  int ssl_error;
  time_t ssl_time;

  ASSERT(ssl);
  
  ssl->socket = socket;

  if (!ssl_initialized)
    start_ssl();

  if (!(ssl->handler = SSL_new(ssl->ctx))) { 
    LogError("%s: Cannot initialize the SSL handler -- %s\n", prog, SSLERROR);
    return FALSE;
  } 

  if (socket < 0) {
    LogError("%s: Socket error!\n", prog);
    return FALSE;
  }

  set_noblock(ssl->socket);

  if (!(ssl->socket_bio = BIO_new_socket(ssl->socket, BIO_NOCLOSE))) {
    LogError("%s: Cannot generate IO buffer -- %s\n", prog, SSLERROR);
    return FALSE;
  }

  SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio);

  ssl_time = time(NULL);
  
  while ((ssl_error = SSL_accept(ssl->handler)) < 0) {

    if ((time(NULL) - ssl_time) > SSL_TIMEOUT) {
      LogError("%s: SSL service timeout!\n", prog);
      return FALSE;
    }

    if (!handle_error(ssl_error, ssl))
      return FALSE;

    if (!BIO_should_retry(ssl->socket_bio))
      return FALSE;

  }

  ssl->cipher = (char *)SSL_get_cipher(ssl->handler);

  if (!update_ssl_cert_data(ssl) && ssl->clientpemfile) {
    LogError("%s: The client did not supply a required client certificate!\n",
	  prog);
    return FALSE;
  }

  if (SSL_get_verify_result(ssl->handler) > 0) {
    LogError("%s: Verification of the certificate has failed!\n", prog);
    return FALSE;
  }

  return TRUE;
}
Esempio n. 11
0
/**
 * Initializes a ssl connection for server use.
 * @param pemfilename Filename for the key/cert file
 * @return An ssl connection, or NULL if an error occured.
 */
ssl_server_connection *init_ssl_server(char *pemfile, char *clientpemfile) {
  SSL_METHOD *server_method = NULL;
  ssl_server_connection *ssl_server;

  ASSERT(pemfile);

  if (!ssl_initialized)
    start_ssl();

  ssl_server = new_ssl_server_connection(pemfile, clientpemfile);
#ifdef OPENSSL_FIPS
  if (FIPS_mode())
    server_method = TLSv1_server_method();
  else
#endif
    server_method = SSLv23_server_method();
  if (!(ssl_server->method = server_method)) {
    LogError("%s: Cannot initialize the SSL method -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  if (!(ssl_server->ctx = SSL_CTX_new(ssl_server->method))) {
    LogError("%s: Cannot initialize SSL server certificate handler -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  if (SSL_CTX_use_certificate_chain_file(ssl_server->ctx, pemfile) != 1) {
    LogError("%s: Cannot initialize SSL server certificate -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  if (SSL_CTX_use_PrivateKey_file(ssl_server->ctx, pemfile, SSL_FILETYPE_PEM) != 1) {
    LogError("%s: Cannot initialize SSL server private key -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  if (SSL_CTX_check_private_key(ssl_server->ctx) != 1) {
    LogError("%s: The private key doesn't match the certificate public key -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  /* Disable session cache */
  SSL_CTX_set_session_cache_mode(ssl_server->ctx, SSL_SESS_CACHE_OFF);

  /*
   * We need this to force transmission of client certs
   */
  if (!verify_init(ssl_server)) {
    LogError("%s: Verification engine was not properly initialized -- %s\n", prog, SSLERROR);
    goto sslerror;
  }

  if (ssl_server->clientpemfile) {
    STACK_OF(X509_NAME) *stack = SSL_CTX_get_client_CA_list(ssl_server->ctx);
    LogInfo("%s: Found %d client certificates\n", prog, sk_X509_NAME_num(stack));
  }

  return ssl_server;

sslerror:
  delete_ssl_server_socket(ssl_server);
  return NULL;
}
Esempio n. 12
0
/**
 * Generate a new ssl connection
 * @return ssl connection container
 */
ssl_connection *new_ssl_connection(char *clientpemfile, int sslversion) {
        ssl_connection *ssl;

        if (!ssl_initialized)
                start_ssl();

        NEW(ssl);
        ssl->socket_bio = NULL;
        ssl->handler = NULL;
        ssl->cert = NULL;
        ssl->cipher = NULL;
        ssl->socket = 0;
        ssl->next = NULL;
        ssl->accepted = FALSE;
        ssl->cert_md5 = NULL;
        ssl->cert_md5_len = 0;
        ssl->clientpemfile = clientpemfile ? Str_dup(clientpemfile) : NULL;

        switch (sslversion) {
                case SSL_VERSION_SSLV2:
#ifdef OPENSSL_NO_SSL2
                        LogError("SSLv2 is not allowed - use TLS\n");
                        goto sslerror;
#else
#ifdef OPENSSL_FIPS
                        if (FIPS_mode()) {
                                LogError("SSLv2 is not allowed in FIPS mode - use TLS\n");
                                goto sslerror;
                        } else
#endif
                                ssl->method = SSLv2_client_method();
#endif
                        break;
                case SSL_VERSION_SSLV3:
#ifdef OPENSSL_FIPS
                        if (FIPS_mode()) {
                                LogError("SSLv3 is not allowed in FIPS mode - use TLS\n");
                                goto sslerror;
                        } else
#endif
                                ssl->method = SSLv3_client_method();
                        break;
                case SSL_VERSION_TLSV1:
                        ssl->method = TLSv1_client_method();
                        break;
#ifdef HAVE_TLSV1_1
                case SSL_VERSION_TLSV11:
                        ssl->method = TLSv1_1_client_method();
                        break;
#endif
#ifdef HAVE_TLSV1_2
                case SSL_VERSION_TLSV12:
                        ssl->method = TLSv1_2_client_method();
                        break;
#endif
                case SSL_VERSION_AUTO:
                default:
                        ssl->method = SSLv23_client_method();
                        break;

        }

        if (!ssl->method) {
                LogError("Cannot initialize SSL method -- %s\n", SSLERROR);
                goto sslerror;
        }

        if (!(ssl->ctx = SSL_CTX_new(ssl->method))) {
                LogError("Cannot initialize SSL client certificate handler -- %s\n", SSLERROR);
                goto sslerror;
        }

        if (sslversion == SSL_VERSION_AUTO)
                SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

        if (ssl->clientpemfile) {

                if (SSL_CTX_use_certificate_chain_file(ssl->ctx, ssl->clientpemfile) <= 0) {
                        LogError("Cannot initialize SSL client certificate -- %s\n", SSLERROR);
                        goto sslerror;
                }

                if (SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->clientpemfile, SSL_FILETYPE_PEM) <= 0) {
                        LogError("Cannot initialize SSL client private key -- %s\n", SSLERROR);
                        goto sslerror;
                }

                if (!SSL_CTX_check_private_key(ssl->ctx)) {
                        LogError("Private key does not match the certificate public key -- %s\n", SSLERROR);
                        goto sslerror;
                }

        }

        return ssl;

sslerror:
        delete_ssl_socket(ssl);
        return NULL;
}
Esempio n. 13
0
int main(int argc, char **argv)
{
    struct sockaddr_in srvaddr, cliaddr;
    socklen_t socketfd,clisocketfd;
    socklen_t clilen;
    WOLFSSL_CTX *wsslctx;
    WOLFSSL *sslconn;
    int portnum;
    const char *certpath;
    const char *privpath;
    std::string cliipaddr;
    std::string data;
    std::string dbpath;
    pid_t pid;

    clilen = sizeof(cliaddr);
    wolfSSL_Init();

    if (argc == 4)
    {
        if (prompt_y_n("Create new user database?", ""))
        {
            do
            {
                std::cout << "Please specify a filename for the new database: ";
                std::getline(std::cin, dbpath);
                
                if (!access(dbpath.c_str(), F_OK))
                {
                    if (prompt_y_n("File already exists, overwrite?", ""))
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            } while (true);
                
            std::string jsondat = "{ \"users\" : { } }";
            std::ofstream outputfile;
            outputfile.open(dbpath);
         
            if (outputfile.is_open())
            {
                outputfile << jsondat;
                outputfile.close();
                std::cout << "Created new database file!"
                          << std::endl;
            }
            else
            {
                std::cout << "Failed to create new database file!"
                          << std::endl;
            }
        }
        else
        {
            std::cout << "Ok, please specify an existing user database" << std::endl;
			std::cout<<"Usage: "<<argv[0]<<" <port #> <certfile> <privkey> [userdb]"<<std::endl;
            return -1;
        }
    }

    else if (argc < 5)
    {
        std::cout<<"Usage: "<<argv[0]<<" <port #> <certfile> <privkey> [userdb]"<<std::endl;
        std::cout<<"If [userdb] is unspecified, we will create a new one"<<std::endl;
        return 1;
    }

    portnum  = atoi(argv[1]);
    certpath = argv[2];
    privpath = argv[3];
    if (argc == 5)
        dbpath = std::string(argv[4]);

    if (portnum < 1 || portnum > 65535)
    {
        std::cout<<"Please choose a port in the range: 1-65535"<<std::endl;
        return 1;
    }

    /*userdb_file.open(dbpath);
    if (!userdb_file.is_open())
    {
        std::cout<<"[-] Could not open user database"<<std::endl;
        return 1;
        }*/

    if ( (socketfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
    {
        std::cout<<"Failed to initialize socket"<<std::endl;
        return -1;
    }

    memset((void*)&srvaddr,0,sizeof(srvaddr));
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_addr.s_addr = INADDR_ANY;
    srvaddr.sin_port = htons(portnum);

    if ( (wsslctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL )
    {
        std::cout<<"Failed to create new WolfSSL CTX"<<std::endl;
        return -1;
    }
    
    if (wolfSSL_CTX_use_PrivateKey_file(wsslctx,privpath,SSL_FILETYPE_PEM) != SSL_SUCCESS)
    {
        std::cout<<"Failed to load SSL private key file"<<std::endl;
        return -2;
    }

    if (wolfSSL_CTX_use_certificate_file(wsslctx,certpath,SSL_FILETYPE_PEM) != SSL_SUCCESS)
    {
        std::cout<<"Failed to load SSL certificate file"<<std::endl;
        return -2;
    }

    if (bind(socketfd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) != 0)
    {
        std::cout<<"Failed to bind to port "<<portnum<<std::endl;
        return -3;
    }
    
    listen(socketfd,10);
    std::cout<<"[+] KeyLocker server started. Waiting for connections..."<<std::endl;

    while(1)
    {
        if ( (clisocketfd = accept(socketfd,(struct sockaddr *)&cliaddr,&clilen)) == -1 )
        {
            std::cout<<"Failed to accept connection on socket"<<std::endl;
            //return -3;
        }

        if ( (pid=fork()) < 0 )
        {
            std::cout<<"Fork failed"<<std::endl;
            return -4;
        }
        else if (pid > 0)
        {
            /* parent */
            close(clisocketfd);
            waitpid(pid, 0, 0);
            continue;
        }
        else
        {
            /* child */
            close(socketfd);
            //15 second timeout
            signal(SIGALRM,sighandler);
            alarm(15);
            cliipaddr = std::string(inet_ntoa(cliaddr.sin_addr));
            std::cout<<"[+] Client connected from IP address: "<<cliipaddr
                     <<std::endl;
            sslconn = start_ssl(wsslctx,clisocketfd,cliaddr);
            data = get_cli_data(sslconn);

            //shut alarm off
            alarm(0);
            process_data(data,dbpath,sslconn);

            close(clisocketfd);
            break;
        }

        usleep(1000);
    }
    //close(clisocketfd);
    wolfSSL_free(sslconn);
    wolfSSL_CTX_free(wsslctx);
    wolfSSL_Cleanup();

    return 0;
}
Esempio n. 14
0
/**
 * Inserts an SSL connection in the connection list of a server.
 * @param ssl_server data for ssl server connection
 * @return new SSL connection for the connection, or NULL if failed
 */
ssl_connection *insert_accepted_ssl_socket(ssl_server_connection *ssl_server) {

#ifdef HAVE_OPENSSL

    ssl_connection *ssl = (ssl_connection *) NEW(ssl);

    ASSERT(ssl_server);

    if (!ssl_initilized) {

        start_ssl();

    }

    ssl->method= NULL;
    ssl->handler= NULL;
    ssl->cert= NULL;
    ssl->cipher= NULL;
    ssl->socket= 0;
    ssl->next= NULL;
    ssl->accepted= FALSE;
    ssl->cert_md5= NULL;
    ssl->cert_md5_len= 0;
    ssl->clientpemfile= NULL;

    if(ssl_server->clientpemfile!=NULL) {

        ssl->clientpemfile= xstrdup(ssl_server->clientpemfile);

    }

    if(( ssl_server == NULL ) || (ssl == NULL)) {

        return NULL;

    }

    LOCK(ssl_mutex);

    ssl->prev=NULL;
    ssl->next=ssl_server->ssl_conn_list;

    if( ssl->next != NULL ) {

        ssl->next->prev=ssl;

    }

    END_LOCK;

    ssl_server->ssl_conn_list=ssl;
    ssl->ctx=ssl_server->ctx;
    ssl->accepted=TRUE;

    return ssl;

#else

    return NULL;

#endif

}
Esempio n. 15
0
int main (int argc, char **argv) {
	
	server *srv = NULL;
	int print_config = 0;
	int test_config = 0;
	int i_am_root;
	int o;
	int num_childs = 0;
	int pid_fd = -1, fd;
	size_t i;
#ifdef HAVE_SIGACTION
	struct sigaction act;
#endif
#ifdef HAVE_GETRLIMIT
	struct rlimit rlim;
#endif

#ifdef USE_ALARM
	struct itimerval interval;

	interval.it_interval.tv_sec = 1;
	interval.it_interval.tv_usec = 0;
	interval.it_value.tv_sec = 1;
	interval.it_value.tv_usec = 0;
#endif
	
	/* for nice %b handling in strfime() */
	setlocale(LC_TIME, "C");

	if (NULL == (srv = server_init())) {
		fprintf(stderr, "did this really happen?\n");
		return -1;
	}

	/* init structs done */

	srv->srvconf.port = 0;
#ifdef HAVE_GETUID
	i_am_root = (getuid() == 0);
#else
	i_am_root = 0;
#endif
	srv->srvconf.dont_daemonize = 0;

#ifdef APP_IPKG
    if(!access("/etc/server.pem",F_OK)){

    }
    else{
    	start_ssl();
    }
#endif

	while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
		switch(o) {
		case 'f':
			if (srv->config_storage) {
				log_error_write(srv, __FILE__, __LINE__, "s",
						"Can only read one config file. Use the include command to use multiple config files.");

				server_free(srv);
				return -1;
			}
			if (config_read(srv, optarg)) {
				server_free(srv);
				return -1;
			}			
			break;
		case 'm':
			buffer_copy_string(srv->srvconf.modules_dir, optarg);
			break;
		case 'p': print_config = 1; break;
		case 't': test_config = 1; break;
		case 'D': srv->srvconf.dont_daemonize = 1; break;
		case 'v': show_version(); return 0;
		case 'V': show_features(); return 0;
		case 'h': show_help(); return 0;
		default:
			show_help();
			server_free(srv);
			return -1;
		}
	}
	
	if (!srv->config_storage) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"No configuration available. Try using -f option.");

		server_free(srv);
		return -1;
	}

	if (print_config) {
		data_unset *dc = srv->config_context->data[0];
		if (dc) {
			dc->print(dc, 0);
			fprintf(stdout, "\n");
		} else {
			/* shouldn't happend */
			fprintf(stderr, "global config not found\n");
		}
	}

	if (test_config) {
		printf("Syntax OK\n");
	}

	if (test_config || print_config) {
		server_free(srv);
		return 0;
	}

	/* close stdin and stdout, as they are not needed */
	openDevNull(STDIN_FILENO);
	openDevNull(STDOUT_FILENO);

	if (0 != config_set_defaults(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"setting default values failed");
		server_free(srv);
		return -1;
	}

	/* UID handling */
#ifdef HAVE_GETUID
	if (!i_am_root && issetugid()) {
		/* we are setuid-root */

		log_error_write(srv, __FILE__, __LINE__, "s",
				"Are you nuts ? Don't apply a SUID bit to this binary");

		server_free(srv);
		return -1;
	}
#endif

	/* check document-root */
	if (buffer_string_is_empty(srv->config_storage[0]->document_root)) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"document-root is not set\n");

		server_free(srv);

		return -1;
	}

	if (plugins_load(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"loading plugins finally failed");

		plugins_free(srv);
		server_free(srv);

		return -1;
	}

	/* open pid file BEFORE chroot */
	if (!buffer_string_is_empty(srv->srvconf.pid_file)) {
		if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
			struct stat st;
			if (errno != EEXIST) {
				log_error_write(srv, __FILE__, __LINE__, "sbs",
					"opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
				return -1;
			}

			if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
				log_error_write(srv, __FILE__, __LINE__, "sbs",
						"stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
			}

			if (!S_ISREG(st.st_mode)) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
						"pid-file exists and isn't regular file:", srv->srvconf.pid_file);
				return -1;
			}

			if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
				log_error_write(srv, __FILE__, __LINE__, "sbs",
						"opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
				return -1;
			}
		}
	}

	if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
		/* select limits itself
		 *
		 * as it is a hard limit and will lead to a segfault we add some safety
		 * */
		srv->max_fds = FD_SETSIZE - 200;
	} else {
		srv->max_fds = 4096;
	}

	if (i_am_root) {
		struct group *grp = NULL;
		struct passwd *pwd = NULL;
		int use_rlimit = 1;

#ifdef HAVE_VALGRIND_VALGRIND_H
		if (RUNNING_ON_VALGRIND) use_rlimit = 0;
#endif

#ifdef HAVE_GETRLIMIT
		if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
			log_error_write(srv, __FILE__, __LINE__,
					"ss", "couldn't get 'max filedescriptors'",
					strerror(errno));
			return -1;
		}

		if (use_rlimit && srv->srvconf.max_fds) {
			/* set rlimits */

			rlim.rlim_cur = srv->srvconf.max_fds;
			rlim.rlim_max = srv->srvconf.max_fds;

			if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
				log_error_write(srv, __FILE__, __LINE__,
						"ss", "couldn't set 'max filedescriptors'",
						strerror(errno));
				return -1;
			}
		}

		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
			srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
		} else {
			srv->max_fds = rlim.rlim_cur;
		}

		/* set core file rlimit, if enable_cores is set */
		if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
			rlim.rlim_cur = rlim.rlim_max;
			setrlimit(RLIMIT_CORE, &rlim);
		}
#endif
		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
			/* don't raise the limit above FD_SET_SIZE */
			if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"can't raise max filedescriptors above",  FD_SETSIZE - 200,
						"if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
				return -1;
			}
		}


#ifdef HAVE_PWD_H
		/* set user and group */
		if (!buffer_string_is_empty(srv->srvconf.username)) {
			if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
						"can't find username", srv->srvconf.username);
				return -1;
			}

			if (pwd->pw_uid == 0) {
				log_error_write(srv, __FILE__, __LINE__, "s",
						"I will not set uid to 0\n");
				return -1;
			}
		}

		if (!buffer_string_is_empty(srv->srvconf.groupname)) {
			if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
					"can't find groupname", srv->srvconf.groupname);
				return -1;
			}
			if (grp->gr_gid == 0) {
				log_error_write(srv, __FILE__, __LINE__, "s",
						"I will not set gid to 0\n");
				return -1;
			}
		}
#endif
		/* we need root-perms for port < 1024 */
		if (0 != network_init(srv)) {
			plugins_free(srv);
			server_free(srv);

			return -1;
		}
#ifdef HAVE_PWD_H
		/* 
		 * Change group before chroot, when we have access
		 * to /etc/group
		 * */
		if (NULL != grp) {
			if (-1 == setgid(grp->gr_gid)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "setgid failed: ", strerror(errno));
				return -1;
			}
			if (-1 == setgroups(0, NULL)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "setgroups failed: ", strerror(errno));
				return -1;
			}
			if (!buffer_string_is_empty(srv->srvconf.username)) {
				initgroups(srv->srvconf.username->ptr, grp->gr_gid);
			}
		}
#endif
#ifdef HAVE_CHROOT
		if (!buffer_string_is_empty(srv->srvconf.changeroot)) {
			tzset();

			if (-1 == chroot(srv->srvconf.changeroot->ptr)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "chroot failed: ", strerror(errno));
				return -1;
			}
			if (-1 == chdir("/")) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "chdir failed: ", strerror(errno));
				return -1;
			}
		}
#endif
#ifdef HAVE_PWD_H
		/* drop root privs */
		if (NULL != pwd) {
			if (-1 == setuid(pwd->pw_uid)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "setuid failed: ", strerror(errno));
				return -1;
			}
		}
#endif
#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
		/**
		 * on IRIX 6.5.30 they have prctl() but no DUMPABLE
		 */
		if (srv->srvconf.enable_cores) {
			prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
		}
#endif
	} else {

#ifdef HAVE_GETRLIMIT
		if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
			log_error_write(srv, __FILE__, __LINE__,
					"ss", "couldn't get 'max filedescriptors'",
					strerror(errno));
			return -1;
		}

		/**
		 * we are not root can can't increase the fd-limit, but we can reduce it
		 */
		if (srv->srvconf.max_fds && srv->srvconf.max_fds < rlim.rlim_cur) {
			/* set rlimits */

			rlim.rlim_cur = srv->srvconf.max_fds;

			if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
				log_error_write(srv, __FILE__, __LINE__,
						"ss", "couldn't set 'max filedescriptors'",
						strerror(errno));
				return -1;
			}
		}

		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
			srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
		} else {
			srv->max_fds = rlim.rlim_cur;
		}

		/* set core file rlimit, if enable_cores is set */
		if (srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
			rlim.rlim_cur = rlim.rlim_max;
			setrlimit(RLIMIT_CORE, &rlim);
		}

#endif
		if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
			/* don't raise the limit above FD_SET_SIZE */
			if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"can't raise max filedescriptors above",  FD_SETSIZE - 200,
						"if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
				return -1;
			}
		}

		if (0 != network_init(srv)) {
			plugins_free(srv);
			server_free(srv);

			return -1;
		}
	}

	/* set max-conns */
	if (srv->srvconf.max_conns > srv->max_fds/2) {
		/* we can't have more connections than max-fds/2 */
		log_error_write(srv, __FILE__, __LINE__, "sdd", "can't have more connections than fds/2: ", srv->srvconf.max_conns, srv->max_fds);
		srv->max_conns = srv->max_fds/2;
	} else if (srv->srvconf.max_conns) {
		/* otherwise respect the wishes of the user */
		srv->max_conns = srv->srvconf.max_conns;
	} else {
		/* or use the default: we really don't want to hit max-fds */
		srv->max_conns = srv->max_fds/3;
	}
	
	if (HANDLER_GO_ON != plugins_call_init(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");

		plugins_free(srv);
		network_close(srv);
		server_free(srv);

		return -1;
	}

#ifdef HAVE_FORK
	/* network is up, let's deamonize ourself */
	if (srv->srvconf.dont_daemonize == 0) daemonize();
#endif


#ifdef HAVE_SIGACTION
	memset(&act, 0, sizeof(act));
	act.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &act, NULL);
	sigaction(SIGUSR1, &act, NULL);
# if defined(SA_SIGINFO)
	act.sa_sigaction = sigaction_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = SA_SIGINFO;
# else
	act.sa_handler = signal_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
# endif
	sigaction(SIGINT,  &act, NULL);
	sigaction(SIGTERM, &act, NULL);
	sigaction(SIGHUP,  &act, NULL);
	sigaction(SIGALRM, &act, NULL);
	sigaction(SIGCHLD, &act, NULL);

#elif defined(HAVE_SIGNAL)
	/* ignore the SIGPIPE from sendfile() */
	signal(SIGPIPE, SIG_IGN);
	signal(SIGUSR1, SIG_IGN);
	signal(SIGALRM, signal_handler);
	signal(SIGTERM, signal_handler);
	signal(SIGHUP,  signal_handler);
	signal(SIGCHLD,  signal_handler);
	signal(SIGINT,  signal_handler);
#endif

#if EMBEDDED_EANBLE
	sigset_t sigs_to_catch;	

	/* set the signal handler */ 
	sigemptyset(&sigs_to_catch); 
	sigaddset(&sigs_to_catch, SIGTERM);
	sigaddset(&sigs_to_catch, SIGUSR2);   
	sigprocmask(SIG_UNBLOCK, &sigs_to_catch, NULL);
	signal(SIGTERM, sigaction_handler);

	//- 20121108 Sungmin add
	signal(SIGUSR2, sigaction_handler);
#endif

#ifdef USE_ALARM
	signal(SIGALRM, signal_handler);

	/* setup periodic timer (1 second) */
	if (setitimer(ITIMER_REAL, &interval, NULL)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
		return -1;
	}

	getitimer(ITIMER_REAL, &interval);
#endif


	srv->gid = getgid();
	srv->uid = getuid();

	/* write pid file */
	if (pid_fd != -1) {
		buffer_copy_int(srv->tmp_buf, getpid());
		buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("\n"));
		if (-1 == write_all(pid_fd, CONST_BUF_LEN(srv->tmp_buf))) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "Couldn't write pid file:", strerror(errno));
			close(pid_fd);
			return -1;
		}
		close(pid_fd);
		pid_fd = -1;
	}

	/* Close stderr ASAP in the child process to make sure that nothing
	 * is being written to that fd which may not be valid anymore. */
	if (-1 == log_error_open(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down.");

		plugins_free(srv);
		network_close(srv);
		server_free(srv);
		return -1;
	}
	
	//- Sungmin add	
	if (-1 == log_sys_open(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "Opening syslog failed. Going down.");

		plugins_free(srv);
		network_close(srv);
		server_free(srv);
		return -1;
	}

	#if EMBEDDED_EANBLE
	#ifndef APP_IPKG
	buffer_copy_string( srv->last_login_info, nvram_get_webdav_last_login_info() );
	buffer_copy_string( srv->cur_login_info, nvram_get_webdav_last_login_info() );
	#else
	char *last_login_info = nvram_get_webdav_last_login_info();
	fprintf(stderr,"last_login_info=%s\n",last_login_info);
	if(last_login_info == NULL || *last_login_info == '(')
	{
		fprintf(stderr,"111\n");
	}
	else
	{
		buffer_copy_string( srv->last_login_info, last_login_info);
		buffer_copy_string( srv->cur_login_info, last_login_info);
		free(last_login_info);
	}
	#endif
	#else
	buffer_copy_string( srv->last_login_info, "admin>2012/08/08 18:28:28>100.100.100.100" );
	buffer_copy_string( srv->cur_login_info, "admin>2012/08/08 18:28:28>100.100.100.100" );
	#endif
	//////////////////////////////////////////////////////////////////////////////////////////
	
	if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
		log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
		
		plugins_free(srv);
		network_close(srv);
		server_free(srv);

		return -1;
	}
	
	/* dump unused config-keys */
	for (i = 0; i < srv->config_context->used; i++) {
		array *config = ((data_config *)srv->config_context->data[i])->value;
		size_t j;

		for (j = 0; config && j < config->used; j++) {
			data_unset *du = config->data[j];

			/* all var.* is known as user defined variable */
			if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
				continue;
			}

			if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
				log_error_write(srv, __FILE__, __LINE__, "sbs",
						"WARNING: unknown config-key:",
						du->key,
						"(ignored)");
			}
		}
	}

	if (srv->config_unsupported) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"Configuration contains unsupported keys. Going down.");
	}

	if (srv->config_deprecated) {
		log_error_write(srv, __FILE__, __LINE__, "s",
				"Configuration contains deprecated keys. Going down.");
	}

	if (srv->config_unsupported || srv->config_deprecated) {
		plugins_free(srv);
		network_close(srv);
		server_free(srv);

		return -1;
	}


#ifdef HAVE_FORK
	/* start watcher and workers */
	num_childs = srv->srvconf.max_worker;
	if (num_childs > 0) {
		int child = 0;
		while (!child && !srv_shutdown && !graceful_shutdown) {
			if (num_childs > 0) {
				switch (fork()) {
				case -1:
					return -1;
				case 0:
					child = 1;
					break;
				default:
					num_childs--;
					break;
				}
			} else {
				int status;

				if (-1 != wait(&status)) {
					/** 
					 * one of our workers went away 
					 */
					num_childs++;
				} else {
					switch (errno) {
					case EINTR:
						/**
						 * if we receive a SIGHUP we have to close our logs ourself as we don't 
						 * have the mainloop who can help us here
						 */
						if (handle_sig_hup) {
							handle_sig_hup = 0;

							log_error_cycle(srv);

							/**
							 * forward to all procs in the process-group
							 * 
							 * we also send it ourself
							 */
							if (!forwarded_sig_hup) {
								forwarded_sig_hup = 1;
								kill(0, SIGHUP);
							}
						}
						break;
					default:
						break;
					}
				}
			}
		}

		/**
		 * for the parent this is the exit-point 
		 */
		if (!child) {
			/** 
			 * kill all children too 
			 */
			if (graceful_shutdown) {
				kill(0, SIGINT);
			} else if (srv_shutdown) {
				kill(0, SIGTERM);
			}

			log_error_close(srv);
			network_close(srv);
			connections_free(srv);
			plugins_free(srv);
			server_free(srv);
			return 0;
		}
	}
#endif

	if (NULL == (srv->ev = fdevent_init(srv, srv->max_fds + 1, srv->event_handler))) {
		log_error_write(srv, __FILE__, __LINE__,
				"s", "fdevent_init failed");
		return -1;
	}

	/* libev backend overwrites our SIGCHLD handler and calls waitpid on SIGCHLD; we want our own SIGCHLD handling. */
#ifdef HAVE_SIGACTION
	sigaction(SIGCHLD, &act, NULL);
#elif defined(HAVE_SIGNAL)
	signal(SIGCHLD,  signal_handler);
#endif

	/*
	 * kqueue() is called here, select resets its internals,
	 * all server sockets get their handlers
	 *
	 * */
	if (0 != network_register_fdevents(srv)) {
		plugins_free(srv);
		network_close(srv);
		server_free(srv);

		return -1;
	}

	/* might fail if user is using fam (not gamin) and famd isn't running */
	if (NULL == (srv->stat_cache = stat_cache_init())) {
		log_error_write(srv, __FILE__, __LINE__, "s",
			"stat-cache could not be setup, dieing.");
		return -1;
	}

#ifdef HAVE_FAM_H
	/* setup FAM */
	if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
		if (0 != FAMOpen2(&srv->stat_cache->fam, "lighttpd")) {
			log_error_write(srv, __FILE__, __LINE__, "s",
					 "could not open a fam connection, dieing.");
			return -1;
		}
#ifdef HAVE_FAMNOEXISTS
		FAMNoExists(&srv->stat_cache->fam);
#endif

		fdevent_register(srv->ev, FAMCONNECTION_GETFD(&srv->stat_cache->fam), stat_cache_handle_fdevent, NULL);
		fdevent_event_set(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(&srv->stat_cache->fam), FDEVENT_IN);
	}
#endif


	/* get the current number of FDs */
	srv->cur_fds = open("/dev/null", O_RDONLY);
	close(srv->cur_fds);

	for (i = 0; i < srv->srv_sockets.used; i++) {
		server_socket *srv_socket = srv->srv_sockets.ptr[i];
		if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno));
			return -1;
		}
	}

	/* main-loop */
	while (!srv_shutdown) {
		int n;
		size_t ndx;
		time_t min_ts;

		if (handle_sig_hup) {
			handler_t r;

			/* reset notification */
			handle_sig_hup = 0;


			/* cycle logfiles */

			switch(r = plugins_call_handle_sighup(srv)) {
			case HANDLER_GO_ON:
				break;
			default:
				log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
				break;
			}

			if (-1 == log_error_cycle(srv)) {
				log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");

				return -1;
			} else {
#ifdef HAVE_SIGACTION
				log_error_write(srv, __FILE__, __LINE__, "sdsd", 
					"logfiles cycled UID =",
					last_sighup_info.si_uid,
					"PID =",
					last_sighup_info.si_pid);
#else
				log_error_write(srv, __FILE__, __LINE__, "s", 
					"logfiles cycled");
#endif
			}
		}

		if (handle_sig_alarm) {
			/* a new second */

#ifdef USE_ALARM
			/* reset notification */
			handle_sig_alarm = 0;
#endif

			/* get current time */
			min_ts = time(NULL);

			if (min_ts != srv->cur_ts) {
#ifdef DEBUG_CONNECTION_STATES
				int cs = 0;
#endif
				connections *conns = srv->conns;
				handler_t r;

				switch(r = plugins_call_handle_trigger(srv)) {
				case HANDLER_GO_ON:
					break;
				case HANDLER_ERROR:
					log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed");
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "d", r);
					break;
				}

				/* trigger waitpid */
				srv->cur_ts = min_ts;

				/* cleanup stat-cache */
				stat_cache_trigger_cleanup(srv);
				/**
				 * check all connections for timeouts
				 *
				 */
				for (ndx = 0; ndx < conns->used; ndx++) {
					int changed = 0;
					connection *con;
					int t_diff;

					con = conns->ptr[ndx];

					if (con->state == CON_STATE_READ ||
					    con->state == CON_STATE_READ_POST) {
						if (con->request_count == 1 || con->state == CON_STATE_READ_POST) {
							if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
								/* time - out */
								if (con->conf.log_request_handling) {
									log_error_write(srv, __FILE__, __LINE__, "sd",
										"connection closed - read timeout:", con->fd);
								}

								connection_set_state(srv, con, CON_STATE_ERROR);
								changed = 1;
							}
						} else {
							if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) {
								/* time - out */
								if (con->conf.log_request_handling) {
									log_error_write(srv, __FILE__, __LINE__, "sd",
										"connection closed - keep-alive timeout:", con->fd);
								}

								connection_set_state(srv, con, CON_STATE_ERROR);
								changed = 1;
							}
						}
					}

					if ((con->state == CON_STATE_WRITE) &&
					    (con->write_request_ts != 0)) {
#if 0
						if (srv->cur_ts - con->write_request_ts > 60) {
							log_error_write(srv, __FILE__, __LINE__, "sdd",
									"connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
						}
#endif

						if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
							/* time - out */
							if (con->conf.log_timeouts) {
								log_error_write(srv, __FILE__, __LINE__, "sbsosds",
									"NOTE: a request for",
									con->request.uri,
									"timed out after writing",
									con->bytes_written,
									"bytes. We waited",
									(int)con->conf.max_write_idle,
									"seconds. If this a problem increase server.max-write-idle");
							}
							connection_set_state(srv, con, CON_STATE_ERROR);
							changed = 1;
						}
					}

					if (con->state == CON_STATE_CLOSE && (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT)) {
						changed = 1;
					}

					/* we don't like div by zero */
					if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;

					if (con->traffic_limit_reached &&
					    (con->conf.kbytes_per_second == 0 ||
					     ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
						/* enable connection again */
						con->traffic_limit_reached = 0;

						changed = 1;
					}

					if (changed) {
						connection_state_machine(srv, con);
					}
					con->bytes_written_cur_second = 0;
					*(con->conf.global_bytes_per_second_cnt_ptr) = 0;

#if DEBUG_CONNECTION_STATES
					if (cs == 0) {
						fprintf(stderr, "connection-state: ");
						cs = 1;
					}

					fprintf(stderr, "c[%d,%d]: %s ",
						con->fd,
						con->fcgi.fd,
						connection_get_state(con->state));
#endif
				}

#ifdef DEBUG_CONNECTION_STATES
				if (cs == 1) fprintf(stderr, "\n");
#endif
			}
		}

		if (srv->sockets_disabled) {
			/* our server sockets are disabled, why ? */

			if ((srv->cur_fds + srv->want_fds < srv->max_fds * 8 / 10) && /* we have enough unused fds */
			    (srv->conns->used <= srv->max_conns * 9 / 10) &&
			    (0 == graceful_shutdown)) {
				for (i = 0; i < srv->srv_sockets.used; i++) {
					server_socket *srv_socket = srv->srv_sockets.ptr[i];
					fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
				}

				log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");

				srv->sockets_disabled = 0;
			}
		} else {
			if ((srv->cur_fds + srv->want_fds > srv->max_fds * 9 / 10) || /* out of fds */
			    (srv->conns->used >= srv->max_conns) || /* out of connections */
			    (graceful_shutdown)) { /* graceful_shutdown */

				/* disable server-fds */

				for (i = 0; i < srv->srv_sockets.used; i++) {
					server_socket *srv_socket = srv->srv_sockets.ptr[i];
					fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);

					if (graceful_shutdown) {
						/* we don't want this socket anymore,
						 *
						 * closing it right away will make it possible for
						 * the next lighttpd to take over (graceful restart)
						 *  */

						fdevent_unregister(srv->ev, srv_socket->fd);
						close(srv_socket->fd);
						srv_socket->fd = -1;

						/* network_close() will cleanup after us */

						if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
						    buffer_string_is_empty(srv->srvconf.changeroot)) {
							if (0 != unlink(srv->srvconf.pid_file->ptr)) {
								if (errno != EACCES && errno != EPERM) {
									log_error_write(srv, __FILE__, __LINE__, "sbds",
											"unlink failed for:",
											srv->srvconf.pid_file,
											errno,
											strerror(errno));
								}
							}
						}
					}
				}

				if (graceful_shutdown) {
					log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
				} else if (srv->conns->used >= srv->max_conns) {
					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
				} else {
					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
				}

				srv->sockets_disabled = 1;
			}
		}

		if (graceful_shutdown && srv->conns->used == 0) {
			/* we are in graceful shutdown phase and all connections are closed
			 * we are ready to terminate without harming anyone */
			srv_shutdown = 1;
		}

		/* we still have some fds to share */
		if (srv->want_fds) {
			/* check the fdwaitqueue for waiting fds */
			int free_fds = srv->max_fds - srv->cur_fds - 16;
			connection *con;

			for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
				connection_state_machine(srv, con);

				srv->want_fds--;
			}
		}

		if ((n = fdevent_poll(srv->ev, 1000)) > 0) {
			/* n is the number of events */
			int revents;
			int fd_ndx;
#if 0
			if (n > 0) {
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"polls:", n);
			}
#endif
			fd_ndx = -1;
			do {
				fdevent_handler handler;
				void *context;
				handler_t r;

				fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);
				if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */

				revents = fdevent_event_get_revent (srv->ev, fd_ndx);
				fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);
				handler = fdevent_get_handler(srv->ev, fd);
				context = fdevent_get_context(srv->ev, fd);

				/* connection_handle_fdevent needs a joblist_append */
#if 0
				log_error_write(srv, __FILE__, __LINE__, "sdd",
						"event for", fd, revents);
#endif
				switch (r = (*handler)(srv, context, revents)) {
				case HANDLER_FINISHED:
				case HANDLER_GO_ON:
				case HANDLER_WAIT_FOR_EVENT:
				case HANDLER_WAIT_FOR_FD:
					break;
				case HANDLER_ERROR:
					/* should never happen */
					SEGFAULT();
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "d", r);
					break;
				}
			} while (--n > 0);
		} else if (n < 0 && errno != EINTR) {
			log_error_write(srv, __FILE__, __LINE__, "ss",
					"fdevent_poll failed:",
					strerror(errno));
		}

		for (ndx = 0; ndx < srv->joblist->used; ndx++) {
			connection *con = srv->joblist->ptr[ndx];
			handler_t r;

			connection_state_machine(srv, con);

			switch(r = plugins_call_handle_joblist(srv, con)) {
			case HANDLER_FINISHED:
			case HANDLER_GO_ON:
				break;
			default:
				log_error_write(srv, __FILE__, __LINE__, "d", r);
				break;
			}

			con->in_joblist = 0;
		}

		srv->joblist->used = 0;
	}

	if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
	    buffer_string_is_empty(srv->srvconf.changeroot) &&
	    0 == graceful_shutdown) {
		if (0 != unlink(srv->srvconf.pid_file->ptr)) {
			if (errno != EACCES && errno != EPERM) {
				log_error_write(srv, __FILE__, __LINE__, "sbds",
						"unlink failed for:",
						srv->srvconf.pid_file,
						errno,
						strerror(errno));
			}
		}
	}

#ifdef HAVE_SIGACTION
	log_error_write(srv, __FILE__, __LINE__, "sdsd", 
			"server stopped by UID =",
			last_sigterm_info.si_uid,
			"PID =",
			last_sigterm_info.si_pid);
#else
	log_error_write(srv, __FILE__, __LINE__, "s", 
			"server stopped");
#endif

	/* clean-up */
	log_error_close(srv);
	network_close(srv);
	connections_free(srv);
	plugins_free(srv);
	server_free(srv);

	return 0;
}
Esempio n. 16
0
/**
 * Initializes a ssl connection for server use.
 * @param pemfilename Filename for the key/cert file
 * @return An ssl connection, or NULL if an error occured.
 */
ssl_server_connection *init_ssl_server (char *pemfile, char *clientpemfile) {

#ifdef HAVE_OPENSSL

    ssl_server_connection *ssl_server = new_ssl_server_connection(pemfile,
                                        clientpemfile);

    ASSERT(pemfile);

    if (!ssl_initilized) {

        start_ssl();

    }

    if ((ssl_server->method= SSLv23_server_method()) == NULL ) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server (): Cannot initialize the SSL method!\n", prog);
        goto sslerror;

    }

    if ((ssl_server->ctx= SSL_CTX_new(ssl_server->method)) == NULL ) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server (): Cannot initialize SSL server"
            " certificate handler!\n"
            , prog);
        goto sslerror;

    }

    if (SSL_CTX_use_certificate_file(ssl_server->ctx, pemfile,
                                     SSL_FILETYPE_PEM) <= 0) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server(): Cannot initialize SSL server"
            " certificate!\n", prog);
        goto sslerror;

    }

    if (SSL_CTX_use_PrivateKey_file(ssl_server->ctx, pemfile,
                                    SSL_FILETYPE_PEM) <= 0) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server(): Cannot initialize SSL server"
            " private key!\n", prog);
        goto sslerror;

    }

    if (!SSL_CTX_check_private_key(ssl_server->ctx)) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server(): The private key does not match the"
            " certificate public key!\n", prog);
        goto sslerror;

    }

    /*
     * We need this to force transmission of client certs
     */
    if (!verify_init(ssl_server)) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server(): Verification engine was not"
            " properly initilized!\n", prog);
        goto sslerror;

    }

    if (ssl_server->clientpemfile != NULL) {

        verify_info(ssl_server);

    }

    return ssl_server;

sslerror:

    cleanup_ssl_server_socket(ssl_server);
    return NULL;

#else

    return NULL;

#endif

}
Esempio n. 17
0
/**
 * Embeds a socket in a ssl connection.
 * @param socket the socket to be used.
 * @return The ssl connection or NULL if an error occured.
 */
int embed_ssl_socket(ssl_connection *ssl, int socket) {
        int ssl_error;
        time_t ssl_time;

        if (!ssl)
                return FALSE;

        if (!ssl_initialized)
                start_ssl();

        if (socket >= 0) {
                ssl->socket = socket;
        } else {
                LogError("SSL socket error\n");
                goto sslerror;
        }

        if ((ssl->handler = SSL_new (ssl->ctx)) == NULL) {
                LogError("Cannot initialize the SSL handler -- %s\n", SSLERROR);
                goto sslerror;
        }

        if (SSL_CTX_set_cipher_list(ssl->ctx, CIPHER_LIST) != 1) {
                LogError("Error setting cipher list '%s' (no valid ciphers)\n", CIPHER_LIST);
                goto sslerror;
        }

        Net_setNonBlocking(ssl->socket);

        if ((ssl->socket_bio = BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) {
                LogError("Cannot create IO buffer -- %s\n", SSLERROR);
                goto sslerror;
        }

        SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio);
        ssl_time = time(NULL);

        while ((ssl_error = SSL_connect (ssl->handler)) < 0) {
                if ((time(NULL) - ssl_time) > SSL_TIMEOUT) {
                        LogError("SSL service timeout\n");
                        goto sslerror;
                }

                if (!handle_error(ssl_error, ssl))
                        goto sslerror;

                if (!BIO_should_retry(ssl->socket_bio))
                        goto sslerror;
        }

        ssl->cipher = (char *) SSL_get_cipher(ssl->handler);

        if (! update_ssl_cert_data(ssl)) {
                LogError("Cannot get the SSL server certificate\n");
                goto sslerror;
        }

        return TRUE;

sslerror:
        cleanup_ssl_socket(ssl);
        return FALSE;
}
Esempio n. 18
0
/**
 * Embeds a socket in a ssl connection.
 * @param socket the socket to be used.
 * @return The ssl connection or NULL if an error occured.
 */
int embed_ssl_socket (ssl_connection *ssl, int socket) {

#ifdef HAVE_OPENSSL

    int ssl_error;
    time_t ssl_time;

    if ( ssl == NULL ) {

        return FALSE;

    }

    if (!ssl_initilized) {

        start_ssl();

    }

    if ( socket >= 0 ) {

        ssl->socket= socket;

    } else {

        log("%s: embed_ssl_socket (): Socket error!\n", prog);
        goto sslerror;
    }

    if ((ssl->handler= SSL_new (ssl->ctx)) == NULL ) {

        handle_ssl_error("embed_ssl_socket()");
        log("%s: embed_ssl_socket (): Cannot initialize the SSL handler!\n",
            prog);
        goto sslerror;

    }

    set_noblock(ssl->socket);

    if((ssl->socket_bio= BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) {

        handle_ssl_error("embed_ssl_socket()");
        log("%s: embed_ssl_socket (): Cannot generate IO buffer!\n", prog);
        goto sslerror;

    }

    SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio);

    ssl_time=time(NULL);

    while((ssl_error= SSL_connect (ssl->handler)) < 0) {

        if((time(NULL)-ssl_time) > SSL_TIMEOUT) {

            log("%s: embed_ssl_socket (): SSL service timeout!\n",
                prog);
            goto sslerror;

        }

        if (!handle_connection_error(ssl_error, ssl, "embed_ssl_socket()", SSL_TIMEOUT)) {

            goto sslerror;

        }

        if (!BIO_should_retry(ssl->socket_bio)) {

            goto sslerror;

        }


    }

    ssl->cipher= (char *) SSL_get_cipher(ssl->handler);

    if (! update_ssl_cert_data(ssl)) {

        log("%s: embed_ssl_socket (): Cannot get the SSL server certificate!\n",
            prog);
        goto sslerror;

    }

    return TRUE;

sslerror:

    cleanup_ssl_socket(ssl);
    return FALSE;

#else

    return FALSE;

#endif
}
Esempio n. 19
0
/**
 * Generate a new ssl connection
 * @return ssl connection container
 */
ssl_connection *new_ssl_connection(char *clientpemfile, int sslversion) {

#ifdef HAVE_OPENSSL

    ssl_connection *ssl = (ssl_connection *) NEW(ssl);

    if (!ssl_initilized) {

        start_ssl();

    }

    ssl->socket_bio= NULL;
    ssl->handler= NULL;
    ssl->cert= NULL;
    ssl->cipher= NULL;
    ssl->socket= 0;
    ssl->next = NULL;
    ssl->accepted = FALSE;
    ssl->cert_md5 = NULL;
    ssl->cert_md5_len = 0;

    if(clientpemfile!=NULL) {

        ssl->clientpemfile= xstrdup(clientpemfile);

    } else {

        ssl->clientpemfile= NULL;

    }

    switch (sslversion) {

    case SSL_VERSION_AUTO:

        ssl->method = SSLv23_client_method();
        break;

    case SSL_VERSION_SSLV2:

        ssl->method = SSLv2_client_method();
        break;

    case SSL_VERSION_SSLV3:

        ssl->method = SSLv3_client_method();
        break;

    case SSL_VERSION_TLS:

        ssl->method = TLSv1_client_method();
        break;

    default:

        log("%s: new_ssl_connection(): Unknown SSL version!\n", prog);
        goto sslerror;

    }

    if (ssl->method == NULL ) {

        handle_ssl_error("new_ssl_connection()");
        log("%s: new_ssl_connection(): Cannot initilize SSL method!\n", prog);
        goto sslerror;

    }

    if ((ssl->ctx= SSL_CTX_new (ssl->method)) == NULL ) {

        handle_ssl_error("new_ssl_connection()");
        log("%s: new_ssl_connection(): Cannot initilize SSL server certificate"
            " handler!\n", prog);
        goto sslerror;

    }

    if ( ssl->clientpemfile!=NULL ) {

        if (SSL_CTX_use_certificate_file(ssl->ctx, ssl->clientpemfile,
                                         SSL_FILETYPE_PEM) <= 0) {

            handle_ssl_error("new_ssl_connection()");
            log("%s: new_ssl_connection(): Cannot initilize SSL server"
                " certificate!\n", prog);
            goto sslerror;

        }

        if (SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->clientpemfile,
                                        SSL_FILETYPE_PEM) <= 0) {

            handle_ssl_error("new_ssl_connection()");
            log("%s: new_ssl_connection(): Cannot initilize SSL server"
                " private key!\n", prog);
            goto sslerror;

        }

        if (!SSL_CTX_check_private_key(ssl->ctx)) {

            handle_ssl_error("new_ssl_connection()");
            log("%s: new_ssl_connection(): Private key does not match the"
                " certificate public key!\n",
                prog);
            goto sslerror;

        }

    }


    return ssl;

sslerror:

    delete_ssl_socket(ssl);

    return NULL;

#else

    return NULL;

#endif

}
Esempio n. 20
0
/**
 * Embeds an accepted server socket in an existing ssl connection.
 * @param ssl ssl connection
 * @param socket the socket to be used.
 * @return TRUE, or FALSE if an error has occured.
 */
int embed_accepted_ssl_socket(ssl_connection *ssl, int socket) {

#ifdef HAVE_OPENSSL

    int ssl_error;
    time_t ssl_time;

    ASSERT(ssl);

    ssl->socket=socket;

    if(!ssl_initilized) {

        start_ssl();

    }

    if((ssl->handler= SSL_new(ssl->ctx)) == NULL) {

        handle_ssl_error("embed_accepted_ssl_socket()");
        log("%s: embed_accepted_ssl_socket(): Cannot initialize the"
            " SSL handler!\n", prog);
        goto sslerror;

    }

    if(socket < 0) {

        log("Socket error!\n");
        goto sslerror;

    }

    set_noblock(ssl->socket);

    if((ssl->socket_bio= BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) {

        handle_ssl_error("embed_accepted_ssl_socket()");
        log("%s: embed_accepted_ssl_socket(): Cannot generate IO buffer!\n",
            prog);
        goto sslerror;

    }

    SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio);

    ssl_time= time(NULL);

    while((ssl_error= SSL_accept(ssl->handler)) < 0) {

        if((time(NULL)-ssl_time) > SSL_TIMEOUT) {

            log("%s: embed_accepted_ssl_socket(): SSL service timeout!\n",
                prog);
            goto sslerror;

        }

        if (!handle_connection_error(ssl_error, ssl,
                                     "embed_accepted_ssl_socket()", SSL_TIMEOUT)) {

            goto sslerror;

        }

        if (!BIO_should_retry(ssl->socket_bio)) {

            goto sslerror;

        }

    }

    ssl->cipher= (char *) SSL_get_cipher(ssl->handler);

    if(!update_ssl_cert_data(ssl) && (ssl->clientpemfile != NULL)) {

        log("%s: The client did not supply a required client certificate!\n",
            prog);
        goto sslerror;

    }

    if (SSL_get_verify_result(ssl->handler)>0) {

        log("%s: Verification of the certificate has failed!\n",
            prog);
        goto sslerror;

    }

    return TRUE;

sslerror:

    return FALSE;

#else

    return FALSE;

#endif

}