From: Jeff Garzik <jeff@garzik.org>
To: hail-devel@vger.kernel.org
Subject: [PATCH] chunk: Update protocol to support in-band SSL negotiation
Date: Fri, 5 Mar 2010 10:08:41 -0500 [thread overview]
Message-ID: <20100305150840.GA12387@havoc.gtf.org> (raw)
commit 0df0e18e7fdf2674e4a22f0ca8e57a157dad6ca9
Author: Jeff Garzik <jeff@garzik.org>
Date: Fri Mar 5 10:04:00 2010 -0500
Protocol: replace SSL/no-SSL split ports with in-band SSL negotiation
Initiating SSL immediately upon connection, based on incoming TCP
connection port, is a relic of poor HTTP design and should not have
been carried over to chunk protocol. Modern protocols (SMTP, IMAP,
etc.) all support binding to a single port, and then negotiating
SSL/TLS based on a command from the client.
Change chunk protocol such that clients must issue a CHO_START_TLS
command at the beginning of the TCP connection, if they wish
encryption.
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
diff --git a/doc/setup.txt b/doc/setup.txt
index a5e7c66..5ef7225 100644
--- a/doc/setup.txt
+++ b/doc/setup.txt
@@ -27,14 +27,6 @@ _cld._udp.phx2.ex.com has SRV record 10 50 8081 maika.phx2.ex.com.
<Port>8082</Port>
</Listen>
- You can also set the interface and the encryption:
-
- <Listen>
- <Node>192.168.1.24</Node>
- <Port>18082</Port>
- <Encrypt>true</Encrypt>
- </Listen>
-
For clouds and their many cheap nodes with one Ethernet it usually is
not a great idea to specify interfaces, since they often use IPv6 or
acquire IP addresses from DHCP. So, just specify a port.
diff --git a/include/chunk_msg.h b/include/chunk_msg.h
index 154201d..a25fcb5 100644
--- a/include/chunk_msg.h
+++ b/include/chunk_msg.h
@@ -32,16 +32,22 @@ enum {
};
enum chunksrv_ops {
- CHO_NOP = 0,
- CHO_GET = 1,
- CHO_GET_META = 2,
- CHO_PUT = 3,
- CHO_DEL = 4,
- CHO_LIST = 5,
- CHO_LOGIN = 6,
- CHO_TABLE_OPEN = 7,
- CHO_CHECK_START = 8,
- CHO_CHECK_STATUS = 9,
+ CHO_NOP = 0, /* No-op (ping server) */
+ CHO_GET = 1, /* GET object */
+ CHO_GET_META = 2, /* GET object metadata */
+ CHO_PUT = 3, /* PUT object */
+ CHO_DEL = 4, /* Delete object */
+ CHO_LIST = 5, /* List objects */
+ CHO_LOGIN = 6, /* Login as user */
+ CHO_TABLE_OPEN = 7, /* Open table */
+ CHO_CHECK_START = 8, /* Begin self-check */
+ CHO_CHECK_STATUS = 9, /* Query self-check status */
+
+ /* START-TLS is special. It MUST be the first request of a TCP
+ * cxn, and no chunkd-specific response is returned. The SSL
+ * functions' success/failure is sufficient indication.
+ */
+ CHO_START_TLS = 10, /* Encrypt all subsequent msgs */
};
enum chunk_errcode {
diff --git a/lib/chunkdc.c b/lib/chunkdc.c
index e9e0e0f..9c1e967 100644
--- a/lib/chunkdc.c
+++ b/lib/chunkdc.c
@@ -191,6 +191,27 @@ static bool stc_login(struct st_client *stc)
return true;
}
+static bool stc_start_tls_cmd(struct st_client *stc)
+{
+ struct chunksrv_req *req = (struct chunksrv_req *) stc->req_buf;
+
+ if (stc->verbose)
+ fprintf(stderr, "libstc: START-TLS\n");
+
+ /* initialize request */
+ req_init(stc, req);
+ req->op = CHO_START_TLS;
+ strcpy(req->sig, "START-TLS");
+
+ /* write request */
+ if (!net_write(stc, req, req_len(req)))
+ return false;
+
+ /* no response - SSL negotiation begins immediately */
+
+ return true;
+}
+
struct st_client *stc_new(const char *service_host, int port,
const char *user, const char *secret_key,
bool use_ssl)
@@ -253,6 +274,9 @@ struct st_client *stc_new(const char *service_host, int port,
goto err_out;
if (use_ssl) {
+ if (!stc_start_tls_cmd(stc))
+ goto err_out;
+
stc->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
if (!stc->ssl_ctx)
goto err_out;
@@ -266,7 +290,8 @@ struct st_client *stc_new(const char *service_host, int port,
if (!SSL_set_fd(stc->ssl, stc->fd))
goto err_out_ssl;
- if (SSL_connect(stc->ssl) <= 0)
+ rc = SSL_connect(stc->ssl);
+ if (rc <= 0)
goto err_out_ssl;
}
@@ -276,9 +301,15 @@ struct st_client *stc_new(const char *service_host, int port,
return stc;
err_out_ssl:
- SSL_free(stc->ssl);
+ if (stc->ssl) {
+ SSL_free(stc->ssl);
+ stc->ssl = NULL;
+ }
err_out_ctx:
- SSL_CTX_free(stc->ssl_ctx);
+ if (stc->ssl_ctx) {
+ SSL_CTX_free(stc->ssl_ctx);
+ stc->ssl_ctx = NULL;
+ }
err_out:
close(stc->fd);
stc_free(stc);
diff --git a/server/chunkd.h b/server/chunkd.h
index 42bcb21..cd83f7b 100644
--- a/server/chunkd.h
+++ b/server/chunkd.h
@@ -102,6 +102,7 @@ struct client {
SSL *ssl;
bool read_want_write;
bool write_want_read;
+ bool first_req;
struct list_head write_q; /* list of async writes */
bool writing;
@@ -150,7 +151,6 @@ struct listen_cfg {
char *node;
char *port;
char *port_file;
- bool encrypt;
};
struct geo {
diff --git a/server/cldu.c b/server/cldu.c
index 9c27138..dbcf11d 100644
--- a/server/cldu.c
+++ b/server/cldu.c
@@ -540,11 +540,9 @@ static int cldu_make_ffile(char **ret, struct cld_session *sp)
rc = asprintf(&str,
" <Socket>\r\n"
- " <Type>%s</Type>\r\n"
" <Host>%s</Host>\r\n"
" <Port>%s</Port>\r\n"
" </Socket>\r\n",
- cfg->encrypt ? "chunk-ssl" : "chunk",
host,
cfg->port);
if (rc == -1) {
diff --git a/server/config.c b/server/config.c
index 69b5e9b..0422239 100644
--- a/server/config.c
+++ b/server/config.c
@@ -398,16 +398,6 @@ static void cfg_elm_end (GMarkupParseContext *context,
}
}
- else if (cc->in_listen && cc->text &&
- !strcmp(element_name, "Encrypt")) {
- if (!strcasecmp(cc->text, "yes") ||
- !strcasecmp(cc->text, "true"))
- cc->tmp_listen.encrypt = true;
-
- free(cc->text);
- cc->text = NULL;
- }
-
else if (!strcmp(element_name, "Group") && cc->text) {
free(chunkd_srv.group);
chunkd_srv.group = cc->text;
diff --git a/server/server.c b/server/server.c
index 0d83311..4d9a09e 100644
--- a/server/server.c
+++ b/server/server.c
@@ -357,7 +357,7 @@ static void cli_free(struct client *cli)
free(cli);
}
-static struct client *cli_alloc(bool use_ssl)
+static struct client *cli_alloc(void)
{
struct client *cli;
@@ -366,18 +366,10 @@ static struct client *cli_alloc(bool use_ssl)
if (!cli)
return NULL;
- if (use_ssl) {
- cli->ssl = SSL_new(ssl_ctx);
- if (!cli->ssl) {
- applog(LOG_ERR, "SSL_new failed");
- free(cli);
- return NULL;
- }
- }
-
cli->state = evt_read_fixed;
INIT_LIST_HEAD(&cli->write_q);
cli->req_ptr = &cli->creq;
+ cli->first_req = true;
return cli;
}
@@ -1038,6 +1030,7 @@ static const char *op2str(enum chunksrv_ops op)
case CHO_TABLE_OPEN: return "CHO_TABLE_OPEN";
case CHO_CHECK_START: return "CHO_CHECK_START";
case CHO_CHECK_STATUS: return "CHO_CHECK_STATUS";
+ case CHO_START_TLS: return "CHO_START_TLS";
default:
return "BUG/UNKNOWN!";
@@ -1082,7 +1075,8 @@ static bool cli_evt_exec_req(struct client *cli, unsigned int events)
cli->state = evt_recycle;
- if (G_UNLIKELY((!logged_in) && (req->op != CHO_LOGIN))) {
+ if (G_UNLIKELY((!logged_in) && (req->op != CHO_LOGIN) &&
+ (req->op != CHO_START_TLS))) {
cli->state = evt_dispose;
return true;
}
@@ -1142,11 +1136,37 @@ static bool cli_evt_exec_req(struct client *cli, unsigned int events)
case CHO_CHECK_STATUS:
rcb = chk_status(cli);
break;
+ case CHO_START_TLS:
+ if (!cli->first_req) {
+ cli->state = evt_dispose;
+ rcb = true;
+ } else {
+ cli->ssl = SSL_new(ssl_ctx);
+ if (!cli->ssl) {
+ applog(LOG_ERR, "SSL_new failed");
+ cli->state = evt_dispose;
+ rcb = true;
+ break;
+ }
+
+ if (!SSL_set_fd(cli->ssl, cli->fd)) {
+ applog(LOG_ERR, "SSL_set_fd failed");
+ cli->state = evt_dispose;
+ rcb = true;
+ break;
+ }
+
+ cli->state = evt_ssl_accept;
+ rcb = true;
+ }
+ break;
default:
rcb = cli_err(cli, che_InvalidURI, true);
break;
}
+ cli->first_req = false;
+
out:
return rcb;
@@ -1220,7 +1240,7 @@ static bool cli_evt_ssl_accept(struct client *cli, unsigned int events)
rc = SSL_accept(cli->ssl);
if (rc > 0) {
- cli->state = evt_read_fixed;
+ cli->state = evt_recycle;
return true;
}
@@ -1236,6 +1256,8 @@ static bool cli_evt_ssl_accept(struct client *cli, unsigned int events)
return false;
}
+ applog(LOG_ERR, "SSL_accept returned %d", rc);
+
out:
cli->state = evt_dispose;
return true;
@@ -1294,10 +1316,10 @@ static bool tcp_srv_event(int fd, short events, void *userdata)
socklen_t addrlen = sizeof(struct sockaddr_in6);
struct client *cli;
char host[64];
- int rc, on = 1;
+ int on = 1;
struct server_poll *sp;
- cli = cli_alloc(sock->cfg->encrypt);
+ cli = cli_alloc();
if (!cli) {
applog(LOG_ERR, "out of memory");
return false; /* end main loop; terminate server */
@@ -1321,32 +1343,6 @@ static bool tcp_srv_event(int fd, short events, void *userdata)
applog(LOG_WARNING, "TCP_NODELAY failed: %s",
strerror(errno));
- if (sock->cfg->encrypt) {
- if (!SSL_set_fd(cli->ssl, cli->fd))
- goto err_out_fd;
-
- rc = SSL_accept(cli->ssl);
- if (rc <= 0) {
- rc = SSL_get_error(cli->ssl, rc);
- if (rc == SSL_ERROR_WANT_READ)
- cli->state = evt_ssl_accept;
- else if (rc == SSL_ERROR_WANT_WRITE) {
- cli->state = evt_ssl_accept;
- cli->read_want_write = true;
- }
- else {
- unsigned long e = ERR_get_error();
- char estr[121] = "(none?)";
-
- if (e)
- ERR_error_string(e, estr);
- applog(LOG_WARNING, "%s SSL error %s",
- cli->addr_host, estr);
- goto err_out_fd;
- }
- }
- }
-
sp = calloc(1, sizeof(*sp));
if (!sp)
goto err_out_fd;
@@ -1356,11 +1352,6 @@ static bool tcp_srv_event(int fd, short events, void *userdata)
sp->cb = tcp_cli_event;
sp->userdata = cli;
- if (cli->read_want_write) {
- cli->writing = true;
- sp->events |= POLLOUT;
- }
-
g_hash_table_insert(chunkd_srv.fd_info, GINT_TO_POINTER(cli->fd), sp);
/* pretty-print incoming cxn info */
diff --git a/test/auth.c b/test/auth.c
index 78b1f8b..e4bfaf0 100644
--- a/test/auth.c
+++ b/test/auth.c
@@ -43,7 +43,7 @@ static void test(bool do_encrypt)
size_t len = 0;
void *mem;
- port = stc_readport(do_encrypt ? TEST_PORTFILE_SSL : TEST_PORTFILE);
+ port = stc_readport(TEST_PORTFILE);
OK(port > 0);
stc1 = stc_new(TEST_HOST, port, TEST_USER, TEST_USER_KEY, do_encrypt);
diff --git a/test/basic-object.c b/test/basic-object.c
index c4d803a..92ec8c8 100644
--- a/test/basic-object.c
+++ b/test/basic-object.c
@@ -41,7 +41,7 @@ static void test(bool do_encrypt)
size_t len = 0;
void *mem;
- port = stc_readport(do_encrypt ? TEST_PORTFILE_SSL : TEST_PORTFILE);
+ port = stc_readport(TEST_PORTFILE);
OK(port > 0);
stc = stc_new(TEST_HOST, port, TEST_USER, TEST_USER_KEY, do_encrypt);
diff --git a/test/it-works.c b/test/it-works.c
index 597c58b..a3c01ee 100644
--- a/test/it-works.c
+++ b/test/it-works.c
@@ -35,7 +35,7 @@ static void test(bool ssl)
int port;
bool rcb;
- port = stc_readport(ssl ? TEST_PORTFILE_SSL : TEST_PORTFILE);
+ port = stc_readport(TEST_PORTFILE);
OK(port > 0);
stc = stc_new(TEST_HOST, port, TEST_USER, TEST_USER_KEY, ssl);
diff --git a/test/large-object.c b/test/large-object.c
index 5188aad..d1a031e 100644
--- a/test/large-object.c
+++ b/test/large-object.c
@@ -108,7 +108,7 @@ static void test(bool do_encrypt)
memset(data, 0xdeadbeef, sizeof(data));
- port = stc_readport(do_encrypt ? TEST_PORTFILE_SSL : TEST_PORTFILE);
+ port = stc_readport(TEST_PORTFILE);
OK(port > 0);
stc = stc_new(TEST_HOST, port, TEST_USER, TEST_USER_KEY, do_encrypt);
diff --git a/test/lotsa-objects.c b/test/lotsa-objects.c
index 048c1c3..d7dd95c 100644
--- a/test/lotsa-objects.c
+++ b/test/lotsa-objects.c
@@ -47,7 +47,7 @@ static void test(int n_objects, bool do_encrypt)
char *k;
struct timeval ta, tb;
- port = stc_readport(do_encrypt ? TEST_PORTFILE_SSL : TEST_PORTFILE);
+ port = stc_readport(TEST_PORTFILE);
OK(port > 0);
stc = stc_new(TEST_HOST, port, TEST_USER, TEST_USER_KEY, do_encrypt);
diff --git a/test/nop.c b/test/nop.c
index 526b8c0..bd89a7b 100644
--- a/test/nop.c
+++ b/test/nop.c
@@ -42,7 +42,7 @@ static void test(int n_nops, bool do_encrypt)
int i;
struct timeval ta, tb;
- port = stc_readport(do_encrypt ? TEST_PORTFILE_SSL : TEST_PORTFILE);
+ port = stc_readport(TEST_PORTFILE);
OK(port > 0);
stc = stc_new(TEST_HOST, port, TEST_USER, TEST_USER_KEY, do_encrypt);
diff --git a/test/server-test.cfg b/test/server-test.cfg
index d98fca4..29b69e2 100644
--- a/test/server-test.cfg
+++ b/test/server-test.cfg
@@ -10,12 +10,6 @@
<PortFile>chunkd.port</PortFile>
</Listen>
-<Listen>
- <Port>auto</Port>
- <PortFile>chunkd-ssl.port</PortFile>
- <Encrypt>true</Encrypt>
-</Listen>
-
<PID>chunkd.pid</PID>
<Path>data/chunk</Path>
diff --git a/test/test.h b/test/test.h
index 75aa250..cc4111f 100644
--- a/test/test.h
+++ b/test/test.h
@@ -36,7 +36,6 @@
#define TEST_PORTFILE_CLD "cld.port"
#define TEST_PORTFILE "chunkd.port"
-#define TEST_PORTFILE_SSL "chunkd-ssl.port"
#define TEST_CHUNKD_CFG "server-test.cfg"
reply other threads:[~2010-03-05 15:08 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100305150840.GA12387@havoc.gtf.org \
--to=jeff@garzik.org \
--cc=hail-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).