Encrypt all post-auth ceoc<->ceod communication
This commit is contained in:
parent
235681263d
commit
0d42df6a85
12
src/ceoc.c
12
src/ceoc.c
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
48
src/gss.c
48
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue