Hi Matt,

This is a patch for the serverpart of dropbear:
- cmdline option -U <username>  forcing all user logins to use 1 fixed user
- If used, the original user will be saved in env var SSH_ORGUSER
- if a public key is used to grant a user access, the info part of the ssh
key will be saved in env.var SSD_PUBKEYINFO
  ssh keylayout :   <opts> <keytype> <keydata> <info>

So if you do:  dropbear -U osuser
and : ssh root@mysystem  , user will login as osuser
and the env var SSH_ORGUSER will be set to "root"

I use this with ssh pubkey authentication only, and the SSH_PUBINFO gives
me information in my .profile which public key (=user) was used.


patchfile is against version 2014.65

Hans
--- a/auth.h    2014-08-08 13:40:46.000000000 +0000
+++ b/auth.h    2014-08-25 13:59:19.389599685 +0000
@@ -122,6 +122,8 @@ struct AuthState {
 #ifdef ENABLE_SVR_PUBKEY_OPTIONS
        struct PubKeyOptions* pubkey_options;
 #endif
+       char *org_username;
+       char *pubkey_info;
 };
 
 #ifdef ENABLE_SVR_PUBKEY_OPTIONS
--- a/runopts.h 2014-08-08 13:40:47.000000000 +0000
+++ b/runopts.h 2014-08-25 13:32:18.220491735 +0000
@@ -86,6 +86,7 @@ typedef struct svr_runopts {
 #endif
 
        int norootlogin;
+       char *forceuser;
 
        int noauthpass;
        int norootpass;
--- a/svr-auth.c        2014-08-08 13:40:47.000000000 +0000
+++ b/svr-auth.c        2014-08-25 13:58:16.972524805 +0000
@@ -46,6 +46,8 @@ void svr_authinitialise() {
        ses.authstate.pw_dir = NULL;
        ses.authstate.pw_shell = NULL;
        ses.authstate.pw_passwd = NULL;
+       ses.authstate.org_username = NULL;
+       ses.authstate.pubkey_info = NULL;
        authclear();
        
 }
@@ -76,6 +78,12 @@ static void authclear() {
        if (ses.authstate.pw_passwd) {
                m_free(ses.authstate.pw_passwd);
        }
+       if (ses.authstate.org_username) {
+               m_free(ses.authstate.org_username);
+       }
+       if (ses.authstate.pubkey_info) {
+               m_free(ses.authstate.pubkey_info);
+       }
        
 }
 
@@ -134,6 +142,16 @@ void recv_msg_userauth_request() {
                m_free(methodname);
                dropbear_exit("unknown service in auth");
        }
+       
+       /* if we need to force logins to a specific user, this is a good place 
to do it. */
+       if (svr_opts.forceuser) {
+               /* first save original user */
+               ses.authstate.org_username = m_strdup(username);
+               /* now point to the user we want to have */
+               m_free(username);
+               username=m_strdup(svr_opts.forceuser);                          
  
+               userlen=strlen(username);
+       }
 
        /* check username is good before continuing. 
         * the 'incrfail' varies depending on the auth method to
@@ -291,6 +309,10 @@ static int checkusername(unsigned char *
         * should return some standard shells like "/bin/sh" and "/bin/csh" 
(this
         * is platform-specific) */
        setusershell();
+       /* ignore shell check if user is forced */
+       if (svr_opts.forceuser) {
+               goto goodshell;
+       }
        while ((listshell = getusershell()) != NULL) {
                TRACE(("test shell is '%s'", listshell))
                if (strcmp(listshell, usershell) == 0) {
--- a/svr-authpubkey.c  2014-08-08 13:40:47.000000000 +0000
+++ b/svr-authpubkey.c  2014-08-25 14:02:18.220481679 +0000
@@ -188,7 +188,7 @@ static int checkpubkey(unsigned char* al
        char * filename = NULL;
        int ret = DROPBEAR_FAILURE;
        buffer * line = NULL;
-       unsigned int len, pos;
+       unsigned int len, pos, infolen, infopos;
        buffer * options_buf = NULL;
        int line_num;
 
@@ -310,11 +310,17 @@ static int checkpubkey(unsigned char* al
                        continue;
                }
 
-               /* truncate the line at the space after the base64 data */
+               /* findout the length of the base64 data */
                pos = line->pos;
                for (len = 0; line->pos < line->len; len++) {
                        if (buf_getbyte(line) == ' ') break;
                }       
+               /* findout the length of the public key info */
+               infopos = line->pos;
+               for (infolen = 0; line->pos < line->len; infolen++) {
+                       if (buf_getbyte(line) == ' ') break;
+               }       
+               /* truncate the line at the space after the base64 data */
                buf_setpos(line, pos);
                buf_setlen(line, line->pos + len);
 
@@ -327,6 +333,12 @@ static int checkpubkey(unsigned char* al
                }
 
                if (ret == DROPBEAR_SUCCESS) {
+                       /* save the (optional) public key information */
+                       if (infolen) {
+                               ses.authstate.pubkey_info = m_malloc(infolen + 
1);
+                               strncpy(ses.authstate.pubkey_info, 
&line->data[infopos], infolen);
+                               ses.authstate.pubkey_info[infolen]='\0';
+                       }
                        break;
                }
 
--- a/svr-chansession.c 2014-08-08 13:40:47.000000000 +0000
+++ b/svr-chansession.c 2014-08-25 07:48:05.818351524 +0000
@@ -941,6 +941,14 @@ static void execchild(void *user_data) {
                addnewvar("SSH_CONNECTION", chansess->connection_string);
        }
        
+       if (ses.authstate.org_username != NULL) {
+               addnewvar("SSH_ORGUSER", ses.authstate.org_username);
+       }
+       
+       if (ses.authstate.pubkey_info != NULL) {
+               addnewvar("SSH_PUBKEYINFO", ses.authstate.pubkey_info);
+       }
+       
 #ifdef ENABLE_SVR_PUBKEY_OPTIONS
        if (chansess->original_command) {
                addnewvar("SSH_ORIGINAL_COMMAND", chansess->original_command);
--- a/svr-runopts.c     2014-08-08 13:40:47.000000000 +0000
+++ b/svr-runopts.c     2014-08-24 18:15:56.947584018 +0000
@@ -67,6 +67,7 @@ static void printhelp(const char * progn
 #ifdef DO_MOTD
                                        "-m             Don't display the motd 
on login\n"
 #endif
+                                       "-U username    Force all logins to 
this user\n"
                                        "-w             Disallow root logins\n"
 #if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH)
                                        "-s             Disable password 
logins\n"
@@ -126,6 +127,7 @@ void svr_getopts(int argc, char ** argv)
        svr_opts.banner = NULL;
        svr_opts.forkbg = 1;
        svr_opts.norootlogin = 0;
+       svr_opts.forceuser = NULL;
        svr_opts.noauthpass = 0;
        svr_opts.norootpass = 0;
        svr_opts.allowblankpass = 0;
@@ -232,6 +234,9 @@ void svr_getopts(int argc, char ** argv)
                                        svr_opts.domotd = 0;
                                        break;
 #endif
+                               case 'U':
+                                       next = &svr_opts.forceuser;
+                                       break;
                                case 'w':
                                        svr_opts.norootlogin = 1;
                                        break;

Reply via email to