Encrypt all post-auth ceoc<->ceod communication
authorMichael Spang <mspang@uwaterloo.ca>
Sat, 24 Oct 2009 16:24:27 +0000 (12:24 -0400)
committerMichael Spang <mspang@uwaterloo.ca>
Sat, 24 Oct 2009 16:59:03 +0000 (12:59 -0400)
src/ceoc.c
src/dslave.c
src/gss.c
src/gss.h

index d6ada68..dc9029d 100644 (file)
@@ -70,6 +70,7 @@ void run_remote(struct op *op, struct strbuf *in, struct strbuf *out) {
     int sock = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
     struct sockaddr_in addr;
     struct sctp_meta response_meta;
+    struct strbuf in_cipher = STRBUF_INIT, out_cipher = STRBUF_INIT;
 
     if (!in->len)
         fatal("no data to send");
@@ -96,19 +97,26 @@ void run_remote(struct op *op, struct strbuf *in, struct strbuf *out) {
     client_acquire_creds("ceod", hostname);
     client_gss_auth(sock, (sa *)&addr, sizeof(addr));
 
-    if (sctp_sendmsg(sock, in->buf, in->len, (struct sockaddr *)&addr,
+    gss_encipher(in, &in_cipher);
+
+    if (sctp_sendmsg(sock, in_cipher.buf, in_cipher.len, (struct sockaddr *)&addr,
                      sizeof(addr), op->id, 0, 0, 0, 0) < 0)
         fatalpe("sctp_sendmsg");
 
-    if (!receive_one_message(sock, &response_meta, out))
+    if (!receive_one_message(sock, &response_meta, &out_cipher))
         fatal("no response received for op %s", op->name);
 
+    gss_decipher(&out_cipher, out);
+
     if (response_meta.sinfo.sinfo_ppid != op->id)
         fatal("wrong ppid from server: expected %d got %d", op->id, response_meta.sinfo.sinfo_ppid);
 
     if (sctp_sendmsg(sock, NULL, 0, (struct sockaddr *)&addr,
                 sizeof(addr), 0, SCTP_EOF, 0, 0 ,0) < 0)
         fatalpe("sctp_sendmsg");
+
+    strbuf_release(&in_cipher);
+    strbuf_release(&out_cipher);
 }
 
 int client_main(char *op_name) {
index a5e915c..8bd511f 100644 (file)
@@ -82,6 +82,7 @@ static void handle_auth_message(struct strbuf *in, struct strbuf *out) {
 
 static void handle_op_message(uint32_t in_type, struct strbuf *in, struct strbuf *out) {
     struct op *op = get_local_op(in_type);
+    struct strbuf in_plain = STRBUF_INIT, out_plain = STRBUF_INIT;
     char *envp[16];
 
     if (!op)
@@ -93,17 +94,23 @@ static void handle_op_message(uint32_t in_type, struct strbuf *in, struct strbuf
     if (!client_username())
         fatal("unathenticated");
 
+    gss_decipher(in, &in_plain);
+
     make_env(envp, "LANG", "C", "CEO_USER", client_username(),
                    "CEO_CONFIG_DIR", config_dir, NULL);
     char *argv[] = { op->path, NULL, };
 
-    if (spawnvemu(op->path, argv, envp, in, out, 0, op->user))
+    if (spawnvemu(op->path, argv, envp, &in_plain, &out_plain, 0, op->user))
         fatal("child %s failed", op->path);
 
+    gss_encipher(&out_plain, out);
+
     if (!out->len)
         fatal("no response from op");
 
     free_env(envp);
+    strbuf_release(&in_plain);
+    strbuf_release(&out_plain);
 }
 
 static void handle_one_message(int sock, struct sctp_meta *in_meta, struct strbuf *in) {
index c963d48..12e6ac4 100644 (file)
--- a/src/gss.c
+++ b/src/gss.c
@@ -234,3 +234,51 @@ char *client_username(void) {
     return peer_username;
 }
 
+void gss_encipher(struct strbuf *plain, struct strbuf *cipher) {
+    OM_uint32 maj_stat, min_stat;
+    gss_buffer_desc plain_tok, cipher_tok;
+    int conf_state;
+
+    plain_tok.value = plain->buf;
+    plain_tok.length = plain->len;
+
+    maj_stat = gss_wrap(&min_stat, context_handle, 1, GSS_C_QOP_DEFAULT,
+                        &plain_tok, &conf_state, &cipher_tok);
+    if (maj_stat != GSS_S_COMPLETE)
+        gss_fatal("gss_wrap", maj_stat, min_stat);
+
+    if (!conf_state)
+        fatal("gss_encipher: confidentiality service required");
+
+    strbuf_add(cipher, cipher_tok.value, cipher_tok.length);
+
+    maj_stat = gss_release_buffer(&min_stat, &cipher_tok);
+    if (maj_stat != GSS_S_COMPLETE)
+        gss_fatal("gss_release_buffer", maj_stat, min_stat);
+}
+
+void gss_decipher(struct strbuf *cipher, struct strbuf *plain) {
+    OM_uint32 maj_stat, min_stat;
+    gss_buffer_desc plain_tok, cipher_tok;
+    int conf_state;
+    gss_qop_t qop_state;
+
+    cipher_tok.value = cipher->buf;
+    cipher_tok.length = cipher->len;
+
+    maj_stat = gss_unwrap(&min_stat, context_handle, &cipher_tok,
+                          &plain_tok, &conf_state, &qop_state);
+    if (maj_stat != GSS_S_COMPLETE)
+        gss_fatal("gss_unwrap", maj_stat, min_stat);
+
+    if (!conf_state)
+        fatal("gss_encipher: confidentiality service required");
+
+    strbuf_add(plain, plain_tok.value, plain_tok.length);
+
+    maj_stat = gss_release_buffer(&min_stat, &plain_tok);
+    if (maj_stat != GSS_S_COMPLETE)
+        gss_fatal("gss_release_buffer", maj_stat, min_stat);
+}
+
+
index 9a14a61..a484647 100644 (file)
--- a/src/gss.h
+++ b/src/gss.h
@@ -10,3 +10,6 @@ int initial_client_token(gss_buffer_t outgoing_tok);
 char *client_principal(void);
 char *client_username(void);
 void free_gss(void);
+
+void gss_encipher(struct strbuf *plain, struct strbuf *cipher);
+void gss_decipher(struct strbuf *cipher, struct strbuf *plain);