Mercurial > dropbear
view svr-agentfwd.c @ 1672:3a97f14c0235
Add Chacha20-Poly1305, AES128-GCM and AES256-GCM support (#93)
* Add Chacha20-Poly1305 authenticated encryption
* Add general AEAD approach.
* Add [email protected] algo using LibTomCrypt chacha and
poly1305 routines.
Chacha20-Poly1305 is generally faster than AES256 on CPU w/o dedicated
AES instructions, having the same key size.
Compiling in will add ~5,5kB to binary size on x86-64.
function old new delta
chacha_crypt - 1397 +1397
_poly1305_block - 608 +608
poly1305_done - 595 +595
dropbear_chachapoly_crypt - 457 +457
.rodata 26976 27392 +416
poly1305_process - 290 +290
poly1305_init - 221 +221
chacha_setup - 218 +218
encrypt_packet 1068 1270 +202
dropbear_chachapoly_getlength - 147 +147
decrypt_packet 756 897 +141
chacha_ivctr64 - 137 +137
read_packet 543 637 +94
dropbear_chachapoly_start - 94 +94
read_kex_algos 792 880 +88
chacha_keystream - 69 +69
dropbear_mode_chachapoly - 48 +48
sshciphers 280 320 +40
dropbear_mode_none 24 48 +24
dropbear_mode_ctr 24 48 +24
dropbear_mode_cbc 24 48 +24
dropbear_chachapoly_mac - 24 +24
dropbear_chachapoly - 24 +24
gen_new_keys 848 854 +6
------------------------------------------------------------------------------
(add/remove: 14/0 grow/shrink: 10/0 up/down: 5388/0) Total: 5388 bytes
* Add AES128-GCM and AES256-GCM authenticated encryption
* Add general AES-GCM mode.
* Add [email protected] and [email protected] algo using
LibTomCrypt gcm routines.
AES-GCM is combination of AES CTR mode and GHASH, slower than AES-CTR on
CPU w/o dedicated AES/GHASH instructions therefore disabled by default.
Compiling in will add ~6kB to binary size on x86-64.
function old new delta
gcm_process - 1060 +1060
.rodata 26976 27808 +832
gcm_gf_mult - 820 +820
gcm_add_aad - 660 +660
gcm_shift_table - 512 +512
gcm_done - 471 +471
gcm_add_iv - 384 +384
gcm_init - 347 +347
dropbear_gcm_crypt - 309 +309
encrypt_packet 1068 1270 +202
decrypt_packet 756 897 +141
gcm_reset - 118 +118
read_packet 543 637 +94
read_kex_algos 792 880 +88
sshciphers 280 360 +80
gcm_mult_h - 80 +80
dropbear_gcm_start - 62 +62
dropbear_mode_gcm - 48 +48
dropbear_mode_none 24 48 +24
dropbear_mode_ctr 24 48 +24
dropbear_mode_cbc 24 48 +24
dropbear_ghash - 24 +24
dropbear_gcm_getlength - 24 +24
gen_new_keys 848 854 +6
------------------------------------------------------------------------------
(add/remove: 14/0 grow/shrink: 10/0 up/down: 6434/0) Total: 6434 bytes
author | Vladislav Grishenko <themiron@users.noreply.github.com> |
---|---|
date | Mon, 25 May 2020 20:50:25 +0500 |
parents | 592a18dac250 |
children | a7cc3332d8ab |
line wrap: on
line source
/* * Dropbear - a SSH2 server * * Copyright (c) 2002,2003 Matt Johnston * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* This file (agentfwd.c) handles authentication agent forwarding, for OpenSSH * style agents. */ #include "includes.h" #if DROPBEAR_SVR_AGENTFWD #include "agentfwd.h" #include "session.h" #include "ssh.h" #include "dbutil.h" #include "chansession.h" #include "channel.h" #include "packet.h" #include "buffer.h" #include "dbrandom.h" #include "listener.h" #include "auth.h" #define AGENTDIRPREFIX "/tmp/dropbear-" static int send_msg_channel_open_agent(int fd); static int bindagent(int fd, struct ChanSess * chansess); static void agentaccept(const struct Listener * listener, int sock); /* Handles client requests to start agent forwarding, sets up listening socket. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ int svr_agentreq(struct ChanSess * chansess) { int fd = -1; if (!svr_pubkey_allows_agentfwd()) { return DROPBEAR_FAILURE; } if (chansess->agentlistener != NULL) { return DROPBEAR_FAILURE; } /* create listening socket */ fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { goto fail; } /* create the unix socket dir and file */ if (bindagent(fd, chansess) == DROPBEAR_FAILURE) { goto fail; } /* listen */ if (listen(fd, 20) < 0) { goto fail; } /* set non-blocking */ setnonblocking(fd); /* pass if off to listener */ chansess->agentlistener = new_listener( &fd, 1, 0, chansess, agentaccept, NULL); if (chansess->agentlistener == NULL) { goto fail; } return DROPBEAR_SUCCESS; fail: m_close(fd); /* cleanup */ svr_agentcleanup(chansess); return DROPBEAR_FAILURE; } /* accepts a connection on the forwarded socket and opens a new channel for it * back to the client */ /* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ static void agentaccept(const struct Listener *UNUSED(listener), int sock) { int fd; fd = accept(sock, NULL, NULL); if (fd < 0) { TRACE(("accept failed")) return; } if (send_msg_channel_open_agent(fd) != DROPBEAR_SUCCESS) { close(fd); } } /* set up the environment variable pointing to the socket. This is called * just before command/shell execution, after dropping privileges */ void svr_agentset(const struct ChanSess * chansess) { char *path = NULL; int len; if (chansess->agentlistener == NULL) { return; } /* 2 for "/" and "\0" */ len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2; path = m_malloc(len); snprintf(path, len, "%s/%s", chansess->agentdir, chansess->agentfile); addnewvar("SSH_AUTH_SOCK", path); m_free(path); } /* close the socket, remove the socket-file */ void svr_agentcleanup(struct ChanSess * chansess) { char *path = NULL; uid_t uid; gid_t gid; int len; if (chansess->agentlistener != NULL) { remove_listener(chansess->agentlistener); chansess->agentlistener = NULL; } if (chansess->agentfile != NULL && chansess->agentdir != NULL) { #if DROPBEAR_SVR_MULTIUSER /* Remove the dir as the user. That way they can't cause problems except * for themselves */ uid = getuid(); gid = getgid(); if ((setegid(ses.authstate.pw_gid)) < 0 || (seteuid(ses.authstate.pw_uid)) < 0) { dropbear_exit("Failed to set euid"); } #endif /* 2 for "/" and "\0" */ len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2; path = m_malloc(len); snprintf(path, len, "%s/%s", chansess->agentdir, chansess->agentfile); unlink(path); m_free(path); rmdir(chansess->agentdir); #if DROPBEAR_SVR_MULTIUSER if ((seteuid(uid)) < 0 || (setegid(gid)) < 0) { dropbear_exit("Failed to revert euid"); } #endif m_free(chansess->agentfile); m_free(chansess->agentdir); } } static const struct ChanType chan_svr_agent = { 0, /* sepfds */ "[email protected]", NULL, NULL, NULL, NULL, NULL }; /* helper for accepting an agent request */ static int send_msg_channel_open_agent(int fd) { if (send_msg_channel_open_init(fd, &chan_svr_agent) == DROPBEAR_SUCCESS) { encrypt_packet(); return DROPBEAR_SUCCESS; } else { return DROPBEAR_FAILURE; } } /* helper for creating the agent socket-file returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ static int bindagent(int fd, struct ChanSess * chansess) { struct sockaddr_un addr; unsigned int prefix; char path[(sizeof(addr.sun_path)-1)/2], sockfile[(sizeof(addr.sun_path)-1)/2]; mode_t mode; int i; uid_t uid; gid_t gid; int ret = DROPBEAR_FAILURE; #if DROPBEAR_SVR_MULTIUSER /* drop to user privs to make the dir/file */ uid = getuid(); gid = getgid(); if ((setegid(ses.authstate.pw_gid)) < 0 || (seteuid(ses.authstate.pw_uid)) < 0) { dropbear_exit("Failed to set euid"); } #endif memset((void*)&addr, 0x0, sizeof(addr)); addr.sun_family = AF_UNIX; mode = S_IRWXU; for (i = 0; i < 20; i++) { genrandom((unsigned char*)&prefix, sizeof(prefix)); /* we want 32 bits (8 hex digits) - "/tmp/dropbear-f19c62c0" */ snprintf(path, sizeof(path), AGENTDIRPREFIX "%.8x", prefix); if (mkdir(path, mode) == 0) { goto bindsocket; } if (errno != EEXIST) { break; } } /* couldn't make a dir */ goto out; bindsocket: /* Format is "/tmp/dropbear-0246dead/auth-d00f7654-23". * The "23" is the file desc, the random data is to avoid collisions * between subsequent user processes reusing socket fds (odds are now * 1/(2^64) */ genrandom((unsigned char*)&prefix, sizeof(prefix)); snprintf(sockfile, sizeof(sockfile), "auth-%.8x-%d", prefix, fd); snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", path, sockfile); if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { chansess->agentdir = m_strdup(path); chansess->agentfile = m_strdup(sockfile); ret = DROPBEAR_SUCCESS; } out: #if DROPBEAR_SVR_MULTIUSER if ((seteuid(uid)) < 0 || (setegid(gid)) < 0) { dropbear_exit("Failed to revert euid"); } #endif return ret; } #endif