Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Makefile.in
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
atomicio.o compat.o fake-rfc2553.o \
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
dbmalloc.o \
gensignkey.o gendss.o genrsa.o
gensignkey.o gendss.o genrsa.o \
dbconfigure.o

SVROBJS=svr-kex.o svr-auth.o sshpty.o \
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
Expand Down Expand Up @@ -75,8 +76,8 @@ ifeq (@DROPBEAR_FUZZ@, 1)
else
dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
dropbearkeyobjs=$(COMMONOBJS) $(CLISVROBJS) $(KEYOBJS)
dropbearconvertobjs=$(COMMONOBJS) $(CLISVROBJS) $(CONVERTOBJS)
scpobjs=$(SCPOBJS)
endif

Expand Down
94 changes: 93 additions & 1 deletion crypto_desc.c
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
#include "crypto_desc.h"
#include "ltc_prng.h"
#include "ecc.h"
#include "dbconfigure.h"
#include "algo.h"

static void configure_algo(char *line, char *key, algo_type* algos);

#if DROPBEAR_LTC_PRNG
int dropbear_ltc_prng = -1;
#endif


/* Register the compiled in ciphers.
* This should be run before using any of the ciphers/hashes */
void crypto_init() {
Expand Down Expand Up @@ -73,3 +76,92 @@ void crypto_init() {
#endif
}

static void configure_algo(char *line, char *key, algo_type* algos)
{
char value[32][24] = {'\0'};
unsigned int count = 0, length;
unsigned int n, m, found = 0;

n = strlen(key);
while (line[n] == ' ' || line[n] == '\t')
n++;
if (line[n] == '\0') {
fprintf(stderr, "%s value is empty, skip setting.\n", key);
return;
}

length = strlen(line) + 1; /* we need to reach '\0' */
while (n < length && line[n] == ',')
n++; /* eat ',' in front of value */
m = n;
for (; n < length; n++) {
if (line[n] == ',') {
strncpy(value[count], &line[m], n - m);
value[count][sizeof(value[0])/sizeof(char) - 1] = '\0';
while (n + 1 < length && line[n + 1] == ',')
n++;
m = n + 1; /* skip ',' */
if (++count >= sizeof(value)/sizeof(value[0])) {
fprintf(stderr, "Too many %s value, do truncate.\n", key);
break;
}
} else if (line[n] == '\0' && m != n) {
strncpy(value[count++], &line[m], n - m);
break;
}
}
if (count > 0) {
for (n = 0; algos[n].name != NULL; n++) {
algos[n].usable = 0;
for (m = 0; m < count; m++) {
if (!strcmp(algos[n].name, value[m])) {
found = 1;
algos[n].usable = 1;
}
}
}
}

/* no match algorithm, restore all to usable? */
if (!found) {
fprintf(stderr, "No match of %s in configuration file, skip setting.\n", key);
for (n = 0; algos[n].name != NULL; n++)
algos[n].usable = 1;
}
}


/* Read from /etc/dropbear/crypto_config in order to use specified algorithm.
* Format:
* Ciphers algo1,algo2,algo3
* MACs algo1,algo2,algo3
* ...
*/
void crypto_configure(const char *config_file)
{
int i;
int ciphers_line = -1, macs_line = -1;
config_file_content *cfc = NULL;

cfc = read_config_file(config_file);
if (!cfc)
return;

for (i = 0; i < cfc->lines_count; i++) {
if (!strncmp("Ciphers", cfc->lines[i], strlen("Ciphers")) &&
strlen(cfc->lines[i]) > strlen("Ciphers") + 2) {
ciphers_line = i;
} else if (!strncmp("MACs", cfc->lines[i], strlen("MACs")) &&
strlen(cfc->lines[i]) > strlen("MACs") + 2) {
macs_line = i;
}
}

if (ciphers_line != -1)
configure_algo(cfc->lines[ciphers_line], "Ciphers", sshciphers);
if (macs_line != -1)
configure_algo(cfc->lines[macs_line], "MACs", sshhashes);

cfc->free(cfc);
}

1 change: 1 addition & 0 deletions crypto_desc.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define DROPBEAR_CRYPTO_DESC_H

void crypto_init(void);
void crypto_configure(const char *config_file);

extern int dropbear_ltc_prng;

Expand Down
134 changes: 134 additions & 0 deletions dbconfigure.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include "dbconfigure.h"

static int check_line_limit(const char *config_file, int line_length, int line_count);
static void free_config_file(config_file_content *self);
static config_file_content *init_config_file_content(void);

static int check_line_limit(const char *config_file, int line_length, int line_count)
{
if (line_length > CONFIG_FILE_LINE_MAX_LENGTH) {
fprintf(stderr, "[%s] line length too long\n", config_file);
return -1;
}
if (line_count > CONFIG_FILE_MAX_LINE) {
fprintf(stderr, "[%s] too many lines_count\n", config_file);
return -1;
}
return 0;
}

static void free_config_file(config_file_content *self)
{
int i;

if (self) {
if (self->lines) {
for (i = 0; i < self->lines_count; i++)
if (self->lines[i])
free(self->lines[i]);
free(self->lines);
}
free(self);
}
}

static config_file_content *init_config_file_content(void)
{
config_file_content *content;

content = (config_file_content*) m_malloc(sizeof(config_file_content));
content->free = free_config_file;

return content;
}

config_file_content *read_config_file(const char *config_file)
{
char content[CONFIG_FILE_CONTENT_SIZE] = {'\0'};
char buf[512];
config_file_content *cfc = NULL;
int fd, ret, len;
unsigned int i, j, count = 0;

if ((fd = open(config_file, O_RDONLY)) == -1)
return NULL;

while ((ret = read(fd, buf, sizeof(buf))) > 0) {
if (count + ret >= sizeof(content)) {
fprintf(stderr, "config file %s too large\n", config_file);
close(fd);
return NULL;
}
memcpy(&content[count], buf, ret);
count += ret;
}

cfc = init_config_file_content();
cfc->lines = (char**) m_malloc(CONFIG_FILE_MAX_LINE * sizeof(char*));
cfc->lines_count = 0;
for (i = 0, j = 0; i < count; i++) {
if (content[i] == '\n') {
if (i == 0) { /* some '\n' before text, eat them. */
while (i < count - 1 && content[i + 1] == '\n')
i++;
j = i + 1; /* let j point to a character after '\n' */
continue;
}
if (check_line_limit(config_file, i - j + 1, cfc->lines_count + 1) != 0)
goto error_free;
cfc->lines[cfc->lines_count++] = (char*) m_malloc((i - j + 1) * sizeof(char));
memcpy(cfc->lines[cfc->lines_count - 1], &content[j], i - j);
cfc->lines[cfc->lines_count - 1][i - j] = '\0';
while (i < count - 1 && content[i + 1] == '\n')
i++; /* eat '\n' after a line */
j = i + 1;
} else if (content[i] == '#') {
unsigned int pre_i = i;
while (i < count - 1) {
if (content[i + 1] != '\n' && content[i + 1] != '#' && content[i] == '\n')
break;
else
i++; /* eat comment */
}
if (pre_i != j) { /* comment after text in one line, ie: abcd #comment */
if (check_line_limit(config_file, pre_i - j + 1, cfc->lines_count + 1) != 0)
goto error_free;
cfc->lines[cfc->lines_count++] = (char*) m_malloc((pre_i - j + 1) * sizeof(char));
memcpy(cfc->lines[cfc->lines_count - 1], &content[j], pre_i - j);
cfc->lines[cfc->lines_count - 1][pre_i - j] = '\0';
}
if (i == count - 1) /* reach end */
break;
else
j = i + 1;
} else if (i == count - 1) {
if (check_line_limit(config_file, i - j + 2, cfc->lines_count + 1) != 0)
goto error_free;
cfc->lines[cfc->lines_count++] = (char*) m_malloc((i - j + 2) * sizeof(char));
memcpy(cfc->lines[cfc->lines_count - 1], &content[j], i - j + 1);
cfc->lines[cfc->lines_count - 1][i + 1] = '\0';
break;
}

if (lines_cnt > 1) {
len = strlen(lines[lines_cnt - 1]);

if (len >= 1 && lines[lines_cnt - 1][len - 1] == '\r') {
lines[lines_cnt - 1][len - 1] = '\0';
}
}
}

if (cfc->lines_count == 0) {
goto error_free;
} else {
close(fd);
return cfc;
}

error_free:
cfc->free(cfc);
close(fd);
return NULL;
}

24 changes: 24 additions & 0 deletions dbconfigure.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef CONFIGURE_H_
#define CONFIGURE_H_

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "dbmalloc.h"


#define CONFIG_FILE_MAX_LINE 256
#define CONFIG_FILE_LINE_MAX_LENGTH 512
#define CONFIG_FILE_CONTENT_SIZE (CONFIG_FILE_MAX_LINE * CONFIG_FILE_LINE_MAX_LENGTH)

typedef struct Config_file_content {
char **lines;
int lines_count; /* exclude empty line and comment line */
void (*free) (struct Config_file_content *self);
} config_file_content;

config_file_content *read_config_file(const char *config_file);

#endif
2 changes: 2 additions & 0 deletions svr-main.c
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ static void commonsetup() {

crypto_init();

crypto_configure("/etc/dropbear/crypto_config");

/* Now we can setup the hostkeys - needs to be after logging is on,
* otherwise we might end up blatting error messages to the socket */
load_all_hostkeys();
Expand Down