src/svr-authpubkey.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) --- a/src/svr-authpubkey.c +++ b/src/svr-authpubkey.c @@ -79,6 +79,39 @@ static void send_msg_userauth_pk_ok(cons const unsigned char* keyblob, unsigned int keybloblen); static int checkfileperm(char * filename); +static const char * const global_authkeys_dir = "/etc/dropbear"; +/* strlen(global_authkeys_dir) */ +#define n_global_authkeys_dir 13 +static const char * const authkeys_file = "authorized_keys"; +/* strlen(authkeys_file) */ +#define n_authkeys_file 15 + +/* OpenWrt-specific: + use OpenWrt' global authorized keys directory if: + 1. logging as uid 0 (typically root). + 2. "svr_opts.authorized_keys_dir" is set to default i.e. no "-D" option was specified + OR + "-D" option is specified as homedir-relative path ("~" or "~/...") + OR + "-D" option is specified as "/etc/dropbear". + */ +static int is_openwrt_defaults(void) { + if (ses.authstate.pw_uid != 0) return 0; + switch (svr_opts.authorized_keys_dir[0]) { + case '~': + switch (svr_opts.authorized_keys_dir[1]) { + case 0: + return 1; + case '/': + return 1; + } + break; + case '/': + return (strcmp(svr_opts.authorized_keys_dir, global_authkeys_dir) == 0); + } + return 0; +} + /* process a pubkey auth request, sending success or failure message as * appropriate */ void svr_auth_pubkey(int valid_user) { @@ -439,16 +472,22 @@ out: static char *authorized_keys_filepath() { size_t len = 0; char *pathname = NULL, *dir = NULL; - const char *filename = "authorized_keys"; + + if (is_openwrt_defaults()) { + len = n_global_authkeys_dir + n_authkeys_file + 2; + pathname = m_malloc(len); + snprintf(pathname, len, "%s/%s", global_authkeys_dir, authkeys_file); + return pathname; + } dir = expand_homedir_path_home(svr_opts.authorized_keys_dir, ses.authstate.pw_dir); /* allocate max required pathname storage, * = dir + "/" + "authorized_keys" + '\0' */; - len = strlen(dir) + strlen(filename) + 2; + len = strlen(dir) + n_authkeys_file + 2; pathname = m_malloc(len); - snprintf(pathname, len, "%s/%s", dir, filename); + snprintf(pathname, len, "%s/%s", dir, authkeys_file); m_free(dir); return pathname; } @@ -549,11 +588,23 @@ out: * When this path is inside the user's home dir it checks up to and including * the home dir, otherwise it checks every path component. */ static int checkpubkeyperms() { - char *path = authorized_keys_filepath(), *sep = NULL; + char *path = NULL, *sep = NULL; int ret = DROPBEAR_SUCCESS; + if (is_openwrt_defaults()) { + TRACE(("enter checkpubkeyperms/openwrt")) + if (checkfileperm(global_authkeys_dir) != DROPBEAR_SUCCESS) { + TRACE(("checkpubkeyperms: bad perm on %s", global_authkeys_dir)) + ret = DROPBEAR_FAILURE; + } + TRACE(("leave checkpubkeyperms/openwrt")) + return ret; + } + TRACE(("enter checkpubkeyperms")) + path = authorized_keys_filepath(); + /* Walk back up path checking permissions, stopping at either homedir, * or root if the path is outside of the homedir. */ while ((sep = strrchr(path, '/')) != NULL) {