Switch from SCTP to TCP
[public/pyceo-broken.git] / src / ceoc.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <getopt.h>
5 #include <libgen.h>
6
7 #include "util.h"
8 #include "net.h"
9 #include "gss.h"
10 #include "ops.h"
11 #include "config.h"
12
13 char *prog = NULL;
14
15 static struct option opts[] = {
16     { NULL, 0, NULL, '\0' },
17 };
18
19 static void usage() {
20     fprintf(stderr, "Usage: %s op\n", prog);
21     exit(2);
22 }
23
24 static void send_gss_token(int sock, struct sockaddr *addr, socklen_t addrlen, gss_buffer_t token) {
25     OM_uint32 maj_stat, min_stat;
26
27     if (ceo_send_message(sock, token->value, token->length, MSG_AUTH))
28         fatalpe("write");
29
30     maj_stat = gss_release_buffer(&min_stat, token);
31     if (maj_stat != GSS_S_COMPLETE)
32         gss_fatal("gss_release_buffer", maj_stat, min_stat);
33 }
34
35 static void client_gss_auth(int sock, struct sockaddr *addr, socklen_t addrlen) {
36     gss_buffer_desc incoming_tok, outgoing_tok;
37     struct strbuf msg = STRBUF_INIT;
38     uint32_t msgtype;
39     int complete;
40
41     complete = initial_client_token(&outgoing_tok);
42
43     for (;;) {
44         if (outgoing_tok.length)
45             send_gss_token(sock, addr, addrlen, &outgoing_tok);
46         else if (!complete)
47             fatal("no token to send during auth");
48
49         if (complete)
50             break;
51
52         if (ceo_receive_message(sock, &msg, &msgtype))
53             fatal("connection closed during auth");
54
55         if (msgtype != MSG_AUTH)
56             fatal("unexpected message type 0x%x", msgtype);
57
58         incoming_tok.value = msg.buf;
59         incoming_tok.length = msg.len;
60
61         complete = process_client_token(&incoming_tok, &outgoing_tok);
62     }
63
64     strbuf_release(&msg);
65 }
66
67 void run_remote(struct op *op, struct strbuf *in, struct strbuf *out) {
68     const char *hostname = op->hostname;
69     int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
70     struct sockaddr_in addr;
71     uint32_t msgtype;
72     struct strbuf in_cipher = STRBUF_INIT, out_cipher = STRBUF_INIT;
73
74     if (!in->len)
75         fatal("no data to send");
76
77     memset(&addr, 0, sizeof(addr));
78     addr.sin_family = AF_INET;
79     addr.sin_port = htons(9987);
80     addr.sin_addr = op->addr;
81
82     if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)))
83         fatalpe("connect");
84
85     client_acquire_creds("ceod", hostname);
86     client_gss_auth(sock, (sa *)&addr, sizeof(addr));
87
88     gss_encipher(in, &in_cipher);
89
90     if (ceo_send_message(sock, in_cipher.buf, in_cipher.len, op->id))
91         fatalpe("write");
92
93     if (ceo_receive_message(sock, &out_cipher, &msgtype))
94         fatal("no response received for op %s", op->name);
95
96     gss_decipher(&out_cipher, out);
97
98     if (msgtype != op->id)
99         fatal("wrong message type from server: expected %d got %d", op->id, msgtype);
100
101     if (close(sock))
102         fatalpe("close");
103
104     strbuf_release(&in_cipher);
105     strbuf_release(&out_cipher);
106 }
107
108 int client_main(char *op_name) {
109     struct op *op = find_op(op_name);
110
111     if (!op)
112         fatal("no such op: %s", op_name);
113
114     struct strbuf in = STRBUF_INIT;
115     struct strbuf out = STRBUF_INIT;
116
117     if (strbuf_read(&in, STDIN_FILENO, 0) < 0)
118         fatalpe("read");
119
120     run_remote(op, &in, &out);
121
122     if (strbuf_write(&out, STDOUT_FILENO) < 0)
123         fatalpe("write");
124
125     strbuf_release(&in);
126     strbuf_release(&out);
127
128     return 0;
129 }
130
131 int main(int argc, char *argv[]) {
132     int opt;
133     int ret;
134     char *op;
135
136     prog = xstrdup(basename(argv[0]));
137     init_log(prog, LOG_PID, LOG_USER, 1);
138
139     configure();
140     setup_ops();
141     setup_fqdn();
142
143     while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) {
144         switch (opt) {
145             case '?':
146                 usage();
147                 break;
148             default:
149                 fatal("error parsing arguments");
150         }
151     }
152
153     if (argc - optind != 1)
154         usage();
155
156     op = argv[optind++];
157
158     ret = client_main(op);
159
160     free_gss();
161     free_fqdn();
162     free_config();
163     free_ops();
164     free(prog);
165
166     return ret;
167 }