dc9029d70990bd955894ba37a65a0f05056e973c
[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 (sctp_sendmsg(sock, token->value, token->length,
28                      addr, addrlen, MSG_AUTH, 0, 0, 0, 0) < 0)
29         fatalpe("sctp_sendmsg");
30
31     maj_stat = gss_release_buffer(&min_stat, token);
32     if (maj_stat != GSS_S_COMPLETE)
33         gss_fatal("gss_release_buffer", maj_stat, min_stat);
34 }
35
36 static void client_gss_auth(int sock, struct sockaddr *addr, socklen_t addrlen) {
37     gss_buffer_desc incoming_tok, outgoing_tok;
38     struct sctp_meta msg_meta;
39     struct strbuf msg = STRBUF_INIT;
40     int complete;
41
42     complete = initial_client_token(&outgoing_tok);
43
44     for (;;) {
45         if (outgoing_tok.length)
46             send_gss_token(sock, addr, addrlen, &outgoing_tok);
47         else if (!complete)
48             fatal("no token to send during auth");
49
50         if (complete)
51             break;
52
53         if (!receive_one_message(sock, &msg_meta, &msg))
54             fatal("connection closed during auth");
55
56         if (msg_meta.sinfo.sinfo_ppid != MSG_AUTH)
57             fatal("unexpected message type 0x%x", msg_meta.sinfo.sinfo_ppid);
58
59         incoming_tok.value = msg.buf;
60         incoming_tok.length = msg.len;
61
62         complete = process_client_token(&incoming_tok, &outgoing_tok);
63     }
64
65     strbuf_release(&msg);
66 }
67
68 void run_remote(struct op *op, struct strbuf *in, struct strbuf *out) {
69     const char *hostname = op->hostname;
70     int sock = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
71     struct sockaddr_in addr;
72     struct sctp_meta response_meta;
73     struct strbuf in_cipher = STRBUF_INIT, out_cipher = STRBUF_INIT;
74
75     if (!in->len)
76         fatal("no data to send");
77
78     memset(&addr, 0, sizeof(addr));
79     addr.sin_family = AF_INET;
80     addr.sin_port = htons(9987);
81     addr.sin_addr = op->addr;
82
83     struct sctp_event_subscribe events;
84     memset(&events, 0, sizeof(events));
85     events.sctp_data_io_event = 1;
86     events.sctp_association_event = 1;
87     events.sctp_address_event = 1;
88     events.sctp_send_failure_event = 1;
89     events.sctp_peer_error_event = 1;
90     events.sctp_shutdown_event = 1;
91     events.sctp_partial_delivery_event = 1;
92     events.sctp_adaptation_layer_event = 1;
93
94     if (setsockopt(sock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)))
95         fatalpe("setsockopt");
96
97     client_acquire_creds("ceod", hostname);
98     client_gss_auth(sock, (sa *)&addr, sizeof(addr));
99
100     gss_encipher(in, &in_cipher);
101
102     if (sctp_sendmsg(sock, in_cipher.buf, in_cipher.len, (struct sockaddr *)&addr,
103                      sizeof(addr), op->id, 0, 0, 0, 0) < 0)
104         fatalpe("sctp_sendmsg");
105
106     if (!receive_one_message(sock, &response_meta, &out_cipher))
107         fatal("no response received for op %s", op->name);
108
109     gss_decipher(&out_cipher, out);
110
111     if (response_meta.sinfo.sinfo_ppid != op->id)
112         fatal("wrong ppid from server: expected %d got %d", op->id, response_meta.sinfo.sinfo_ppid);
113
114     if (sctp_sendmsg(sock, NULL, 0, (struct sockaddr *)&addr,
115                 sizeof(addr), 0, SCTP_EOF, 0, 0 ,0) < 0)
116         fatalpe("sctp_sendmsg");
117
118     strbuf_release(&in_cipher);
119     strbuf_release(&out_cipher);
120 }
121
122 int client_main(char *op_name) {
123     struct op *op = find_op(op_name);
124
125     if (!op)
126         fatal("no such op: %s", op_name);
127
128     struct strbuf in = STRBUF_INIT;
129     struct strbuf out = STRBUF_INIT;
130
131     if (strbuf_read(&in, STDIN_FILENO, 0) < 0)
132         fatalpe("read");
133
134     run_remote(op, &in, &out);
135
136     if (strbuf_write(&out, STDOUT_FILENO) < 0)
137         fatalpe("write");
138
139     strbuf_release(&in);
140     strbuf_release(&out);
141
142     return 0;
143 }
144
145 int main(int argc, char *argv[]) {
146     int opt;
147     int ret;
148     char *op;
149
150     prog = xstrdup(basename(argv[0]));
151     init_log(prog, LOG_PID, LOG_USER, 1);
152
153     configure();
154     setup_ops();
155     setup_fqdn();
156
157     while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) {
158         switch (opt) {
159             case '?':
160                 usage();
161                 break;
162             default:
163                 fatal("error parsing arguments");
164         }
165     }
166
167     if (argc - optind != 1)
168         usage();
169
170     op = argv[optind++];
171
172     ret = client_main(op);
173
174     free_gss();
175     free_fqdn();
176     free_config();
177     free_ops();
178     free(prog);
179
180     return ret;
181 }