/*
- * Copyright (C) 1997-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2014 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file command.c Client authentication and server commands. */
+#include <netinet/in.h>
+#include <sys/socket.h>
#include <regex.h>
#include <signal.h>
#include <sys/types.h>
#include <osl.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
#include "para.h"
#include "error.h"
char mtime[30] = "";
char *status, *flags; /* vss status info */
/* nobody updates our version of "now" */
- char *ut = get_server_uptime_str(NULL);
long offset = (nmmd->offset + 500) / 1000;
struct timeval current_time;
struct tm mtime_tm;
(long unsigned)current_time.tv_usec);
free(flags);
free(status);
- free(ut);
*result = b.buf;
return b.offset;
}
para_sigaction(SIGHUP, SIG_DFL);
}
-static int parse_auth_request(char *buf, int len, struct user **u)
+struct connection_features {
+ bool sideband_requested;
+ bool aes_ctr128_requested;
+};
+
+static int parse_auth_request(char *buf, int len, struct user **u,
+ struct connection_features *cf)
{
int ret;
char *p, *username, **features = NULL;
size_t auth_rq_len = strlen(AUTH_REQUEST_MSG);
- bool sideband_requested = false;
*u = NULL;
+ memset(cf, 0, sizeof(*cf));
if (len < auth_rq_len + 2)
return -E_AUTH_REQUEST;
if (strncmp(buf, AUTH_REQUEST_MSG, auth_rq_len) != 0)
create_argv(p, ",", &features);
for (i = 0; features[i]; i++) {
if (strcmp(features[i], "sideband") == 0)
- sideband_requested = true;
+ cf->sideband_requested = true;
+ else if (strcmp(features[i], "aes_ctr128") == 0)
+ cf->aes_ctr128_requested = true;
else {
ret = -E_BAD_FEATURE;
goto out;
}
}
}
- if (sideband_requested == false) { /* sideband is mandatory */
- PARA_ERROR_LOG("client did not request sideband\n");
- ret = -E_BAD_FEATURE;
- goto out;
- }
PARA_DEBUG_LOG("received auth request for user %s\n", username);
*u = lookup_user(username);
ret = 1;
int ret;
unsigned char rand_buf[CHALLENGE_SIZE + 2 * SESSION_KEY_LEN];
unsigned char challenge_hash[HASH_SIZE];
- char *p, *command = NULL, *buf = para_malloc(HANDSHAKE_BUFSIZE) /* must be on the heap */;
+ char *command = NULL, *buf = para_malloc(HANDSHAKE_BUFSIZE) /* must be on the heap */;
size_t numbytes;
struct command_context cc_struct = {.peer = peername}, *cc = &cc_struct;
struct iovec iov;
+ struct connection_features cf;
cc->scc.fd = fd;
reset_signals();
/* send Welcome message */
ret = write_va_buffer(fd, "This is para_server, version "
PACKAGE_VERSION ".\n"
- "Features: sideband\n"
+ "Features: sideband,aes_ctr128\n"
);
if (ret < 0)
goto net_err;
ret = recv_buffer(fd, buf, HANDSHAKE_BUFSIZE);
if (ret < 0)
goto net_err;
- ret = parse_auth_request(buf, ret, &cc->u);
+ ret = parse_auth_request(buf, ret, &cc->u, &cf);
if (ret < 0)
goto net_err;
- p = buf + strlen(AUTH_REQUEST_MSG);
- PARA_DEBUG_LOG("received auth request for user %s\n", p);
- cc->u = lookup_user(p);
+ if (!cf.sideband_requested) { /* sideband is mandatory */
+ PARA_ERROR_LOG("client did not request sideband\n");
+ ret = -E_BAD_FEATURE;
+ goto net_err;
+ }
if (cc->u) {
get_random_bytes_or_die(rand_buf, sizeof(rand_buf));
ret = pub_encrypt(cc->u->pubkey, rand_buf, sizeof(rand_buf),
numbytes = 256;
get_random_bytes_or_die((unsigned char *)buf, numbytes);
}
- PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n",
+ PARA_DEBUG_LOG("sending %u byte challenge + session key (%zu bytes)\n",
CHALLENGE_SIZE, numbytes);
ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false);
buf = NULL;
alarm(0);
PARA_INFO_LOG("good auth for %s\n", cc->u->name);
/* init stream cipher keys with the second part of the random buffer */
- cc->scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN);
- cc->scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, SESSION_KEY_LEN);
+ cc->scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN,
+ cf.aes_ctr128_requested);
+ cc->scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN,
+ SESSION_KEY_LEN, cf.aes_ctr128_requested);
ret = send_sb(&cc->scc, NULL, 0, SBD_PROCEED, false);
if (ret < 0)
goto net_err;