void ssl_lock(int mode, int n, const char *file, int line);
-/*
- * OpenSSL wants a callback function to identify the currently running thread.
- * Since we are a pthreads program, we convert the output of pthread_self() to a long.
- */
-static unsigned long id_callback(void)
-{
+// OpenSSL wants a callback function to identify the currently running thread.
+// Since we are a pthreads program, we convert the output of pthread_self() to a long.
+static unsigned long id_callback(void) {
return (unsigned long) pthread_self();
}
-/*
- * OpenSSL wants a callback function to set and clear various types of locks.
- * Since we are a pthreads program, we use mutexes.
- */
-void ssl_lock(int mode, int n, const char *file, int line)
-{
+// OpenSSL wants a callback function to set and clear various types of locks.
+// Since we are a pthreads program, we use mutexes.
+void ssl_lock(int mode, int n, const char *file, int line) {
if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(SSLCritters[n]);
- } else {
+ }
+ else {
pthread_mutex_unlock(SSLCritters[n]);
}
}
/*
* Generate a private key for SSL
*/
-void generate_key(char *keyfilename)
-{
+void generate_key(char *keyfilename) {
int ret = 0;
RSA *rsa = NULL;
BIGNUM *bne = NULL;
fp = fopen(keyfilename, "w");
if (fp != NULL) {
chmod(keyfilename, 0600);
- if (PEM_write_RSAPrivateKey(fp, /* the file */
- rsa, /* the key */
- NULL, /* no enc */
- NULL, /* no passphr */
- 0, /* no passphr */
- NULL, /* no callbk */
- NULL /* no callbk */
- ) != 1) {
+ if (PEM_write_RSAPrivateKey(fp, // the file */
+ rsa, // the key */
+ NULL, // no enc */
+ NULL, // no passphrase
+ 0, // no passphrase
+ NULL, // no callback
+ NULL // no callbk
+ ) != 1) {
syslog(LOG_ERR, "crypto: cannot write key: %s", ERR_reason_error_string(ERR_get_error()));
unlink(keyfilename);
}
}
-/*
- * Initialize ssl engine, load certs and initialize openssl internals
- */
-void init_ssl(void)
-{
+// Initialize ssl engine, load certs and initialize openssl internals
+void init_ssl(void) {
const SSL_METHOD *ssl_method;
RSA *rsa = NULL;
X509_REQ *req = NULL;
if (!SSLCritters) {
syslog(LOG_ERR, "citserver: can't allocate memory!!");
exit(1);
- } else {
+ }
+ else {
int a;
for (a = 0; a < CRYPTO_num_locks(); a++) {
SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
}
}
- /*
- * Initialize SSL transport layer
- */
+ // Initialize SSL transport layer
SSL_library_init();
SSL_load_error_strings();
ssl_method = SSLv23_server_method();
CRYPTO_set_locking_callback(ssl_lock);
CRYPTO_set_id_callback(id_callback);
- /*
- * Get our certificates in order.
- * First, create the key/cert directory if it's not there already...
- */
+ // Get our certificates in order.
+ // First, create the key/cert directory if it's not there already...
mkdir(CTDL_CRYPTO_DIR, 0700);
- /*
- * If we still don't have a private key, generate one.
- */
+ // If we still don't have a private key, generate one.
generate_key(CTDL_KEY_PATH);
- /*
- * If there is no certificate file on disk, we will be generating a self-signed certificate
- * in the next step. Therefore, if we have neither a CSR nor a certificate, generate
- * the CSR in this step so that the next step may commence.
- */
+ // If there is no certificate file on disk, we will be generating a self-signed certificate
+ // in the next step. Therefore, if we have neither a CSR nor a certificate, generate
+ // the CSR in this step so that the next step may commence.
if ((access(CTDL_CER_PATH, R_OK) != 0) && (access(CTDL_CSR_PATH, R_OK) != 0)) {
syslog(LOG_INFO, "Generating a certificate signing request.");
/* Sign the CSR */
if (!X509_REQ_sign(req, pk, EVP_md5())) {
syslog(LOG_WARNING, "X509_REQ_sign(): error");
- } else {
+ }
+ else {
/* Write it to disk. */
fp = fopen(CTDL_CSR_PATH, "w");
if (fp != NULL) {
chmod(CTDL_CSR_PATH, 0600);
PEM_write_X509_REQ(fp, req);
fclose(fp);
- } else {
+ }
+ else {
syslog(LOG_WARNING, "Cannot write key: %s", CTDL_CSR_PATH);
exit(1);
}
}
}
RSA_free(rsa);
- } else {
+ }
+ else {
syslog(LOG_WARNING, "Unable to read private key.");
}
}
/* Sign the cert */
if (!X509_sign(cer, pk, EVP_md5())) {
syslog(LOG_WARNING, "X509_sign(): error");
- } else { /* Write it to disk. */
+ }
+ else { /* Write it to disk. */
fp = fopen(CTDL_CER_PATH, "w");
if (fp != NULL) {
chmod(CTDL_CER_PATH, 0600);
PEM_write_X509(fp, cer);
fclose(fp);
- } else {
+ }
+ else {
syslog(LOG_WARNING, "Cannot write key: %s", CTDL_CER_PATH);
exit(1);
}
/*
* starts SSL/TLS encryption for the current session.
*/
-void starttls(struct client_handle *ch)
-{
+void starttls(struct client_handle *ch) {
int retval, bits, alg_bits;
if (!ssl_ctx) {
ssl_error_reason = ERR_reason_error_string(ERR_get_error());
if (ssl_error_reason == NULL) {
syslog(LOG_WARNING, "SSL_accept failed: errval=%ld, retval=%d %s", errval, retval, strerror(errval));
- } else {
+ }
+ else {
syslog(LOG_WARNING, "SSL_accept failed: %s\n", ssl_error_reason);
}
sleep(1);
ssl_error_reason = ERR_reason_error_string(ERR_get_error());
if (ssl_error_reason == NULL) {
syslog(LOG_WARNING, "SSL_accept failed: errval=%ld, retval=%d (%s)", errval, retval, strerror(errval));
- } else {
+ }
+ else {
syslog(LOG_WARNING, "SSL_accept failed: %s", ssl_error_reason);
}
SSL_free(ch->ssl_handle);
ch->ssl_handle = NULL;
return;
- } else {
+ }
+ else {
syslog(LOG_INFO, "SSL_accept success");
}
bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(ch->ssl_handle), &alg_bits);
/*
* shuts down the TLS connection
*/
-void endtls(struct client_handle *ch)
-{
+void endtls(struct client_handle *ch) {
syslog(LOG_INFO, "Ending SSL/TLS");
if (ch->ssl_handle != NULL) {
SSL_shutdown(ch->ssl_handle);
/*
* Send binary data to the client encrypted.
*/
-int client_write_ssl(struct client_handle *ch, char *buf, int nbytes)
-{
+int client_write_ssl(struct client_handle *ch, char *buf, int nbytes) {
int retval;
int nremain;
char junk[1];
/*
* read data from the encrypted layer.
*/
-int client_read_ssl(struct client_handle *ch, char *buf, int nbytes)
-{
+int client_read_ssl(struct client_handle *ch, char *buf, int nbytes) {
int bytes_read = 0;
int rlen = 0;
char junk[1];
#include "webcit.h"
-/*
- * Called from perform_request() to handle the /ctdl/s/ prefix -- always static content.
- */
-void output_static(struct http_transaction *h)
-{
+// Called from perform_request() to handle the /ctdl/s/ prefix -- always static content.
+void output_static(struct http_transaction *h) {
char filename[PATH_MAX];
struct stat statbuf;
h->response_body = malloc(h->response_body_length);
if (h->response_body != NULL) {
fread(h->response_body, h->response_body_length, 1, fp);
- } else {
+ }
+ else {
h->response_body_length = 0;
}
fclose(fp); // Content is now in memory.
<!-- Top container -->
<div id="navbar" class="w3-bar w3-top w3-black w3-large" style="z-index:4">
<button class="w3-bar-item w3-button w3-hide-large w3-hover-none w3-hover-text-light-grey" onclick="w3_open();"><i class="fa fa-bars"></i> Menu</button>
+ <span class="w3-left">
+ <span class="w3-bar-item" id="ctdl-logo">CITADEL</span>
+ </span>
+ <span class="w3-center">
+ <span id="ctdl_banner_title" class="w3-bar-item">XXX</span>
+ </span>
<span class="w3-right">
<button class="w3-bar-item w3-button" onclick="gotonext(0);">ungoto</button>
<button class="w3-bar-item w3-button" onclick="gotonext(1);">skip</button>
<button class="w3-bar-item w3-button" onclick="gotonext(2);">goto</button>
- <span id="ctdl_banner_title" class="w3-bar-item">XXX</span>
<span id="lilo" class="w3-bar-item">Login</span>
</span>
</div>
+ "</div>" // end avatar
+ "<div class=\"ctdl-msg-content\">" // begin content
+ "<div class=\"ctdl-msg-header\">" // begin header
- + "<span class=\"ctdl-username\"><a href=\"#\">" // FIXME link to user profile
+ + "<span class=\"ctdl-username\"><a href=\"#\">" // FIXME link to user profile
+ msg.from
- + "</a></span> "
+ + "</a></span>"
+ "<span class=\"ctdl-msgdate\">"
+ msg.time
- + "</span> "
+ + "</span>"
+ "</div>" // end header
+ "<div>" // begin body
+ msg.text
#include "webcit.h"
-/*
- * lingering_close() a`la Apache. see
- * http://httpd.apache.org/docs/2.0/misc/fin_wait_2.html for rationale
- */
-int lingering_close(int fd)
-{
+// lingering_close() a`la Apache. see
+// http://httpd.apache.org/docs/2.0/misc/fin_wait_2.html for rationale
+int lingering_close(int fd) {
char buf[SIZ];
int i;
fd_set set;
}
-/*
- * This is a generic function to set up a master socket for listening on
- * a TCP port. The server shuts down if the bind fails. (IPv4/IPv6 version)
- *
- * ip_addr IP address to bind
- * port_number port number to bind
- * queue_len number of incoming connections to allow in the queue
- */
-int webcit_tcp_server(const char *ip_addr, int port_number, int queue_len)
-{
+// This is a generic function to set up a master socket for listening on
+// a TCP port. The server shuts down if the bind fails. (IPv4/IPv6 version)
+//
+// ip_addr IP address to bind
+// port_number port number to bind
+// queue_len number of incoming connections to allow in the queue
+int webcit_tcp_server(const char *ip_addr, int port_number, int queue_len) {
const char *ipv4broadcast = "0.0.0.0";
int IsDefault = 0;
struct protoent *p;
int s, i, b;
int ip_version = 6;
- retry:
+retry:
memset(&sin6, 0, sizeof(sin6));
memset(&sin4, 0, sizeof(sin4));
sin6.sin6_family = AF_INET6;
sin4.sin_family = AF_INET;
- if ((ip_addr == NULL) /* any IPv6 */
- ||(IsEmptyStr(ip_addr))
- || (!strcmp(ip_addr, "*"))
- ) {
+ if ( (ip_addr == NULL) // any IPv6
+ || (IsEmptyStr(ip_addr))
+ || (!strcmp(ip_addr, "*"))
+ ) {
IsDefault = 1;
ip_version = 6;
sin6.sin6_addr = in6addr_any;
- } else if (!strcmp(ip_addr, "0.0.0.0")) { /* any IPv4 */
+ }
+ else if (!strcmp(ip_addr, "0.0.0.0")) { // any IPv4
ip_version = 4;
sin4.sin_addr.s_addr = INADDR_ANY;
- } else if ((strchr(ip_addr, '.')) && (!strchr(ip_addr, ':'))) { /* specific IPv4 */
+ }
+ else if ((strchr(ip_addr, '.')) && (!strchr(ip_addr, ':'))) { // specific IPv4
ip_version = 4;
if (inet_pton(AF_INET, ip_addr, &sin4.sin_addr) <= 0) {
syslog(LOG_WARNING, "Error binding to [%s] : %s\n", ip_addr, strerror(errno));
return (-1);
}
- } else { /* specific IPv6 */
+ }
+ else { // specific IPv6
ip_version = 6;
if (inet_pton(AF_INET6, ip_addr, &sin6.sin6_addr) <= 0) {
syslog(LOG_WARNING, "Can't create a listening socket: %s\n", strerror(errno));
return (-1);
}
- /* Set some socket options that make sense. */
+
+ // Set some socket options that make sense.
i = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
if (ip_version == 6) {
b = bind(s, (struct sockaddr *) &sin6, sizeof(sin6));
- } else {
+ }
+ else {
b = bind(s, (struct sockaddr *) &sin4, sizeof(sin4));
}
}
-/*
- * Create a Unix domain socket and listen on it
- * sockpath - file name of the unix domain socket
- * queue_len - Number of incoming connections to allow in the queue
- */
-int webcit_uds_server(char *sockpath, int queue_len)
-{
+// Create a Unix domain socket and listen on it
+// sockpath - file name of the unix domain socket
+// queue_len - Number of incoming connections to allow in the queue
+int webcit_uds_server(char *sockpath, int queue_len) {
struct sockaddr_un addr;
int s;
int i;
#include "webcit.h"
-/*
- * Convert a text/plain message to text/html
- */
-StrBuf *text2html(const char *supplied_charset, int treat_as_wiki, char *roomname, long msgnum, StrBuf * Source)
-{
+// Convert a text/plain message to text/html
+StrBuf *text2html(const char *supplied_charset, int treat_as_wiki, char *roomname, long msgnum, StrBuf * Source) {
StrBuf *sj = NULL;
sj = NewStrBuf();
}
-/*
- * Convert a text/x-citadel-variformat message to text/html
- */
-StrBuf *variformat2html(StrBuf * Source)
-{
+// Convert a text/x-citadel-variformat message to text/html
+StrBuf *variformat2html(StrBuf * Source) {
StrBuf *Target = NULL;
Target = NewStrBuf();
}
}
- /*
- * Quoted text should be displayed in italics and in a
- * different colour. This code understands Citadel-style
- * " >" quotes and will convert to <BLOCKQUOTE> tags.
- */
+ // Quoted text should be displayed in italics and in a
+ // different colour. This code understands Citadel-style
+ // " >" quotes and will convert to <BLOCKQUOTE> tags.
if (i > 0)
StrBufCutLeft(Line, i);
if (StrLength(Line) == 0)
continue;
- /* Activate embedded URL's */
+ // Activate embedded URL's
UrlizeText(Line1, Line, Line2);
StrEscAppend(Target, Line1, NULL, 0, 0);
#include "webcit.h"
-/*
- * Fetch a user photo (avatar)
- */
-void fetch_user_photo(struct http_transaction *h, struct ctdlsession *c, char *username)
-{
+// Fetch a user photo (avatar)
+void fetch_user_photo(struct http_transaction *h, struct ctdlsession *c, char *username) {
char buf[1024];
int content_length = 0;
char content_type[1024];
}
-/*
- * Fetch a user bio (profile)
- */
-void fetch_user_bio(struct http_transaction *h, struct ctdlsession *c, char *username)
-{
+// Fetch a user bio (profile)
+void fetch_user_bio(struct http_transaction *h, struct ctdlsession *c, char *username) {
do_404(h); // FIXME finish this
}
-/*
- * Client requested an object related to a user.
- */
-void object_in_user(struct http_transaction *h, struct ctdlsession *c, char *requested_username)
-{
+// Client requested an object related to a user.
+void object_in_user(struct http_transaction *h, struct ctdlsession *c, char *requested_username) {
char object_name[1024];
extract_token(object_name, h->uri, 4, '/', sizeof object_name);
}
-/*
- * Handle REST/DAV requests for the user itself (such as /ctdl/u/username
- * or /ctdl/i/username/ but *not* specific properties of the user)
- */
-void the_user_itself(struct http_transaction *h, struct ctdlsession *c, char *username)
-{
+// Handle REST/DAV requests for the user itself (such as /ctdl/u/username
+// or /ctdl/i/username/ but *not* specific properties of the user)
+void the_user_itself(struct http_transaction *h, struct ctdlsession *c, char *username) {
do_404(h);
}
-/*
- * Dispatcher for "/ctdl/u" and "/ctdl/u/" for the user list
- */
-void user_list(struct http_transaction *h, struct ctdlsession *c)
-{
+// Dispatcher for "/ctdl/u" and "/ctdl/u/" for the user list
+void user_list(struct http_transaction *h, struct ctdlsession *c) {
do_404(h);
}
-/*
- * Dispatcher for paths starting with /ctdl/u/
- */
-void ctdl_u(struct http_transaction *h, struct ctdlsession *c)
-{
+// Dispatcher for paths starting with /ctdl/u/
+void ctdl_u(struct http_transaction *h, struct ctdlsession *c) {
char requested_username[128];
char buf[1024];
#include "webcit.h"
-/*
- * remove escaped strings from i.e. the url string (like %20 for blanks)
- */
-int unescape_input(char *buf)
-{
+// remove escaped strings from i.e. the url string (like %20 for blanks)
+int unescape_input(char *buf) {
unsigned int a, b;
char hex[3];
long buflen;
if (buf[a] == '+')
buf[a] = ' ';
if (buf[a] == '%') {
- /* don't let % chars through, rather truncate the input. */
+ // don't let % chars through, rather truncate the input.
if (a + 2 > buflen) {
buf[a] = '\0';
buflen = a;
- } else {
+ }
+ else {
hex[0] = buf[a + 1];
hex[1] = buf[a + 2];
hex[2] = 0;
}
-/*
- * Supplied with a unix timestamp, generate a textual time/date stamp.
- * Caller owns the returned memory.
- */
-char *http_datestring(time_t xtime)
-{
+// Supplied with a unix timestamp, generate a textual time/date stamp.
+// Caller owns the returned memory.
+char *http_datestring(time_t xtime) {
- /* HTTP Months - do not translate - these are not for human consumption */
+ // HTTP Months - do not translate - these are not for human consumption
static char *httpdate_months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
- /* HTTP Weekdays - do not translate - these are not for human consumption */
+ // HTTP Weekdays - do not translate - these are not for human consumption
static char *httpdate_weekdays[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
localtime_r(&xtime, &t);
- /* Convert "seconds west of GMT" to "hours/minutes offset" */
+ // Convert "seconds west of GMT" to "hours/minutes offset"
offset = t.tm_gmtoff;
if (offset > 0) {
offsign = '+';
static void *original_brk = NULL; // Remember the original program break so we can test for leaks
-/*
- * Spawn an additional worker thread into the pool.
- */
-void spawn_another_worker_thread(int *pointer_to_master_socket)
-{
+// Spawn an additional worker thread into the pool.
+void spawn_another_worker_thread(int *pointer_to_master_socket) {
pthread_t th; // Thread descriptor
pthread_attr_t attr; // Thread attributes
- /* set attributes for the new thread */
+ // set attributes for the new thread
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&attr, 1048576); // Large stacks to prevent MIME parser crash on FreeBSD
- /* now create the thread */
+ // now create the thread
if (pthread_create(&th, &attr, (void *(*)(void *)) worker_entry, (void *) pointer_to_master_socket) != 0) {
syslog(LOG_WARNING, "Can't create thread: %s", strerror(errno));
- } else {
+ }
+ else {
++num_threads_existing;
++num_threads_executing;
}
- /* free up the attributes */
+ // free up the attributes
pthread_attr_destroy(&attr);
}
-/*
- * Entry point for worker threads
- */
-void worker_entry(int *pointer_to_master_socket)
-{
+// Entry point for worker threads
+void worker_entry(int *pointer_to_master_socket) {
int master_socket = *pointer_to_master_socket;
int i = 0;
int fail_this_transaction = 0;
struct client_handle ch;
while (1) {
- /* Each worker thread blocks on accept() while waiting for something to do. */
+ // Each worker thread blocks on accept() while waiting for something to do.
memset(&ch, 0, sizeof ch);
ch.sock = -1;
errno = EAGAIN;
num_threads_executing, num_threads_existing);
} while ((master_socket > 0) && (ch.sock < 0));
- /* If all threads are executing, spawn more, up to the maximum */
+ // If all threads are executing, spawn more, up to the maximum
if ((num_threads_executing >= num_threads_existing) && (num_threads_existing <= MAX_WORKER_THREADS)) {
spawn_another_worker_thread(pointer_to_master_socket);
}
- /* We have a client. Do some work. */
+ // We have a client. Do some work.
- /* Set the SO_REUSEADDR socket option */
+ // Set the SO_REUSEADDR socket option
i = 1;
setsockopt(ch.sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
- /* If we are an HTTPS server, go crypto now. */
+ // If we are an HTTPS server, go crypto now.
if (is_https) {
starttls(&ch);
if (ch.ssl_handle == NULL) {
fail_this_transaction = 1;
}
- } else {
+ }
+ else {
int fdflags;
fdflags = fcntl(ch.sock, F_GETFL);
if (fdflags < 0) {
}
}
- /* Perform an HTTP transaction... */
+ // Perform an HTTP transaction...
if (fail_this_transaction == 0) {
perform_one_http_transaction(&ch);
}
- /* Shut down SSL/TLS if required... */
+ // Shut down SSL/TLS if required...
if (is_https) {
endtls(&ch);
}
- /* ...and close the socket. */
+ // ...and close the socket.
//syslog(LOG_DEBUG, "Closing socket %d...", ch.sock);
//lingering_close(ch.sock);
close(ch.sock);
}
-/*
- * Start up a TCP HTTP[S] server on the requested port
- */
-int webserver(char *webserver_interface, int webserver_port, int webserver_protocol)
-{
+// Start up a TCP HTTP[S] server on the requested port
+int webserver(char *webserver_interface, int webserver_port, int webserver_protocol) {
int master_socket = (-1);
original_brk = sbrk(0);