sbotc.cView |
---|
16 | 16 … | #include <ifaddrs.h> |
17 | 17 … | #include <limits.h> |
18 | 18 … | #include <netdb.h> |
19 | 19 … | #include <netinet/in.h> |
| 20 … | +#include <signal.h> |
20 | 21 … | #include <stdarg.h> |
21 | 22 … | #include <stdbool.h> |
22 | 23 … | #include <stdio.h> |
23 | 24 … | #include <stdlib.h> |
115 | 116 … | |
116 | 117 … | static void usage() { |
117 | 118 … | fputs("usage: sbotc [-j] [-T] [-l] [-r] [-e]\n" |
118 | 119 … | " [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n" |
119 | | - " [ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ]\n" |
| 120 … | + " [ [-s <host>] [-p <port>] [ -4 | -6 ] [-d] | [-u <socket_path>] ]\n" |
120 | 121 … | " [ -a | [-t <type>] <method> [<argument>...] ]\n", stderr); |
121 | 122 … | exit(EXIT_FAILURE); |
122 | 123 … | } |
123 | 124 … | |
155 | 156 … | freeifaddrs(ifaddr); |
156 | 157 … | return fd; |
157 | 158 … | } |
158 | 159 … | |
159 | | -static int tcp_connect(const char *host, const char *port, enum ip_family ip_family) { |
| 160 … | +static int tcp_connect(const char *host, const char *port, enum ip_family ip_family, bool server) { |
160 | 161 … | struct addrinfo hints; |
161 | 162 … | struct addrinfo *result, *rp; |
162 | 163 … | int s; |
163 | 164 … | int fd; |
164 | | - int err; |
| 165 … | + int err, rc; |
165 | 166 … | |
166 | 167 … | memset(&hints, 0, sizeof(hints)); |
167 | 168 … | hints.ai_family = ip_family; |
168 | 169 … | hints.ai_protocol = IPPROTO_TCP; |
| 170 … | + if (server) hints.ai_flags = AI_PASSIVE; |
169 | 171 … | |
170 | 172 … | s = getaddrinfo(host, port, &hints, &result); |
171 | 173 … | if (s < 0) errx(1, "unable to resolve host: %s", gai_strerror(s)); |
172 | 174 … | |
173 | 175 … | for (rp = result; rp; rp = rp->ai_next) { |
174 | 176 … | fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); |
175 | 177 … | if (fd < 0) continue; |
176 | | - if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) break; |
| 178 … | + if (server) { |
| 179 … | + rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); |
| 180 … | + if (rc < 0) goto error; |
| 181 … | + if (bind(fd, rp->ai_addr, rp->ai_addrlen) < 0) goto error; |
| 182 … | + if (listen(fd, 1) == 0) break; |
| 183 … | + } else { |
| 184 … | + if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) break; |
| 185 … | + } |
| 186 … | +error: |
177 | 187 … | err = errno; |
178 | 188 … | close(fd); |
179 | 189 … | errno = err; |
180 | 190 … | } |
181 | 191 … | if (rp == NULL) fd = -1; |
182 | 192 … | |
183 | 193 … | freeaddrinfo(result); |
184 | 194 … | |
185 | | - if (fd == -1 && errno == ECONNREFUSED && (host == NULL || !strcmp(host, "localhost"))) { |
| 195 … | + if (!server && fd == -1 && errno == ECONNREFUSED && (host == NULL || !strcmp(host, "localhost"))) { |
186 | 196 … | return connect_localhost(port, ip_family); |
187 | 197 … | } |
188 | 198 … | |
| 199 … | + if (server && fd > -1) { |
| 200 … | + int client = accept(fd, NULL, NULL); |
| 201 … | + err = errno; |
| 202 … | + close(fd); |
| 203 … | + errno = err; |
| 204 … | + return client; |
| 205 … | + } |
| 206 … | + |
189 | 207 … | return fd; |
190 | 208 … | } |
191 | 209 … | |
192 | | -static int unix_connect(const char *path) { |
| 210 … | +static const char *socket_path = NULL; |
| 211 … | + |
| 212 … | +void cleanup() { |
| 213 … | + if (socket_path != NULL) { |
| 214 … | + int rc = unlink(socket_path); |
| 215 … | + if (rc < 0) warn("unlink"); |
| 216 … | + } |
| 217 … | +} |
| 218 … | + |
| 219 … | +static int unix_connect(const char *path, bool server) { |
193 | 220 … | struct sockaddr_un name; |
194 | 221 … | const size_t path_len = strlen(path); |
195 | 222 … | int s, rc; |
196 | 223 … | if (path_len >= sizeof(name.sun_path)-1) errx(1, "socket path too long"); |
198 | 225 … | if (s < 0) return -1; |
199 | 226 … | memset(&name, 0, sizeof(struct sockaddr_un)); |
200 | 227 … | name.sun_family = AF_UNIX; |
201 | 228 … | strncpy(name.sun_path, path, sizeof(name.sun_path) - 1); |
202 | | - rc = connect(s, (const struct sockaddr *)&name, sizeof name); |
| 229 … | + if (server) { |
| 230 … | + rc = bind(s, (const struct sockaddr *)&name, sizeof name); |
| 231 … | + if (rc < 0) return -1; |
| 232 … | + rc = listen(s, 1); |
| 233 … | + } else { |
| 234 … | + rc = connect(s, (const struct sockaddr *)&name, sizeof name); |
| 235 … | + } |
203 | 236 … | if (rc < 0) return -1; |
| 237 … | + |
| 238 … | + if (server && rc > -1) { |
| 239 … | + socket_path = strdup(path); |
| 240 … | + if (atexit(cleanup) < 0) warn("atexit"); |
| 241 … | + if (signal(SIGINT, exit) == SIG_ERR) warn("signal"); |
| 242 … | + int client = accept(s, NULL, NULL); |
| 243 … | + int err = errno; |
| 244 … | + close(s); |
| 245 … | + errno = err; |
| 246 … | + return client; |
| 247 … | + } |
| 248 … | + |
204 | 249 … | return s; |
205 | 250 … | } |
206 | 251 … | |
207 | | -static int get_socket_path(char *buf, size_t len, const char *app_dir) { |
| 252 … | +static int get_socket_path(char *buf, size_t len, const char *app_dir, bool server) { |
208 | 253 … | struct stat st; |
209 | 254 … | int sz = snprintf(buf, len-1, "%s/%s", app_dir, "socket"); |
210 | 255 … | if (sz < 0 || sz >= (int)len-1) err(1, "failed to get socket path"); |
211 | 256 … | int rc = stat(buf, &st); |
212 | | - if (rc < 0) return -1; |
213 | | - if (!(st.st_mode & S_IFSOCK)) { errno = EINVAL; return -1; } |
| 257 … | + if (!server) { |
| 258 … | + if (rc < 0) return -1; |
| 259 … | + if (!(st.st_mode & S_IFSOCK)) { errno = EINVAL; return -1; } |
| 260 … | + } |
214 | 261 … | return 0; |
215 | 262 … | } |
216 | 263 … | |
217 | 264 … | static int read_all(int fd, void *buf, size_t count) { |
248 | 295 … | } |
249 | 296 … | return 0; |
250 | 297 … | } |
251 | 298 … | |
252 | | -static void shs_connect(int sfd, int infd, int outfd, const unsigned char pubkey[32], const unsigned char seckey[64], const unsigned char appkey[32], const unsigned char server_pubkey[32], struct boxs *bs) { |
| 299 … | +static void shs_connect(int sfd, int infd, int outfd, const unsigned char pubkey[32], const unsigned char seckey[64], const unsigned char appkey[32], const unsigned char remote_pubkey[32], struct boxs *bs, bool client, bool specify_client_key) { |
253 | 300 … | int rc; |
| 301 … | + unsigned char client_pubkey[32]; |
254 | 302 … | unsigned char local_app_mac[32], remote_app_mac[32]; |
| 303 … | + unsigned char kx_pk[32], kx_sk[32], remote_kx_pk[32]; |
| 304 … | + unsigned char buf[64]; |
255 | 305 … | |
256 | | - unsigned char kx_pk[32], kx_sk[32]; |
257 | | - rc = crypto_box_keypair(kx_pk, kx_sk); |
258 | | - if (rc < 0) errx(1, "failed to generate auth keypair"); |
| 306 … | + if (client) { |
|
| 307 … | + rc = crypto_box_keypair(kx_pk, kx_sk); |
| 308 … | + if (rc < 0) errx(1, "failed to generate auth keypair"); |
259 | 309 … | |
260 | | - rc = crypto_auth(local_app_mac, kx_pk, 32, appkey); |
261 | | - if (rc < 0) err(1, "failed to generate app mac"); |
| 310 … | + rc = crypto_auth(local_app_mac, kx_pk, 32, appkey); |
| 311 … | + if (rc < 0) err(1, "failed to generate app mac"); |
262 | 312 … | |
263 | | - |
264 | | - unsigned char buf[64]; |
265 | | - memcpy(buf, local_app_mac, 32); |
266 | | - memcpy(buf+32, kx_pk, 32); |
267 | | - rc = write_all(outfd, buf, sizeof(buf)); |
268 | | - if (rc < 0) err(1, "failed to send challenge"); |
| 313 … | + |
| 314 … | + memcpy(buf, local_app_mac, 32); |
| 315 … | + memcpy(buf+32, kx_pk, 32); |
| 316 … | + rc = write_all(outfd, buf, sizeof(buf)); |
| 317 … | + if (rc < 0) err(1, "failed to send challenge"); |
269 | 318 … | |
270 | | - |
271 | | - unsigned char remote_kx_pk[32]; |
272 | | - rc = read_all(infd, buf, sizeof(buf)); |
273 | | - if (rc < 0) err(1, "challenge not accepted"); |
274 | | - memcpy(remote_app_mac, buf, 32); |
275 | | - memcpy(remote_kx_pk, buf+32, 32); |
276 | | - rc = crypto_auth_verify(buf, remote_kx_pk, 32, appkey); |
277 | | - if (rc < 0) errx(1, "wrong protocol (version?)"); |
| 319 … | + } else { |
| 320 … | + |
| 321 … | + rc = read_all(infd, buf, sizeof(buf)); |
| 322 … | + if (rc < 0) err(1, "expected challenge"); |
| 323 … | + memcpy(remote_app_mac, buf, 32); |
| 324 … | + memcpy(remote_kx_pk, buf+32, 32); |
278 | 325 … | |
279 | | - |
| 326 … | + rc = crypto_auth_verify(buf, remote_kx_pk, 32, appkey); |
| 327 … | + if (rc < 0) errx(1, "wrong protocol/version"); |
280 | 328 … | |
281 | | - unsigned char secret[32]; |
282 | | - rc = crypto_scalarmult(secret, kx_sk, remote_kx_pk); |
283 | | - if (rc < 0) errx(1, "failed to derive shared secret"); |
| 329 … | + } |
284 | 330 … | |
285 | | - unsigned char remote_pk_curve[32]; |
286 | | - rc = crypto_sign_ed25519_pk_to_curve25519(remote_pk_curve, server_pubkey); |
287 | | - if (rc < 0) errx(1, "failed to curvify remote public key"); |
| 331 … | + if (client) { |
| 332 … | + |
| 333 … | + rc = read_all(infd, buf, sizeof(buf)); |
| 334 … | + if (rc < 0) err(1, "challenge not accepted"); |
| 335 … | + memcpy(remote_app_mac, buf, 32); |
| 336 … | + memcpy(remote_kx_pk, buf+32, 32); |
| 337 … | + rc = crypto_auth_verify(buf, remote_kx_pk, 32, appkey); |
| 338 … | + if (rc < 0) errx(1, "wrong protocol (version?)"); |
288 | 339 … | |
289 | | - unsigned char a_bob[32]; |
290 | | - rc = crypto_scalarmult(a_bob, kx_sk, remote_pk_curve); |
291 | | - if (rc < 0) errx(1, "failed to derive a_bob"); |
| 340 … | + } else { |
| 341 … | + rc = crypto_box_keypair(kx_pk, kx_sk); |
| 342 … | + if (rc < 0) errx(1, "failed to generate auth keypair"); |
292 | 343 … | |
293 | | - unsigned char secret2a[96]; |
294 | | - memcpy(secret2a, appkey, 32); |
295 | | - memcpy(secret2a+32, secret, 32); |
296 | | - memcpy(secret2a+64, a_bob, 32); |
| 344 … | + rc = crypto_auth(local_app_mac, kx_pk, 32, appkey); |
| 345 … | + if (rc < 0) err(1, "failed to generate app mac"); |
297 | 346 … | |
| 347 … | + |
| 348 … | + memcpy(buf, local_app_mac, 32); |
| 349 … | + memcpy(buf+32, kx_pk, 32); |
| 350 … | + rc = write_all(outfd, buf, sizeof(buf)); |
| 351 … | + if (rc < 0) err(1, "failed to send challenge"); |
| 352 … | + |
| 353 … | + } |
| 354 … | + |
| 355 … | + unsigned char remote_pk_curve[32]; |
| 356 … | + unsigned char hello[96]; |
298 | 357 … | unsigned char secret2[32]; |
299 | | - rc = crypto_hash_sha256(secret2, secret2a, sizeof(secret2a)); |
300 | | - if (rc < 0) errx(1, "failed to hash secret2"); |
301 | | - |
| 358 … | + unsigned char boxed_auth[112]; |
| 359 … | + unsigned char secret[32]; |
| 360 … | + unsigned char a_bob[32]; |
| 361 … | + unsigned char secret2a[96]; |
302 | 362 … | unsigned char shash[32]; |
303 | | - rc = crypto_hash_sha256(shash, secret, sizeof(secret)); |
304 | | - if (rc < 0) errx(1, "failed to hash secret"); |
305 | | - |
| 363 … | + unsigned char sig[64]; |
306 | 364 … | unsigned char signed1[96]; |
307 | | - memcpy(signed1, appkey, 32); |
308 | | - memcpy(signed1+32, server_pubkey, 32); |
309 | | - memcpy(signed1+64, shash, 32); |
| 365 … | + unsigned char local_sk_curve[32]; |
| 366 … | + if (client) { |
| 367 … | + |
310 | 368 … | |
311 | | - unsigned char sig[64]; |
312 | | - rc = crypto_sign_detached(sig, NULL, signed1, sizeof(signed1), seckey); |
313 | | - if (rc < 0) errx(1, "failed to sign inner hello"); |
| 369 … | + rc = crypto_scalarmult(secret, kx_sk, remote_kx_pk); |
| 370 … | + if (rc < 0) errx(1, "failed to derive shared secret"); |
314 | 371 … | |
315 | | - unsigned char hello[96]; |
316 | | - memcpy(hello, sig, 64); |
317 | | - memcpy(hello+64, pubkey, 32); |
| 372 … | + rc = crypto_sign_ed25519_pk_to_curve25519(remote_pk_curve, remote_pubkey); |
| 373 … | + if (rc < 0) errx(1, "failed to curvify remote public key"); |
318 | 374 … | |
319 | | - unsigned char boxed_auth[112]; |
320 | | - rc = crypto_secretbox_easy(boxed_auth, hello, sizeof(hello), zeros, secret2); |
321 | | - if (rc < 0) errx(1, "failed to box hello"); |
| 375 … | + rc = crypto_scalarmult(a_bob, kx_sk, remote_pk_curve); |
| 376 … | + if (rc < 0) errx(1, "failed to derive a_bob"); |
322 | 377 … | |
323 | | - rc = write_all(outfd, boxed_auth, sizeof(boxed_auth)); |
324 | | - if (rc < 0) errx(1, "failed to send auth"); |
| 378 … | + memcpy(secret2a, appkey, 32); |
| 379 … | + memcpy(secret2a+32, secret, 32); |
| 380 … | + memcpy(secret2a+64, a_bob, 32); |
325 | 381 … | |
326 | | - |
| 382 … | + rc = crypto_hash_sha256(secret2, secret2a, sizeof(secret2a)); |
| 383 … | + if (rc < 0) errx(1, "failed to hash secret2"); |
327 | 384 … | |
328 | | - unsigned char boxed_okay[80]; |
329 | | - rc = read_all(infd, boxed_okay, sizeof(boxed_okay)); |
330 | | - if (rc < 0) err(1, "hello not accepted"); |
| 385 … | + rc = crypto_hash_sha256(shash, secret, sizeof(secret)); |
| 386 … | + if (rc < 0) errx(1, "failed to hash secret"); |
331 | 387 … | |
332 | | - unsigned char local_sk_curve[32]; |
333 | | - rc = crypto_sign_ed25519_sk_to_curve25519(local_sk_curve, seckey); |
334 | | - if (rc < 0) errx(1, "failed to curvify local secret key"); |
| 388 … | + unsigned char signed1[96]; |
| 389 … | + memcpy(signed1, appkey, 32); |
| 390 … | + memcpy(signed1+32, remote_pubkey, 32); |
| 391 … | + memcpy(signed1+64, shash, 32); |
335 | 392 … | |
336 | | - unsigned char b_alice[32]; |
337 | | - rc = crypto_scalarmult(b_alice, local_sk_curve, remote_kx_pk); |
338 | | - if (rc < 0) errx(1, "failed to derive b_alice"); |
| 393 … | + rc = crypto_sign_detached(sig, NULL, signed1, sizeof(signed1), seckey); |
| 394 … | + if (rc < 0) errx(1, "failed to sign inner hello"); |
339 | 395 … | |
340 | | - unsigned char secret3a[128]; |
341 | | - memcpy(secret3a, appkey, 32); |
342 | | - memcpy(secret3a+32, secret, 32); |
343 | | - memcpy(secret3a+64, a_bob, 32); |
344 | | - memcpy(secret3a+96, b_alice, 32); |
| 396 … | + memcpy(hello, sig, 64); |
| 397 … | + memcpy(hello+64, pubkey, 32); |
345 | 398 … | |
346 | | - unsigned char secret3[32]; |
347 | | - rc = crypto_hash_sha256(secret3, secret3a, sizeof(secret3a)); |
348 | | - if (rc < 0) errx(1, "failed to hash secret3"); |
| 399 … | + rc = crypto_secretbox_easy(boxed_auth, hello, sizeof(hello), zeros, secret2); |
| 400 … | + if (rc < 0) errx(1, "failed to box hello"); |
349 | 401 … | |
350 | | - rc = crypto_secretbox_open_easy(sig, boxed_okay, sizeof(boxed_okay), zeros, secret3); |
351 | | - if (rc < 0) errx(1, "failed to unbox the okay"); |
| 402 … | + rc = write_all(outfd, boxed_auth, sizeof(boxed_auth)); |
| 403 … | + if (rc < 0) errx(1, "failed to send auth"); |
352 | 404 … | |
| 405 … | + } else { |
| 406 … | + |
| 407 … | + rc = read_all(infd, boxed_auth, sizeof(boxed_auth)); |
| 408 … | + if (rc < 0) err(1, "expected hello"); |
| 409 … | + |
| 410 … | + rc = crypto_scalarmult(secret, kx_sk, remote_kx_pk); |
| 411 … | + if (rc < 0) errx(1, "failed to derive shared secret"); |
| 412 … | + |
| 413 … | + rc = crypto_hash_sha256(shash, secret, sizeof(secret)); |
| 414 … | + if (rc < 0) errx(1, "failed to hash secret"); |
| 415 … | + |
| 416 … | + rc = crypto_sign_ed25519_sk_to_curve25519(local_sk_curve, seckey); |
| 417 … | + if (rc < 0) errx(1, "failed to curvify local secret key"); |
| 418 … | + |
| 419 … | + rc = crypto_scalarmult(a_bob, local_sk_curve, remote_kx_pk); |
| 420 … | + if (rc < 0) errx(1, "failed to derive a_bob"); |
| 421 … | + |
| 422 … | + memcpy(secret2a, appkey, 32); |
| 423 … | + memcpy(secret2a+32, secret, 32); |
| 424 … | + memcpy(secret2a+64, a_bob, 32); |
| 425 … | + |
| 426 … | + rc = crypto_hash_sha256(secret2, secret2a, sizeof(secret2a)); |
| 427 … | + if (rc < 0) errx(1, "failed to hash secret2"); |
| 428 … | + |
| 429 … | + rc = crypto_secretbox_open_easy(hello, boxed_auth, sizeof(boxed_auth), zeros, secret2); |
| 430 … | + if (rc < 0) errx(1, "failed to unbox client hello"); |
| 431 … | + |
| 432 … | + memcpy(sig, hello, 64); |
| 433 … | + memcpy(client_pubkey, hello+64, 32); |
| 434 … | + |
| 435 … | + memcpy(signed1, appkey, 32); |
| 436 … | + memcpy(signed1+32, pubkey, 32); |
| 437 … | + memcpy(signed1+64, shash, 32); |
| 438 … | + |
| 439 … | + rc = crypto_sign_verify_detached(sig, signed1, sizeof(signed1), client_pubkey); |
| 440 … | + if (rc < 0) errx(1, "wrong number"); |
| 441 … | + } |
| 442 … | + |
| 443 … | + unsigned char boxed_okay[80]; |
| 444 … | + unsigned char b_alice[32]; |
| 445 … | + unsigned char secret3a[128]; |
| 446 … | + unsigned char secret3[32]; |
353 | 447 … | unsigned char signed2[160]; |
354 | | - memcpy(signed2, appkey, 32); |
355 | | - memcpy(signed2+32, hello, 96); |
356 | | - memcpy(signed2+128, shash, 32); |
| 448 … | + if (client) { |
| 449 … | + |
357 | 450 … | |
358 | | - rc = crypto_sign_verify_detached(sig, signed2, sizeof(signed2), server_pubkey); |
359 | | - if (rc < 0) errx(1, "server not authenticated"); |
| 451 … | + rc = read_all(infd, boxed_okay, sizeof(boxed_okay)); |
| 452 … | + if (rc < 0) err(1, "hello not accepted"); |
360 | 453 … | |
| 454 … | + rc = crypto_sign_ed25519_sk_to_curve25519(local_sk_curve, seckey); |
| 455 … | + if (rc < 0) errx(1, "failed to curvify local secret key"); |
| 456 … | + |
| 457 … | + rc = crypto_scalarmult(b_alice, local_sk_curve, remote_kx_pk); |
| 458 … | + if (rc < 0) errx(1, "failed to derive b_alice"); |
| 459 … | + |
| 460 … | + memcpy(secret3a, appkey, 32); |
| 461 … | + memcpy(secret3a+32, secret, 32); |
| 462 … | + memcpy(secret3a+64, a_bob, 32); |
| 463 … | + memcpy(secret3a+96, b_alice, 32); |
| 464 … | + |
| 465 … | + rc = crypto_hash_sha256(secret3, secret3a, sizeof(secret3a)); |
| 466 … | + if (rc < 0) errx(1, "failed to hash secret3"); |
| 467 … | + |
| 468 … | + rc = crypto_secretbox_open_easy(sig, boxed_okay, sizeof(boxed_okay), zeros, secret3); |
| 469 … | + if (rc < 0) errx(1, "failed to unbox the okay"); |
| 470 … | + |
| 471 … | + memcpy(signed2, appkey, 32); |
| 472 … | + memcpy(signed2+32, hello, 96); |
| 473 … | + memcpy(signed2+128, shash, 32); |
| 474 … | + |
| 475 … | + rc = crypto_sign_verify_detached(sig, signed2, sizeof(signed2), remote_pubkey); |
| 476 … | + if (rc < 0) errx(1, "server not authenticated"); |
| 477 … | + |
| 478 … | + } else { |
| 479 … | + if (specify_client_key && memcmp(client_pubkey, remote_pubkey, 32)) { |
| 480 … | + errx(1, "unexpected client"); |
| 481 … | + } |
| 482 … | + |
| 483 … | + |
| 484 … | + |
| 485 … | + rc = crypto_sign_ed25519_pk_to_curve25519(remote_pk_curve, client_pubkey); |
| 486 … | + if (rc < 0) errx(1, "failed to curvify remote public key"); |
| 487 … | + |
| 488 … | + rc = crypto_scalarmult(b_alice, kx_sk, remote_pk_curve); |
| 489 … | + if (rc < 0) errx(1, "failed to derive b_alice"); |
| 490 … | + |
| 491 … | + memcpy(secret3a, appkey, 32); |
| 492 … | + memcpy(secret3a+32, secret, 32); |
| 493 … | + memcpy(secret3a+64, a_bob, 32); |
| 494 … | + memcpy(secret3a+96, b_alice, 32); |
| 495 … | + |
| 496 … | + rc = crypto_hash_sha256(secret3, secret3a, sizeof(secret3a)); |
| 497 … | + if (rc < 0) errx(1, "failed to hash secret3"); |
| 498 … | + |
| 499 … | + memcpy(signed2, appkey, 32); |
| 500 … | + memcpy(signed2+32, hello, 96); |
| 501 … | + memcpy(signed2+128, shash, 32); |
| 502 … | + |
| 503 … | + rc = crypto_sign_detached(sig, NULL, signed2, sizeof(signed2), seckey); |
| 504 … | + if (rc < 0) errx(1, "failed to sign inner accept"); |
| 505 … | + |
| 506 … | + rc = crypto_secretbox_easy(boxed_okay, sig, sizeof(sig), zeros, secret3); |
| 507 … | + if (rc < 0) errx(1, "failed to box accept"); |
| 508 … | + |
| 509 … | + rc = write_all(outfd, boxed_okay, sizeof(boxed_okay)); |
| 510 … | + if (rc < 0) errx(1, "failed to send accept"); |
| 511 … | + } |
| 512 … | + |
361 | 513 … | rc = crypto_hash_sha256(secret, secret3, 32); |
362 | 514 … | if (rc < 0) errx(1, "failed to hash secret3"); |
363 | 515 … | |
364 | 516 … | unsigned char enc_key_hashed[64]; |
365 | 517 … | memcpy(enc_key_hashed, secret, 32); |
366 | | - memcpy(enc_key_hashed+32, server_pubkey, 32); |
| 518 … | + memcpy(enc_key_hashed+32, client ? remote_pubkey : client_pubkey, 32); |
367 | 519 … | rc = crypto_hash_sha256(bs->encrypt_key, enc_key_hashed, 64); |
368 | 520 … | if (rc < 0) errx(1, "failed to hash the encrypt key"); |
369 | 521 … | |
370 | 522 … | unsigned char dec_key_hashed[64]; |
1055 | 1207 … | bool ipv4_arg = false; |
1056 | 1208 … | bool ipv6_arg = false; |
1057 | 1209 … | bool passthrough = false; |
1058 | 1210 … | bool strings = false; |
| 1211 … | + bool daemon = false; |
1059 | 1212 … | enum ip_family ip_family; |
1060 | 1213 … | |
1061 | 1214 … | get_app_dir(app_dir, sizeof(app_dir)); |
1062 | 1215 … | |
1088 | 1241 … | case 't': typestr = argv[++i]; break; |
1089 | 1242 … | case 'n': noauth = true; break; |
1090 | 1243 … | case '4': ipv4_arg = true; break; |
1091 | 1244 … | case '6': ipv6_arg = true; break; |
| 1245 … | + case 'd': daemon = true; break; |
1092 | 1246 … | case 'a': passthrough = true; break; |
1093 | 1247 … | case 'l': no_newline = true; break; |
1094 | 1248 … | case 'r': raw = true; no_newline = true; break; |
1095 | 1249 … | case 'e': strings = true; break; |
1183 | 1337 … | s = -1; |
1184 | 1338 … | |
1185 | 1339 … | } else if (socket_path) { |
1186 | 1340 … | if (implied_tcp) errx(1, "-u option conflicts with host/port options"); |
1187 | | - s = unix_connect(socket_path); |
| 1341 … | + s = unix_connect(socket_path, daemon); |
1188 | 1342 … | if (s < 0) err(1, "unix_connect"); |
1189 | 1343 … | infd = outfd = s; |
1190 | 1344 … | |
1191 | 1345 … | } else if (!implied_tcp && !implied_auth) { |
1192 | 1346 … | char socket_path_buf[_POSIX_PATH_MAX]; |
1193 | | - rc = get_socket_path(socket_path_buf, sizeof(socket_path_buf), app_dir); |
| 1347 … | + rc = get_socket_path(socket_path_buf, sizeof(socket_path_buf), app_dir, daemon); |
1194 | 1348 … | if (rc < 0 && noauth) err(1, "get_socket_path"); |
1195 | | - if (rc < 0) goto do_tcp_connect; |
1196 | | - s = unix_connect(socket_path_buf); |
| 1349 … | + if (rc < 0) goto do_tcp; |
| 1350 … | + s = unix_connect(socket_path_buf, daemon); |
1197 | 1351 … | if (s < 0 && noauth) err(1, "unix_connect"); |
1198 | | - if (s < 0) goto do_tcp_connect; |
| 1352 … | + if (s < 0) goto do_tcp; |
1199 | 1353 … | noauth = true; |
1200 | 1354 … | infd = outfd = s; |
1201 | 1355 … | |
1202 | 1356 … | } else { |
1203 | | -do_tcp_connect: |
1204 | | - s = tcp_connect(host, port, ip_family); |
| 1357 … | +do_tcp: |
| 1358 … | + s = tcp_connect(host, port, ip_family, daemon); |
1205 | 1359 … | if (s < 0) err(1, "tcp_connect"); |
1206 | 1360 … | infd = outfd = s; |
1207 | 1361 … | } |
1208 | 1362 … | |
1211 | 1365 … | bs.s = s; |
1212 | 1366 … | bs.noauth = true; |
1213 | 1367 … | if (implied_auth) errx(1, "-n option conflicts with -k, -K, -c and -T options."); |
1214 | 1368 … | } else { |
1215 | | - shs_connect(s, infd, outfd, public_key, private_key, shs_cap_key, remote_key, &bs); |
| 1369 … | + shs_connect(s, infd, outfd, public_key, private_key, shs_cap_key, remote_key, &bs, !daemon, key_arg); |
1216 | 1370 … | } |
1217 | 1371 … | |
1218 | 1372 … | if (test) { |
1219 | 1373 … | rc = write_all(outfd, bs.encrypt_key, sizeof(bs.encrypt_key)); |