Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add -U flag for customizing authorized keys file path #35

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
3 changes: 3 additions & 0 deletions dropbear.8
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ or automatically with the '-R' option. See "Host Key Files" below.
.B \-R
Generate hostkeys automatically. See "Host Key Files" below.
.TP
.B \-U \fIauthorized_keys
Path to file containing authorized user keys inside the user home directory. Defaults to '.ssh/authorized_keys'.
.TP
.B \-F
Don't fork into background.
.TP
Expand Down
2 changes: 2 additions & 0 deletions runopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ typedef struct svr_runopts {

char * forced_command;

char * authkeysfile;

} svr_runopts;

extern svr_runopts svr_opts;
Expand Down
92 changes: 46 additions & 46 deletions svr-authpubkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include "ssh.h"
#include "packet.h"
#include "algo.h"
#include "runopts.h"

#if DROPBEAR_SVR_PUBKEY_AUTH

Expand All @@ -72,7 +73,7 @@

static int checkpubkey(char* algo, unsigned int algolen,
unsigned char* keyblob, unsigned int keybloblen);
static int checkpubkeyperms(void);
static int checkpubkeyperms(char *filename, char *base);
static void send_msg_userauth_pk_ok(char* algo, unsigned int algolen,
unsigned char* keyblob, unsigned int keybloblen);
static int checkfileperm(char * filename);
Expand Down Expand Up @@ -196,6 +197,7 @@ static int checkpubkey(char* algo, unsigned int algolen,

FILE * authfile = NULL;
char * filename = NULL;
char * relfilename = NULL;
int ret = DROPBEAR_FAILURE;
buffer * line = NULL;
unsigned int len, pos;
Expand All @@ -212,21 +214,23 @@ static int checkpubkey(char* algo, unsigned int algolen,
goto out;
}

/* check file permissions, also whether file exists */
if (checkpubkeyperms() == DROPBEAR_FAILURE) {
relfilename = ( svr_opts.authkeysfile
? svr_opts.authkeysfile
: ".ssh/authorized_keys" );
if (relfilename[0] == '/') { /* name is absolute */
filename = m_strdup(relfilename);
}
else {
len = strlen(ses.authstate.pw_dir) + strlen(relfilename) + 2;
filename = m_malloc(len);
snprintf(filename, len, "%s/%s", ses.authstate.pw_dir, relfilename);
}

if (checkpubkeyperms(filename, ses.authstate.pw_dir) != DROPBEAR_SUCCESS) {
TRACE(("bad authorized_keys permissions, or file doesn't exist"))
goto out;
}

/* we don't need to check pw and pw_dir for validity, since
* its been done in checkpubkeyperms. */
len = strlen(ses.authstate.pw_dir);
/* allocate max required pathname storage,
* = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
filename = m_malloc(len + 22);
snprintf(filename, len + 22, "%s/.ssh/authorized_keys",
ses.authstate.pw_dir);

/* open the file */
authfile = fopen(filename, "r");
if (authfile == NULL) {
Expand Down Expand Up @@ -362,52 +366,47 @@ static int checkpubkey(char* algo, unsigned int algolen,

/* Returns DROPBEAR_SUCCESS if file permissions for pubkeys are ok,
* DROPBEAR_FAILURE otherwise.
* Checks that the user's homedir, ~/.ssh, and
* ~/.ssh/authorized_keys are all owned by either root or the user, and are
* Checks filename and its parent directories recursively until the
* base directory (usually ~/) or one of its ancestors (up to /) is
* reached.
* The files and directories must be all owned by root or the user, and be
* g-w, o-w */
static int checkpubkeyperms() {

char* filename = NULL;
static int checkpubkeyperms(char *filename, char *base) {
char* path = NULL;
int ret = DROPBEAR_FAILURE;
unsigned int len;

TRACE(("enter checkpubkeyperms"))
TRACE(("enter checkpubkeyperms(%s, %s)", filename, base))

if (ses.authstate.pw_dir == NULL) {
if ((base == NULL) || (base[0] != '/') ||
(filename == NULL) || (filename[0] != '/')) {
/* both filename and base must be absolute paths */
goto out;
}

if ((len = strlen(ses.authstate.pw_dir)) == 0) {
goto out;
}

/* allocate max required pathname storage,
* = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
filename = m_malloc(len + 22);
strncpy(filename, ses.authstate.pw_dir, len+1);

/* check ~ */
if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
goto out;
}
len = strlen(filename);
path = m_strdup(filename);

/* check ~/.ssh */
strncat(filename, "/.ssh", 5); /* strlen("/.ssh") == 5 */
if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
goto out;
}
while (checkfileperm(len ? path : "/") == DROPBEAR_SUCCESS) {
/* check if we are on base trail and if this is the
* case, return success */
if ((strncmp(base, path, len) == 0) &&
(!len || (base[len] == '\0') || (base[len] == '/'))) {
ret = DROPBEAR_SUCCESS;
break;
}

/* now check ~/.ssh/authorized_keys */
strncat(filename, "/authorized_keys", 16);
if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
goto out;
/* look for parent directory */
while (--len) {
if (path[len] == '/') {
path[len] = '\0';
break;
}
}
}

/* file looks ok, return success */
ret = DROPBEAR_SUCCESS;

out:
m_free(filename);
m_free(path);

TRACE(("leave checkpubkeyperms"))
return ret;
Expand All @@ -433,7 +432,8 @@ static int checkfileperm(char * filename) {
TRACE(("wrong ownership"))
}
/* check permissions - don't want group or others +w */
if (filestat.st_mode & (S_IWGRP | S_IWOTH)) {
if ((filestat.st_mode & (S_IWGRP | S_IWOTH)) &&
!(S_ISDIR(filestat.st_mode) && (filestat.st_mode & S_ISVTX))) {
badperm = 1;
TRACE(("wrong perms"))
}
Expand Down
10 changes: 10 additions & 0 deletions svr-runopts.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ void svr_getopts(int argc, char ** argv) {
char* keepalive_arg = NULL;
char* idle_timeout_arg = NULL;
char* keyfile = NULL;
char* authkeysfile = NULL;
char c;


Expand All @@ -137,6 +138,8 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.hostkey = NULL;
svr_opts.delay_hostkey = 0;
svr_opts.pidfile = DROPBEAR_PIDFILE;
svr_opts.authkeysfile = NULL;

#if DROPBEAR_SVR_LOCALTCPFWD
svr_opts.nolocaltcp = 0;
#endif
Expand Down Expand Up @@ -253,6 +256,9 @@ void svr_getopts(int argc, char ** argv) {
case 'u':
/* backwards compatibility with old urandom option */
break;
case 'U':
next = &authkeysfile;
break;
#if DEBUG_TRACE
case 'v':
debug_trace = 1;
Expand Down Expand Up @@ -295,6 +301,10 @@ void svr_getopts(int argc, char ** argv) {
addhostkey(keyfile);
keyfile = NULL;
}
if (authkeysfile) {
svr_opts.authkeysfile = m_strdup(authkeysfile);
authkeysfile = NULL;
}
}
}

Expand Down