From 674a60748884dc55ee7091b7c23a41240e75f73c Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 1 Jun 2004 02:46:09 +0000 Subject: Makefile.in contains updated files required --HG-- extra : convert_revision : cc8a8c49dc70e632c352853a39801089b08149be --- random.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 random.c (limited to 'random.c') diff --git a/random.c b/random.c new file mode 100644 index 0000000..725b29c --- /dev/null +++ b/random.c @@ -0,0 +1,178 @@ +/* + * 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. */ + +#include "includes.h" +#include "buffer.h" +#include "dbutil.h" + +int donerandinit = 0; + +/* this is used to generate unique output from the same hashpool */ +unsigned int counter = 0; +#define MAX_COUNTER 1000000/* the max value for the counter, so it won't loop */ + +unsigned char hashpool[SHA1_HASH_SIZE]; + +#define INIT_SEED_SIZE 32 /* 256 bits */ + +static void readrand(unsigned char* buf, unsigned int buflen); + +/* The basic setup is we read some data from DEV_URANDOM or PRNGD and hash it + * into hashpool. To read data, we hash together current hashpool contents, + * and a counter. We feed more data in by hashing the current pool and new + * data into the pool. + * + * It is important to ensure that counter doesn't wrap around before we + * feed in new entropy. + * + */ + +static void readrand(unsigned char* buf, unsigned int buflen) { + + int readfd; + unsigned int readpos; + int readlen; +#ifdef DROPBEAR_EGD + struct sockaddr_un egdsock; + char egdcmd[2]; +#endif + +#ifdef DROPBEAR_DEV_URANDOM + readfd = open(DEV_URANDOM, O_RDONLY); + if (!readfd) { + dropbear_exit("couldn't open random device"); + } +#endif + +#ifdef DROPBEAR_EGD + memset((void*)&egdsock, 0x0, sizeof(egdsock)); + egdsock.sun_family = AF_UNIX; + strlcpy(egdsock.sun_path, DROPBEAR_EGD_SOCKET, + sizeof(egdsock.sun_path)); + + if ((readfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + dropbear_exit("couldn't open random device"); + } + /* todo - try various common locations */ + if (connect(readfd, (struct sockaddr*)&egdsock, + sizeof(struct sockaddr_un)) < 0) { + dropbear_exit("couldn't open random device"); + } + + if (buflen > 255) + dropbear_exit("can't request more than 255 bytes from egd"); + egdcmd[0] = 0x02; /* blocking read */ + egdcmd[1] = (unsigned char)buflen; + if (write(readfd, egdcmd, 2) < 0) + dropbear_exit("can't send command to egd"); +#endif + + /* read the actual random data */ + readpos = 0; + do { + readlen = read(readfd, &buf[readpos], buflen - readpos); + if (readlen <= 0) { + if (readlen < 0 && errno == EINTR) { + continue; + } + dropbear_exit("error reading random source"); + } + readpos += readlen; + } while (readpos < buflen); + + close (readfd); +} + +/* initialise the prng from /dev/urandom or prngd */ +void seedrandom() { + + unsigned char readbuf[INIT_SEED_SIZE]; + + hash_state hs; + + /* initialise so compilers will be happy about hashing it */ + if (!donerandinit) { + m_burn(hashpool, sizeof(hashpool)); + } + + /* get the seed data */ + readrand(readbuf, sizeof(readbuf)); + + /* hash in the new seed data */ + sha1_init(&hs); + sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); + sha1_process(&hs, (void*)readbuf, sizeof(readbuf)); + sha1_done(&hs, hashpool); + + counter = 0; + donerandinit = 1; +} + +/* return len bytes of pseudo-random data */ +void genrandom(unsigned char* buf, unsigned int len) { + + hash_state hs; + unsigned char hash[SHA1_HASH_SIZE]; + unsigned int copylen; + + if (!donerandinit) { + dropbear_exit("seedrandom not done"); + } + + while (len > 0) { + sha1_init(&hs); + sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); + sha1_process(&hs, (void*)&counter, sizeof(counter)); + sha1_done(&hs, hash); + + counter++; + if (counter > MAX_COUNTER) { + seedrandom(); + } + + copylen = MIN(len, SHA1_HASH_SIZE); + memcpy(buf, hash, copylen); + len -= copylen; + buf += copylen; + } + m_burn(hash, sizeof(hash)); +} + +/* Adds entropy to the PRNG state. As long as the hash is strong, then we + * don't need to worry about entropy being added "diluting" the current + * state - it should only make it stronger. */ +void addrandom(unsigned char* buf, unsigned int len) { + + hash_state hs; + if (!donerandinit) { + dropbear_exit("seedrandom not done"); + } + + sha1_init(&hs); + sha1_process(&hs, (void*)buf, len); + sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); + sha1_done(&hs, hashpool); + counter = 0; + +} -- cgit v1.2.3 From 8e1ec24f55be1a9af2595a58bb4b805bebd7fa9d Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 12 Aug 2004 16:41:58 +0000 Subject: Merging in the changes from 0.41-0.43 main Dropbear tree --HG-- extra : convert_revision : 4c3428781bc8faf0fd7cadd7099fbd7f4ea386e7 --- buffer.c | 9 +- channel.h | 3 + cli-tcpfwd.c | 9 +- common-channel.c | 27 +++++- configure.in | 2 +- dbutil.c | 6 +- debian/README.runit | 46 +++++++++ debian/changelog | 52 +++++++++++ debian/control | 24 +++-- debian/copyright.in | 6 +- debian/dropbear.README.Debian | 41 +++++++++ debian/dropbear.conffiles | 3 + debian/dropbear.docs | 3 + debian/dropbear.init | 60 ++++-------- debian/dropbear.postinst | 68 ++++++++++++++ debian/dropbear.postrm | 12 +++ debian/dropbear.prerm | 11 +++ debian/implicit | 79 ++++++++++++++++ debian/rules | 210 +++++++++++++++++------------------------- debian/service/log | 2 + debian/service/run | 3 + dropbearkey.c | 1 - dss.c | 4 +- gendss.c | 1 - includes.h | 6 +- options.h | 7 +- packet.c | 4 +- random.c | 5 +- rsa.c | 16 ++-- signkey.c | 4 +- svr-agentfwd.c | 4 +- svr-auth.c | 4 +- svr-authpasswd.c | 8 +- svr-authpubkey.c | 2 +- svr-chansession.c | 35 +++++-- svr-tcpfwd.c | 9 +- svr-x11fwd.c | 4 +- 37 files changed, 554 insertions(+), 236 deletions(-) create mode 100644 debian/README.runit create mode 100644 debian/dropbear.README.Debian create mode 100644 debian/dropbear.conffiles create mode 100644 debian/dropbear.docs create mode 100644 debian/dropbear.postinst create mode 100644 debian/dropbear.postrm create mode 100644 debian/dropbear.prerm create mode 100644 debian/implicit create mode 100644 debian/service/log create mode 100644 debian/service/run (limited to 'random.c') diff --git a/buffer.c b/buffer.c index 7181fca..df608d9 100644 --- a/buffer.c +++ b/buffer.c @@ -34,8 +34,8 @@ #define BUF_MAX_INCR 1000000000 #define BUF_MAX_SIZE 1000000000 -/* avoid excessively large numbers, > 5000 bit */ -#define BUF_MAX_MPINT (5000 / 8) +/* avoid excessively large numbers, > ~8192 bits */ +#define BUF_MAX_MPINT (8240 / 8) /* Create (malloc) a new buffer of size */ buffer* buf_new(unsigned int size) { @@ -76,7 +76,8 @@ void buf_burn(buffer* buf) { } -/* resize a buffer, pos and len will be repositioned if required */ +/* resize a buffer, pos and len will be repositioned if required when + * downsizing */ void buf_resize(buffer *buf, unsigned int newsize) { if (newsize > BUF_MAX_SIZE) { @@ -151,6 +152,8 @@ void buf_incrpos(buffer* buf, int incr) { /* Get a byte from the buffer and increment the pos */ unsigned char buf_getbyte(buffer* buf) { + /* This check is really just ==, but the >= allows us to check for the + * assert()able case of pos > len, which should _never_ happen. */ if (buf->pos >= buf->len) { dropbear_exit("bad buf_getbyte"); } diff --git a/channel.h b/channel.h index e1bdae2..2289de1 100644 --- a/channel.h +++ b/channel.h @@ -41,6 +41,9 @@ #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3 #define SSH_OPEN_RESOURCE_SHORTAGE 4 +/* Not a real type */ +#define SSH_OPEN_IN_PROGRESS 99 + #define MAX_CHANNELS 60 /* simple mem restriction, includes each tcp/x11 connection, so can't be _too_ small */ diff --git a/cli-tcpfwd.c b/cli-tcpfwd.c index 52268b9..8d8e605 100644 --- a/cli-tcpfwd.c +++ b/cli-tcpfwd.c @@ -120,7 +120,7 @@ static int newtcpforwarded(struct Channel * channel) { struct TCPFwdList * iter = NULL; char portstring[NI_MAXSERV]; int sock; - int ret = DROPBEAR_FAILURE; + int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; /* We don't care what address they connected to */ buf_eatstring(ses.payload); @@ -148,6 +148,7 @@ static int newtcpforwarded(struct Channel * channel) { sock = connect_remote(iter->connectaddr, portstring, 1, NULL); if (sock < 0) { TRACE(("leave newtcpdirect: sock failed")); + err = SSH_OPEN_CONNECT_FAILED; goto out; } @@ -160,9 +161,9 @@ static int newtcpforwarded(struct Channel * channel) { channel->infd = sock; channel->initconn = 1; - ret = DROPBEAR_SUCCESS; + err = SSH_OPEN_IN_PROGRESS; out: - TRACE(("leave newtcpdirect: ret %d", ret)); - return ret; + TRACE(("leave newtcpdirect: err %d", err)); + return err; } diff --git a/common-channel.c b/common-channel.c index 5079031..64ea466 100644 --- a/common-channel.c +++ b/common-channel.c @@ -172,6 +172,7 @@ void channelio(fd_set *readfd, fd_set *writefd) { struct Channel *channel; unsigned int i; + int ret; /* iterate through all the possible channels */ for (i = 0; i < ses.chansize; i++) { @@ -196,8 +197,15 @@ void channelio(fd_set *readfd, fd_set *writefd) { * see if it has errors */ if (channel->infd >= 0 && channel->infd != channel->outfd && FD_ISSET(channel->infd, readfd)) { - int ret; - ret = write(channel->infd, NULL, 0); + if (channel->initconn) { + /* Handling for "in progress" connection - this is needed + * to avoid spinning 100% CPU when we connect to a server + * which doesn't send anything (tcpfwding) */ + checkinitdone(channel); + continue; /* Important not to use the channel after + checkinitdone(), as it may be NULL */ + } + ret = write(channel->infd, NULL, 0); /* Fake write */ if (ret < 0 && errno != EINTR && errno != EAGAIN) { closeinfd(channel); } @@ -209,9 +217,8 @@ void channelio(fd_set *readfd, fd_set *writefd) { checkinitdone(channel); continue; /* Important not to use the channel after checkinitdone(), as it may be NULL */ - } else { - writechannel(channel); } + writechannel(channel); } /* now handle any of the channel-closing type stuff */ @@ -285,10 +292,14 @@ static void checkinitdone(struct Channel *channel) { if (getsockopt(channel->infd, SOL_SOCKET, SO_ERROR, &val, &vallen) || val != 0) { + send_msg_channel_open_failure(channel->remotechan, + SSH_OPEN_CONNECT_FAILED, "", ""); close(channel->infd); deletechannel(channel); TRACE(("leave checkinitdone: fail")); } else { + send_msg_channel_open_confirmation(channel, channel->recvwindow, + channel->recvmaxpacket); channel->outfd = channel->infd; channel->initconn = 0; TRACE(("leave checkinitdone: success")); @@ -489,6 +500,7 @@ static void removechannel(struct Channel * channel) { TRACE(("channel index is %d", channel->index)); buf_free(channel->writebuf); + channel->writebuf = NULL; /* close the FDs in case they haven't been done * yet (ie they were shutdown etc */ @@ -497,6 +509,7 @@ static void removechannel(struct Channel * channel) { if (channel->errfd >= 0) { close(channel->errfd); } + channel->typedata = NULL; deletechannel(channel); @@ -587,6 +600,7 @@ static void send_msg_channel_data(struct Channel *channel, int isextended, TRACE(("leave send_msg_channel_data: read err %d", channel->index)); } buf_free(buf); + buf = NULL; return; } buf_incrlen(buf, len); @@ -601,6 +615,7 @@ static void send_msg_channel_data(struct Channel *channel, int isextended, buf_putstring(ses.writepayload, buf_getptr(buf, len), len); buf_free(buf); + buf = NULL; channel->transwindow -= len; @@ -764,6 +779,10 @@ void recv_msg_channel_open() { if (channel->type->inithandler) { ret = channel->type->inithandler(channel); if (ret > 0) { + if (ret == SSH_OPEN_IN_PROGRESS) { + /* We'll send the confirmation later */ + goto cleanup; + } errtype = ret; deletechannel(channel); TRACE(("inithandler returned failure %d", ret)); diff --git a/configure.in b/configure.in index bffd0da..10988c2 100644 --- a/configure.in +++ b/configure.in @@ -169,7 +169,7 @@ AC_ARG_ENABLE(shadow, # Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS([fcntl.h limits.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h crypt.h pty.h ioctl.h libutil.h libgen.h inttypes.h stropts.h utmp.h utmpx.h lastlog.h paths.h util.h netdb.h sys/dirent.h]) +AC_CHECK_HEADERS([fcntl.h limits.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h crypt.h pty.h ioctl.h libutil.h libgen.h inttypes.h stropts.h utmp.h utmpx.h lastlog.h paths.h util.h netdb.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST diff --git a/dbutil.c b/dbutil.c index 5436cbb..30b5708 100644 --- a/dbutil.c +++ b/dbutil.c @@ -121,7 +121,7 @@ void dropbear_trace(const char* format, ...) { int dropbear_listen(const char* address, const char* port, int *socks, unsigned int sockcount, char **errstring, int *maxfd) { - struct addrinfo hints, *res, *res0; + struct addrinfo hints, *res = NULL, *res0 = NULL; int err; unsigned int nsock; struct linger linger; @@ -273,7 +273,7 @@ int connect_remote(const char* remotehost, const char* remoteport, } if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { - if (errno == EINPROGRESS) { + if (errno == EINPROGRESS && nonblocking) { TRACE(("Connect in progress")); break; } else { @@ -287,7 +287,7 @@ int connect_remote(const char* remotehost, const char* remoteport, break; /* Success */ } - if (sock < 0) { + if (sock < 0 && !(errno == EINPROGRESS && nonblocking)) { /* Failed */ if (errstring != NULL && *errstring == NULL) { int len; diff --git a/debian/README.runit b/debian/README.runit new file mode 100644 index 0000000..4ac2814 --- /dev/null +++ b/debian/README.runit @@ -0,0 +1,46 @@ +Using the dropbear SSH server with runit's services supervision +--------------------------------------------------------------- + +The dropbear SSH server is perfectly suited to be run under runit's +service supervision, and this package already has prepared an adequate +service directory. Follow these steps to enable the dropbear service +using the runit package. + +If not yet installed on your system, install the runit package, and make +sure its service supervision is enabled (it's by default) + + # apt-get install runit + +Make sure the dropbear service normally handled through the sysv init +script is stopped + + # /etc/init.d/dropbear stop + +Create the system user ``dropbearlog'' which will run the logger service, +and own the logs + + # adduser --system --home /var/log/dropbear --no-create-home dropbearlog + +Create the log directory and make the newly created system user the owner +of this directory + + # mkdir -p /var/log/dropbear && chown dropbearlog /var/log/dropbear + +Optionally adjust the configuration of the dropbear service by editing the +run script + + # vi /etc/dropbear/run + +Finally enable the service by linking dropbear's service directory to +/var/service/. The service will be started within five seconds, and +automatically at boot time. The sysv init script is disabled; see the +runsvctrl(8) program for information on how to control services handled by +runit. See the svlogd(8) program on how to configure the log service. + + # ln -s /etc/dropbear /var/service/ + +Optionally check the status of the service a few seconds later + + # runsvstat -l /var/service/dropbear + + -- Gerrit Pape , Sun, 16 May 2004 15:52:34 +0000 diff --git a/debian/changelog b/debian/changelog index cb7253f..d9da388 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,55 @@ +dropbear (0.43-1) unstable; urgency=high + + * New upstream release 0.43 + * SECURITY: Don't attempt to free uninitialised buffers in DSS verification + code + * Handle portforwarding to servers which don't send any initial data + (Closes: #258426) + + -- Matt Johnston Fri, 16 July 2004 17:44:54 +0800 + +dropbear (0.42-1) unstable; urgency=low + + * New upstream release 0.42 + + -- Matt Johnston Wed, 16 June 2004 12:44:54 +0800 + +dropbear (0.41-3) unstable; urgency=low + + * 1st upload to the Debian archive (closes: #216553). + * debian/diff/cvs-20040520.diff: new; stable cvs snapshot. + * debian/rules: new target patch: apply diffs in debian/diff/, reverse + apply in target clean; install man pages. + * debian/control: Priority: optional. + + -- Gerrit Pape Sun, 23 May 2004 08:32:37 +0000 + +dropbear (0.41-2) unstable; urgency=low + + * new maintainer. + * debian/control: no longer Build-Depends: debhelper; Build-Depends: + libz-dev; Standards-Version: 3.6.1.0; Suggests: runit; update + descriptions. + * debian/rules: stop using debhelper, use implicit rules; cleanup; + install dropbearconvert into /usr/lib/dropbear/. + * debian/impicit: new; implicit rules. + * debian/copyright.in: adapt. + * debian/dropbear.init: minor adaptions; test for dropbear service + directory. + * debian/README.runit: new; how to use dropbear with runit. + * debian/README.Debian, debian/docs: rename to debian/dropbear.*. + * debian/dropbear.docs: add debian/README.runit + * debian/conffiles: rename to debian/dropbear.conffiles; add init + script, and run scripts. + * debian/postinst: rename to debian/dropbear.postinst; adapt; use + invloke-rc.d dropbear start. + * debian/dropbear.prerm: new; invoke-rc.d dropbear stop. + * debian/postrm: rename to debian/dropbear.postrm; adapt; clean up + service directories. + * debian/compat, debian/dirs, dropbear.default: remove; obsolete. + + -- Gerrit Pape Sun, 16 May 2004 16:50:55 +0000 + dropbear (0.41-1) unstable; urgency=low * Updated to 0.41 release. diff --git a/debian/control b/debian/control index e528454..33c717c 100644 --- a/debian/control +++ b/debian/control @@ -1,14 +1,20 @@ Source: dropbear Section: net -Priority: standard -Maintainer: Grahame Bowland -Build-Depends: debhelper (>> 4.0.0), zlib1g-dev -Standards-Version: 3.5.8 +Priority: optional +Maintainer: Gerrit Pape +Build-Depends: libz-dev +Standards-Version: 3.6.1.0 Package: dropbear Architecture: any -Depends: ${shlibs:Depends} ${misc:Depends} -Suggests: ssh -Description: a minimal SSH2 server - A small secure shell version 2 server. - +Depends: ${shlibs:Depends} +Suggests: ssh, runit +Description: lightweight SSH2 server + dropbear is a SSH 2 server designed to be small enough to be used in small + memory environments, while still being functional and secure enough for + general use. + . + It implements most required features of the SSH 2 protocol, and other + features such as X11 and authentication agent forwarding. + . + See http://matt.ucc.asn.au/dropbear/dropbear.html diff --git a/debian/copyright.in b/debian/copyright.in index 015d9ab..79526d3 100644 --- a/debian/copyright.in +++ b/debian/copyright.in @@ -1,9 +1,11 @@ This package was debianized by Grahame Bowland on -Tue, 17 Jun 2003 15:04:47 +0800. +Tue, 17 Jun 2003 15:04:47 +0800, maintained temporarily by Matt Johnston +, and was adopted by Gerrit Pape on +Sun, 16 May 2004 14:38:33 +0000. It was downloaded from http://matt.ucc.asn.au/dropbear/ -Upstream Author(s): Matt Johnston +Upstream Author: Matt Johnston Copyright: diff --git a/debian/dropbear.README.Debian b/debian/dropbear.README.Debian new file mode 100644 index 0000000..8cdac38 --- /dev/null +++ b/debian/dropbear.README.Debian @@ -0,0 +1,41 @@ +Dropbear for Debian +------------------- + +This package will attempt to listen on port 22. If the OpenSSH +package ("ssh") is installed, the file /etc/default/dropbear +will be set up so that the server does not start by default. + +You can run Dropbear concurrently with OpenSSH 'sshd' by +modifying /etc/default/dropbear so that "NO_START" is set to +"0" and changing the port number that Dropbear runs on. Follow +the instructions in the file. + +This package suggests you install the "ssh" package. This package +provides the "ssh" client program, as well as the "/usr/bin/scp" +binary you will need to be able to retrieve files from a server +running Dropbear via SCP. + +Replacing OpenSSH "sshd" with Dropbear +-------------------------------------- + +You will still want to have the "ssh" package installed, as it +provides the "ssh" and "scp" binaries. When you install this +package, it checks for existing OpenSSH host keys and if found, +converts them to the Dropbear format. + +If this appears to have worked, you should be able to change over +by following these steps: + +1. Stop the OpenSSH server + % /etc/init.d/ssh stop +2. Prevent the OpenSSH server from starting in the future + % touch /etc/ssh/sshd_not_to_be_run +3. Modify the Dropbear defaults file, set NO_START to 0 and + ensure DROPBEAR_PORT is set to 22. + % editor /etc/default/dropbear +4. Restart the Dropbear server. + % /etc/init.d/dropbear restart + +See the Dropbear homepage for more information: + http://matt.ucc.asn.au/dropbear/dropbear.html + diff --git a/debian/dropbear.conffiles b/debian/dropbear.conffiles new file mode 100644 index 0000000..6919006 --- /dev/null +++ b/debian/dropbear.conffiles @@ -0,0 +1,3 @@ +/etc/init.d/dropbear +/etc/dropbear/run +/etc/dropbear/log/run diff --git a/debian/dropbear.docs b/debian/dropbear.docs new file mode 100644 index 0000000..599d48c --- /dev/null +++ b/debian/dropbear.docs @@ -0,0 +1,3 @@ +README +TODO +debian/README.runit diff --git a/debian/dropbear.init b/debian/dropbear.init index 25eda9f..d9578db 100644 --- a/debian/dropbear.init +++ b/debian/dropbear.init @@ -1,15 +1,4 @@ -#! /bin/sh -# -# skeleton example file to build /etc/init.d/ scripts. -# This file should be used to construct scripts for /etc/init.d. -# -# Written by Miquel van Smoorenburg . -# Modified for Debian -# by Ian Murdock . -# -# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl -# - +#!/bin/sh # # Do not configure this file. Edit /etc/default/dropbear instead! # @@ -22,54 +11,45 @@ DESC="Dropbear SSH server" DROPBEAR_PORT=22 DROPBEAR_EXTRA_ARGS= NO_START=0 -set -e -test -f /etc/default/dropbear && . /etc/default/dropbear - -if [ -n "$DROPBEAR_BANNER" ]; then - DROPBEAR_EXTRA_ARGS="$DROPBEAR_EXTRA_ARGS -b $DROPBEAR_BANNER" -fi -if [ -z "$DROPBEAR_RSAKEY" ]; then - DROPBEAR_RSAKEY="/etc/dropbear/dropbear_rsa_host_key" -fi - -if [ -z "$DROPBEAR_DSSKEY" ]; then - DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key" -fi +set -e -test "$NO_START" != "0" && exit 0 +test ! -r /etc/default/dropbear || . /etc/default/dropbear +test "$NO_START" = "0" || exit 0 +test -x "$DAEMON" || exit 0 +test ! -h /var/service/dropbear || exit 0 -test -x $DAEMON || exit 0 +test -z "$DROPBEAR_BANNER" || \ + DROPBEAR_EXTRA_ARGS="$DROPBEAR_EXTRA_ARGS -b $DROPBEAR_BANNER" +test -n "$DROPBEAR_RSAKEY" || \ + DROPBEAR_RSAKEY="/etc/dropbear/dropbear_rsa_host_key" +test -n "$DROPBEAR_DSSKEY" || \ + DROPBEAR_DSSKEY="/etc/dropbear/dropbear_dss_host_key" case "$1" in start) echo -n "Starting $DESC: " - start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ - --exec $DAEMON -- -d $DROPBEAR_DSSKEY -r $DROPBEAR_RSAKEY -p $DROPBEAR_PORT $DROPBEAR_EXTRA_ARGS + start-stop-daemon --start --quiet --pidfile /var/run/"$NAME".pid \ + --exec "$DAEMON" -- -d "$DROPBEAR_DSSKEY" -r "$DROPBEAR_RSAKEY" \ + -p "$DROPBEAR_PORT" $DROPBEAR_EXTRA_ARGS echo "$NAME." ;; stop) echo -n "Stopping $DESC: " - start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/$NAME.pid + start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/"$NAME".pid echo "$NAME." ;; restart|force-reload) - # - # If the "reload" option is implemented, move the "force-reload" - # option to the "reload" entry above. If not, "force-reload" is - # just the same as "restart". - # echo -n "Restarting $DESC: " - start-stop-daemon --stop --quiet --oknodo --pidfile \ - /var/run/$NAME.pid + start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/"$NAME".pid sleep 1 - start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ - --exec $DAEMON -- -d $DROPBEAR_DSSKEY -r $DROPBEAR_RSAKEY -p $DROPBEAR_PORT $DROPBEAR_EXTRA_ARGS + start-stop-daemon --start --quiet --pidfile /var/run/"$NAME".pid \ + --exec "$DAEMON" -- -d "$DROPBEAR_DSSKEY" -r "$DROPBEAR_RSAKEY" \ + -p "$DROPBEAR_PORT" $DROPBEAR_EXTRA_ARGS echo "$NAME." ;; *) N=/etc/init.d/$NAME - # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 echo "Usage: $N {start|stop|restart|force-reload}" >&2 exit 1 ;; diff --git a/debian/dropbear.postinst b/debian/dropbear.postinst new file mode 100644 index 0000000..749ffd1 --- /dev/null +++ b/debian/dropbear.postinst @@ -0,0 +1,68 @@ +#!/bin/sh +set -e + +test "$1" = 'configure' || exit 0 +test -n "$2" || chown log /etc/dropbear/log/main || true + +if test ! -e /etc/dropbear/dropbear_rsa_host_key; then + if test -f /etc/ssh/ssh_host_rsa_key; then + echo "Converting existing OpenSSH RSA host key to Dropbear format." + /usr/lib/dropbear/dropbearconvert openssh dropbear \ + /etc/ssh/ssh_host_rsa_key /etc/dropbear/dropbear_rsa_host_key + else + echo "Generating Dropbear RSA key. Please wait." + dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key + fi +fi +if test ! -e /etc/dropbear/dropbear_dss_host_key; then + if test -f /etc/ssh/ssh_host_dsa_key; then + echo "Converting existing OpenSSH RSA host key to Dropbear format." + /usr/lib/dropbear/dropbearconvert openssh dropbear \ + /etc/ssh/ssh_host_dsa_key /etc/dropbear/dropbear_dss_host_key + else + echo "Generating Dropbear DSS key. Please wait." + dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key + fi +fi +if test ! -s /etc/default/dropbear; then + # check whether OpenSSH seems to be installed. + if test -x /usr/sbin/sshd; then + cat <>/etc/default/dropbear <>/etc/default/dropbear </dev/null + if test -x /usr/sbin/invoke-rc.d; then + invoke-rc.d dropbear start + else + /etc/init.d/dropbear start + fi +fi diff --git a/debian/dropbear.postrm b/debian/dropbear.postrm new file mode 100644 index 0000000..d09dab0 --- /dev/null +++ b/debian/dropbear.postrm @@ -0,0 +1,12 @@ +#! /bin/sh +set -e + +test "$1" = 'purge' || exit 0 +if test -e /etc/dropbear; then + rm -f /etc/dropbear/dropbear_rsa_host_key + rm -f /etc/dropbear/dropbear_dss_host_key + rmdir --ignore-fail-on-non-empty /etc/dropbear +fi +update-rc.d dropbear remove >/dev/null +rm -f /etc/default/dropbear +rm -rf /etc/dropbear/supervise /etc/dropbear/log/supervise diff --git a/debian/dropbear.prerm b/debian/dropbear.prerm new file mode 100644 index 0000000..89bb5b6 --- /dev/null +++ b/debian/dropbear.prerm @@ -0,0 +1,11 @@ +#!/bin/sh +set -u + +test "$1" = 'remove' || test "$1" = 'deconfigure' || exit 0 +if test -x /etc/init.d/dropbear; then + if test -x /usr/sbin/invoke-rc.d; then + invoke-rc.d dropbear stop + else + /etc/init.d/dropbear stop + fi +fi diff --git a/debian/implicit b/debian/implicit new file mode 100644 index 0000000..d28b629 --- /dev/null +++ b/debian/implicit @@ -0,0 +1,79 @@ +# $Id: implicit,v 1.1 2004/06/16 05:08:32 matt Exp $ + +.PHONY: deb-checkdir deb-checkuid + +deb-checkdir: + @test -e debian/control || sh -cx '! : wrong directory' +deb-checkuid: + @test "`id -u`" -eq 0 || sh -cx '! : need root privileges' + +%.deb: %.deb-docs %.deb-DEBIAN + @rm -f $*.deb $*.deb-checkdir $*.deb-docs $*.deb-docs-base \ + $*.deb-docs-docs $*.deb-docs-examples $*.deb-DEBIAN \ + $*.deb-DEBIAN-dir $*.deb-DEBIAN-scripts $*.deb-DEBIAN-md5sums + +%.deb-checkdir: + @test -d debian/$* || sh -cx '! : directory debian/$* missing' + @test "`id -u`" -eq 0 || sh -cx '! : need root privileges' + +%.deb-docs-base: + : implicit + @rm -f debian/$*/usr/share/doc/$*/* || : + @install -d -m0755 debian/$*/usr/share/doc/$* + : debian/$*/usr/share/doc/$*/ + @sh -cx 'install -m0644 debian/copyright debian/$*/usr/share/doc/$*/' + @sh -cx 'install -m0644 debian/changelog \ + debian/$*/usr/share/doc/$*/changelog.Debian' + @test ! -r changelog || \ + sh -cx 'install -m0644 changelog debian/$*/usr/share/doc/$*/' + @test -r debian/$*/usr/share/doc/$*/changelog || \ + sh -cx 'mv debian/$*/usr/share/doc/$*/changelog.Debian \ + debian/$*/usr/share/doc/$*/changelog' + @gzip -9 debian/$*/usr/share/doc/$*/changelog* +%.deb-docs-docs: + @for i in `cat debian/$*.docs 2>/dev/null || :`; do \ + sh -cx "install -m0644 $$i debian/$*/usr/share/doc/$*/" || exit 1; \ + done + @test ! -r debian/$*.README.Debian || \ + sh -cx 'install -m0644 debian/$*.README.Debian \ + debian/$*/usr/share/doc/$*/README.Debian' + @if test -r debian/$*.NEWS.Debian; then \ + sh -cx 'install -m0644 debian/$*.NEWS.Debian \ + debian/$*/usr/share/doc/$*/NEWS.Debian && \ + gzip -9 debian/$*/usr/share/doc/$*/NEWS.Debian'; \ + fi +%.deb-docs-examples: + @rm -rf debian/$*/usr/share/doc/$*/examples + : debian/$*/usr/share/doc/$*/examples/ + @test ! -r debian/$*.examples || \ + install -d -m0755 debian/$*/usr/share/doc/$*/examples + @for i in `cat debian/$*.examples 2>/dev/null || :`; do \ + sh -cx "install -m0644 $$i debian/$*/usr/share/doc/$*/examples/" \ + || exit 1; \ + done +%.deb-docs: %.deb-checkdir %.deb-docs-base %.deb-docs-docs %.deb-docs-examples + : debian/$*/usr/share/doc/$*/ ok + +%.deb-DEBIAN-base: + @rm -rf debian/$*/DEBIAN + : debian/$*/DEBIAN/ + @install -d -m0755 debian/$*/DEBIAN + @for i in conffiles shlibs; do \ + test ! -r debian/$*.$$i || \ + sh -cx "install -m0644 debian/$*.$$i debian/$*/DEBIAN/$$i" \ + || exit 1; \ + done +%.deb-DEBIAN-scripts: + @for i in preinst prerm postinst postrm; do \ + test ! -r debian/$*.$$i || \ + sh -cx "install -m0755 debian/$*.$$i debian/$*/DEBIAN/$$i" \ + || exit 1; \ + done +%.deb-DEBIAN-md5sums: + : debian/$*/DEBIAN/md5sums + @rm -f debian/$*/DEBIAN/md5sums + @cd debian/$* && find * -path 'DEBIAN' -prune -o \ + -type f -exec md5sum {} >>DEBIAN/md5sums \; +%.deb-DEBIAN: %.deb-checkdir %.deb-DEBIAN-base %.deb-DEBIAN-scripts \ + %.deb-DEBIAN-md5sums + : debian/$*/DEBIAN/ ok diff --git a/debian/rules b/debian/rules index 4d73093..ee7b14a 100644 --- a/debian/rules +++ b/debian/rules @@ -1,134 +1,96 @@ #!/usr/bin/make -f -# Sample debian/rules that uses debhelper. -# GNU copyright 1997 to 1999 by Joey Hess. -# -# Modified to make a template file for a multi-binary package with separated -# build-arch and build-indep targets by Bill Allombert 2001 -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 +#export DH_OPTIONS +DEB_HOST_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) -# This has to be exported to make some magic below work. -export DH_OPTIONS - -# These are used for cross-compiling and for saving the configure script -# from having to guess our platform (since we know it already) -DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) -DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) - - -CFLAGS = -Wall -g +STRIP =strip +ifneq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + STRIP =: nostrip +endif +CFLAGS =-Wall -g ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) - CFLAGS += -O0 + CFLAGS +=-O0 else - CFLAGS += -O2 -endif -ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) - INSTALL_PROGRAM += -s + CFLAGS +=-O2 endif -config.status: configure - dh_testdir - # Add here commands to configure the package. - CFLAGS='-DSFTPSERVER_PATH="\"/usr/lib/sftp-server\""' ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info - - -#Architecture -build: build-arch #build-indep - -build-arch: build-arch-stamp -build-arch-stamp: config.status - - # Add here commands to compile the arch part of the package. - $(MAKE) CC=gcc LD=gcc - -build-indep: build-indep-stamp -build-indep-stamp: config.status - - # Add here commands to compile the indep part of the package. - #$(MAKE) doc - -clean: - dh_testdir - dh_testroot - rm -f build-arch-stamp build-indep-stamp config-stamp - - # Add here commands to clean up after the build process. - -$(MAKE) clean -ifneq "$(wildcard /usr/share/misc/config.sub)" "" - cp -f /usr/share/misc/config.sub config.sub -endif -ifneq "$(wildcard /usr/share/misc/config.guess)" "" - cp -f /usr/share/misc/config.guess config.guess +CC =gcc +ifneq (,$(findstring diet,$(DEB_BUILD_OPTIONS))) + CC =diet -v -Os gcc endif - - dh_clean - -install: install-indep install-arch -install-indep: - dh_testdir - dh_testroot - dh_clean -k -i - dh_installdirs -i - - # Add here commands to install the indep part of the package into - # debian/-doc. - #INSTALLDOC# - - dh_install -i - -install-arch: - dh_testdir - dh_testroot - dh_clean -k -a - dh_installdirs -a - dh_installdirs /etc/dropbear - - # Add here commands to install the arch part of the package into - # debian/tmp. - $(MAKE) install prefix=$(CURDIR)/debian/dropbear/usr - - dh_install -a -# Must not depend on anything. This is to be called by -# binary-arch/binary-multi -# in another 'make' thread. -binary-common: - cat $(CURDIR)/debian/copyright.in $(CURDIR)/LICENSE > $(CURDIR)/debian/copyright - dh_testdir - dh_testroot - dh_installchangelogs CHANGES - dh_installdocs - dh_installexamples -# dh_installmenu -# dh_installdebconf -# dh_installlogrotate -# dh_installemacsen -# dh_installpam -# dh_installmime - dh_installinit -# dh_installcron -# dh_installinfo - dh_installman - dh_link - dh_strip - dh_compress - dh_fixperms -# dh_perl -# dh_python - dh_makeshlibs - dh_installdeb - dh_gencontrol - dh_md5sums - dh_builddeb -# Build architecture independant packages using the common target. -binary-indep: build-indep install-indep - $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common - -# Build architecture dependant packages using the common target. -binary-arch: build-arch install-arch - $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common - -binary: binary-arch #binary-indep -.PHONY: build clean binary-indep binary-arch binary install install-indep install-arch +DIR=`pwd`/debian/dropbear + +patch: deb-checkdir patch-stamp +patch-stamp: +# no patches for now +# for i in debian/diff/*.diff; do patch -p0 <$$i || exit 1; done + touch patch-stamp + +config.status: patch-stamp configure + CFLAGS="$(CFLAGS)"' -DSFTPSERVER_PATH="\"/usr/lib/sftp-server\""' \ + ./configure --host="$(DEB_HOST_GNU_TYPE)" \ + --build="$(DEB_BUILD_GNU_TYPE)" --prefix=/usr \ + --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info + +build: deb-checkdir build-stamp +build-stamp: config.status + $(MAKE) CC="$(CC)" LD="$(CC)" + touch build-stamp + +clean: deb-checkdir deb-checkuid + -$(MAKE) distclean +# test ! -e patch-stamp || \ +# for i in debian/diff/*.diff; do patch -p0 -R <$$i; done + rm -f patch-stamp build-stamp config.log config.status + rm -rf "$(DIR)" + rm -f debian/files debian/substvars debian/copyright changelog + +install: deb-checkdir deb-checkuid build-stamp + rm -rf "$(DIR)" + install -d -m0755 "$(DIR)"/etc/dropbear + # programs + install -d -m0755 "$(DIR)"/usr/sbin + install -m0755 dropbear "$(DIR)"/usr/sbin/dropbear + install -d -m0755 "$(DIR)"/usr/bin + install -m0755 dropbearkey "$(DIR)"/usr/bin/dropbearkey + install -d -m0755 "$(DIR)"/usr/lib/dropbear + install -m0755 dropbearconvert \ + "$(DIR)"/usr/lib/dropbear/dropbearconvert + $(STRIP) -R .comment -R .note "$(DIR)"/usr/sbin/* \ + "$(DIR)"/usr/bin/* "$(DIR)"/usr/lib/dropbear/* + # init and run scripts + install -d -m0755 "$(DIR)"/etc/init.d + install -m0755 debian/dropbear.init "$(DIR)"/etc/init.d/dropbear + install -m0755 debian/service/run "$(DIR)"/etc/dropbear/run + install -d -m0755 "$(DIR)"/etc/dropbear/log + install -m0755 debian/service/log "$(DIR)"/etc/dropbear/log/run + ln -s /var/log/dropbear "$(DIR)"/etc/dropbear/log/main + ln -s /var/run/dropbear "$(DIR)"/etc/dropbear/supervise + ln -s /var/run/dropbear.log "$(DIR)"/etc/dropbear/log/supervise + # man pages + install -d -m0755 "$(DIR)"/usr/share/man/man8 + for i in dropbear.8 dropbearkey.8; do \ + install -m644 $$i "$(DIR)"/usr/share/man/man8/ || exit 1; \ + done + gzip -9 "$(DIR)"/usr/share/man/man8/*.8 + # copyright, changelog + cat debian/copyright.in LICENSE >debian/copyright + ln -s CHANGES changelog + +binary-indep: + +binary-arch: install dropbear.deb + test "$(CC)" != 'gcc' || \ + dpkg-shlibdeps "$(DIR)"/usr/sbin/* "$(DIR)"/usr/bin/* \ + "$(DIR)"/usr/lib/dropbear/* + dpkg-gencontrol -isp -pdropbear -P"$(DIR)" + dpkg -b "$(DIR)" .. + +binary: binary-arch binary-indep + +.PHONY: patch build clean install binary-indep binary-arch binary + +include debian/implicit diff --git a/debian/service/log b/debian/service/log new file mode 100644 index 0000000..2ffb13d --- /dev/null +++ b/debian/service/log @@ -0,0 +1,2 @@ +#!/bin/sh +exec chpst -udropbearlog svlogd -tt ./main diff --git a/debian/service/run b/debian/service/run new file mode 100644 index 0000000..f208085 --- /dev/null +++ b/debian/service/run @@ -0,0 +1,3 @@ +#!/bin/sh +exec 2>&1 +exec dropbear -d ./dropbear_dss_host_key -r ./dropbear_rsa_host_key -F -E -p 22 diff --git a/dropbearkey.c b/dropbearkey.c index eac0823..5d4475b 100644 --- a/dropbearkey.c +++ b/dropbearkey.c @@ -45,7 +45,6 @@ * */ #include "includes.h" -#include "runopts.h" #include "signkey.h" #include "buffer.h" #include "dbutil.h" diff --git a/dss.c b/dss.c index 74b92c7..9b56f10 100644 --- a/dss.c +++ b/dss.c @@ -171,6 +171,8 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, TRACE(("enter buf_dss_verify")); assert(key != NULL); + m_mp_init_multi(&val1, &val2, &val3, &val4, NULL); + /* get blob, check length */ string = buf_getstring(buf, &stringlen); if (stringlen != 2*SHA1_HASH_SIZE) { @@ -182,8 +184,6 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, sha1_process(&hs, data, len); sha1_done(&hs, msghash); - m_mp_init_multi(&val1, &val2, &val3, &val4, NULL); - /* create the signature - s' and r' are the received signatures in buf */ /* w = (s')-1 mod q */ /* let val1 = s' */ diff --git a/gendss.c b/gendss.c index 3e9db09..5a440a1 100644 --- a/gendss.c +++ b/gendss.c @@ -31,7 +31,6 @@ #include "gendss.h" #include "dss.h" -#define PSIZE 128 /* 1024 bit*/ #define QSIZE 20 /* 160 bit */ #ifdef DROPBEAR_DSS diff --git a/includes.h b/includes.h index 52c48ed..b37422b 100644 --- a/includes.h +++ b/includes.h @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -56,6 +55,7 @@ #include #include #include +#include #include @@ -111,10 +111,6 @@ #include #endif -#ifdef HAVE_SYS_DIRENT_H -#include -#endif - #include "libtomcrypt/mycrypt_custom.h" #include "libtommath/tommath.h" diff --git a/options.h b/options.h index f0831b9..c687a8c 100644 --- a/options.h +++ b/options.h @@ -47,6 +47,11 @@ * if you want to use this) */ /*#define NO_FAST_EXPTMOD*/ +/* Set this if you want to use the DROPBEAR_SMALL_CODE option. This can save +several kB in binary size, however will make the symmetrical ciphers (AES, DES +etc) slower (perhaps by 50%). Recommended for most small systems. */ +#define DROPBEAR_SMALL_CODE + /* Enable X11 Forwarding - server only */ #define ENABLE_X11FWD @@ -175,7 +180,7 @@ *******************************************************************/ #ifndef DROPBEAR_VERSION -#define DROPBEAR_VERSION "0.41-and-client" +#define DROPBEAR_VERSION "0.45-beta1" #endif #define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION diff --git a/packet.c b/packet.c index 997bc6f..5e8e14d 100644 --- a/packet.c +++ b/packet.c @@ -50,7 +50,7 @@ static void buf_compress(buffer * dest, buffer * src, unsigned int len); void write_packet() { int len, written; - buffer * writebuf; + buffer * writebuf = NULL; TRACE(("enter write_packet")); assert(!isempty(&ses.writequeue)); @@ -80,6 +80,7 @@ void write_packet() { /* We've finished with the packet, free it */ dequeue(&ses.writequeue); buf_free(writebuf); + writebuf = NULL; } else { /* More packet left to write, leave it in the queue for later */ buf_incrpos(writebuf, written); @@ -503,6 +504,7 @@ void encrypt_packet() { /* clearwritebuf is finished with */ buf_free(clearwritebuf); + clearwritebuf = NULL; /* enqueue the packet for sending */ buf_setpos(writebuf, 0); diff --git a/random.c b/random.c index 725b29c..65a9c64 100644 --- a/random.c +++ b/random.c @@ -60,7 +60,7 @@ static void readrand(unsigned char* buf, unsigned int buflen) { #ifdef DROPBEAR_DEV_URANDOM readfd = open(DEV_URANDOM, O_RDONLY); - if (!readfd) { + if (readfd < 0) { dropbear_exit("couldn't open random device"); } #endif @@ -71,7 +71,8 @@ static void readrand(unsigned char* buf, unsigned int buflen) { strlcpy(egdsock.sun_path, DROPBEAR_EGD_SOCKET, sizeof(egdsock.sun_path)); - if ((readfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + readfd = socket(PF_UNIX, SOCK_STREAM, 0); + if (readfd < 0) { dropbear_exit("couldn't open random device"); } /* todo - try various common locations */ diff --git a/rsa.c b/rsa.c index 2d63c02..1130e93 100644 --- a/rsa.c +++ b/rsa.c @@ -244,8 +244,11 @@ int buf_rsa_verify(buffer * buf, rsa_key *key, const unsigned char* data, } out: - mp_clear_multi(rsa_em, &rsa_mdash, &rsa_s, NULL); - m_free(rsa_em); + if (rsa_em) { + mp_clear(rsa_em); + m_free(rsa_em); + } + mp_clear_multi(&rsa_mdash, &rsa_s, NULL); TRACE(("leave buf_rsa_verify: ret %d", ret)); return ret; @@ -260,15 +263,16 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data, unsigned int nsize, ssize; unsigned int i; mp_int rsa_s; - mp_int *rsa_em; + mp_int *rsa_em = NULL; TRACE(("enter buf_put_rsa_sign")); assert(key != NULL); rsa_em = rsa_pad_em(key, data, len); - /* the actual signing of the padded data */ m_mp_init(&rsa_s); + + /* the actual signing of the padded data */ /* s = em^d mod n */ if (mp_exptmod(rsa_em, key->d, key->n, &rsa_s) != MP_OKAY) { dropbear_exit("rsa error"); @@ -322,10 +326,10 @@ static mp_int * rsa_pad_em(rsa_key * key, {0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}; #define RSA_ASN1_MAGIC_LEN 16 - buffer * rsa_EM; + buffer * rsa_EM = NULL; hash_state hs; unsigned int nsize; - mp_int * rsa_em; + mp_int * rsa_em = NULL; assert(key != NULL); assert(data != NULL); diff --git a/signkey.c b/signkey.c index 3efcc2b..7ae08b8 100644 --- a/signkey.c +++ b/signkey.c @@ -194,7 +194,7 @@ void buf_put_pub_key(buffer* buf, sign_key *key, int type) { buffer *pubkeys; TRACE(("enter buf_put_pub_key")); - pubkeys = buf_new(1000); + pubkeys = buf_new(MAX_PUBKEY_SIZE); #ifdef DROPBEAR_DSS if (type == DROPBEAR_SIGNKEY_DSS) { @@ -356,7 +356,7 @@ void buf_put_sign(buffer* buf, sign_key *key, int type, buffer *sigblob; - sigblob = buf_new(1000); + sigblob = buf_new(MAX_PUBKEY_SIZE); #ifdef DROPBEAR_DSS if (type == DROPBEAR_SIGNKEY_DSS) { diff --git a/svr-agentfwd.c b/svr-agentfwd.c index b588586..4e9aa56 100644 --- a/svr-agentfwd.c +++ b/svr-agentfwd.c @@ -64,7 +64,7 @@ int agentreq(struct ChanSess * chansess) { /* create the unix socket dir and file */ if (bindagent(fd, chansess) == DROPBEAR_FAILURE) { - return DROPBEAR_FAILURE; + goto fail; } /* listen */ @@ -146,7 +146,7 @@ void agentcleanup(struct ChanSess * chansess) { chansess->agentlistener = NULL; } - if (chansess->agentfile && chansess->agentdir) { + if (chansess->agentfile != NULL && chansess->agentdir != NULL) { /* Remove the dir as the user. That way they can't cause problems except * for themselves */ diff --git a/svr-auth.c b/svr-auth.c index 314171f..ae7ead2 100644 --- a/svr-auth.c +++ b/svr-auth.c @@ -91,7 +91,7 @@ static void send_msg_userauth_banner() { * checking, and handle success or failure */ void recv_msg_userauth_request() { - unsigned char *username, *servicename, *methodname; + unsigned char *username = NULL, *servicename = NULL, *methodname = NULL; unsigned int userlen, servicelen, methodlen; TRACE(("enter recv_msg_userauth_request")); @@ -275,7 +275,7 @@ goodshell: * failures */ void send_msg_userauth_failure(int partial, int incrfail) { - buffer *typebuf; + buffer *typebuf = NULL; TRACE(("enter send_msg_userauth_failure")); diff --git a/svr-authpasswd.c b/svr-authpasswd.c index 7c6c7b7..6f7c909 100644 --- a/svr-authpasswd.c +++ b/svr-authpasswd.c @@ -37,14 +37,14 @@ void svr_auth_password() { #ifdef HAVE_SHADOW_H - struct spwd *spasswd; + struct spwd *spasswd = NULL; #endif - char * passwdcrypt; /* the crypt from /etc/passwd or /etc/shadow */ - char * testcrypt; /* crypt generated from the user's password sent */ + char * passwdcrypt = NULL; /* the crypt from /etc/passwd or /etc/shadow */ + char * testcrypt = NULL; /* crypt generated from the user's password sent */ unsigned char * password; unsigned int passwordlen; - unsigned char changepw; + unsigned int changepw; passwdcrypt = ses.authstate.pw->pw_passwd; #ifdef HAVE_SHADOW_H diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 9205078..14b5a78 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -53,7 +53,7 @@ void svr_auth_pubkey() { unsigned char testkey; /* whether we're just checking if a key is usable */ unsigned char* algo = NULL; /* pubkey algo */ unsigned int algolen; - unsigned char* keyblob; + unsigned char* keyblob = NULL; unsigned int keybloblen; buffer * signbuf = NULL; sign_key * key = NULL; diff --git a/svr-chansession.c b/svr-chansession.c index a0e877c..01612f4 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -273,7 +273,7 @@ static void closechansess(struct Channel *channel) { * or x11/authagent forwarding. These are passed to appropriate handlers */ static void chansessionrequest(struct Channel *channel) { - unsigned char * type; + unsigned char * type = NULL; unsigned int typelen; unsigned char wantreply; int ret = 1; @@ -320,7 +320,7 @@ static void chansessionrequest(struct Channel *channel) { out: if (wantreply) { - if (ret == 0) { + if (ret == DROPBEAR_SUCCESS) { send_msg_channel_success(channel); } else { send_msg_channel_failure(channel); @@ -336,7 +336,7 @@ out: static int sessionsignal(struct ChanSess *chansess) { int sig = 0; - unsigned char* signame; + unsigned char* signame = NULL; int i; if (chansess->pid == 0) { @@ -528,11 +528,14 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, int iscmd, int issubsys) { unsigned int cmdlen; + int ret; TRACE(("enter sessioncommand")); if (chansess->cmd != NULL) { - /* TODO - send error - multiple commands? */ + /* Note that only one command can _succeed_. The client might try + * one command (which fails), then try another. Ie fallback + * from sftp to scp */ return DROPBEAR_FAILURE; } @@ -541,6 +544,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, chansess->cmd = buf_getstring(ses.payload, &cmdlen); if (cmdlen > MAX_CMD_LEN) { + m_free(chansess->cmd); /* TODO - send error - too long ? */ return DROPBEAR_FAILURE; } @@ -552,6 +556,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, } else #endif { + m_free(chansess->cmd); return DROPBEAR_FAILURE; } } @@ -559,11 +564,16 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, if (chansess->term == NULL) { /* no pty */ - return noptycommand(channel, chansess); + ret = noptycommand(channel, chansess); } else { /* want pty */ - return ptycommand(channel, chansess); + ret = ptycommand(channel, chansess); + } + + if (ret == DROPBEAR_FAILURE) { + m_free(chansess->cmd); } + return ret; } /* Execute a command and set up redirection of stdin/stdout/stderr without a @@ -650,7 +660,7 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) { static int ptycommand(struct Channel *channel, struct ChanSess *chansess) { pid_t pid; - struct logininfo *li; + struct logininfo *li = NULL; #ifdef DO_MOTD buffer * motdbuf = NULL; int len; @@ -778,8 +788,8 @@ static void addchildpid(struct ChanSess *chansess, pid_t pid) { static void execchild(struct ChanSess *chansess) { char *argv[4]; - char * usershell; - char * baseshell; + char * usershell = NULL; + char * baseshell = NULL; unsigned int i; /* wipe the hostkey */ @@ -863,6 +873,11 @@ static void execchild(struct ChanSess *chansess) { agentset(chansess); #endif + /* Re-enable SIGPIPE for the executed process */ + if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) { + dropbear_exit("signal() error"); + } + baseshell = basename(usershell); if (chansess->cmd != NULL) { @@ -921,7 +936,7 @@ void svr_chansessinitialise() { /* add a new environment variable, allocating space for the entry */ void addnewvar(const char* param, const char* var) { - char* newvar; + char* newvar = NULL; int plen, vlen; plen = strlen(param); diff --git a/svr-tcpfwd.c b/svr-tcpfwd.c index 0eccae4..0f22a23 100644 --- a/svr-tcpfwd.c +++ b/svr-tcpfwd.c @@ -208,7 +208,7 @@ static int newtcpdirect(struct Channel * channel) { char portstring[NI_MAXSERV]; int sock; int len; - int ret = DROPBEAR_FAILURE; + int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; if (opts.nolocaltcp) { TRACE(("leave newtcpdirect: local tcp forwarding disabled")); @@ -240,6 +240,7 @@ static int newtcpdirect(struct Channel * channel) { snprintf(portstring, sizeof(portstring), "%d", destport); sock = connect_remote(desthost, portstring, 1, NULL); if (sock < 0) { + err = SSH_OPEN_CONNECT_FAILED; TRACE(("leave newtcpdirect: sock failed")); goto out; } @@ -253,13 +254,13 @@ static int newtcpdirect(struct Channel * channel) { channel->infd = sock; channel->initconn = 1; - ret = DROPBEAR_SUCCESS; + err = SSH_OPEN_IN_PROGRESS; out: m_free(desthost); m_free(orighost); - TRACE(("leave newtcpdirect: ret %d", ret)); - return ret; + TRACE(("leave newtcpdirect: err %d", err)); + return err; } #endif diff --git a/svr-x11fwd.c b/svr-x11fwd.c index 0f4f71e..a8d1cd5 100644 --- a/svr-x11fwd.c +++ b/svr-x11fwd.c @@ -131,7 +131,7 @@ static void x11accept(struct Listener* listener, int sock) { void x11setauth(struct ChanSess *chansess) { char display[20]; /* space for "localhost:12345.123" */ - FILE * authprog; + FILE * authprog = NULL; int val; if (chansess->x11listener == NULL) { @@ -187,7 +187,7 @@ static const struct ChanType chan_x11 = { static int send_msg_channel_open_x11(int fd, struct sockaddr_in* addr) { - char* ipstring; + char* ipstring = NULL; if (send_msg_channel_open_init(fd, &chan_x11) == DROPBEAR_SUCCESS) { ipstring = inet_ntoa(addr->sin_addr); -- cgit v1.2.3 From 42c691a051af521efa3cd74045eed7db33a38ca2 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Mon, 20 Dec 2004 13:11:15 +0000 Subject: Cleaned up the random code, use /dev/random by default, and remove the addrandom() function which wasn't used. --HG-- extra : convert_revision : d560d214ad20001f8ef5d5494ff3c97e6184d9cc --- options.h | 38 +++++++++++++++++++++++--------------- random.c | 30 ++++++------------------------ 2 files changed, 29 insertions(+), 39 deletions(-) (limited to 'random.c') diff --git a/options.h b/options.h index c6b727f..7a8f1fd 100644 --- a/options.h +++ b/options.h @@ -128,19 +128,21 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */ #define ENABLE_CLI_PASSWORD_AUTH #define ENABLE_CLI_PUBKEY_AUTH -/* Random device to use - you must specify _one only_. - * DEV_URANDOM is recommended on hosts with a good /dev/urandom, otherwise use - * PRNGD and run prngd, specifying the socket. This device must be able to - * produce a large amount of random data, so using /dev/random or Entropy - * Gathering Daemon (egd) may result in halting, as it waits for more random - * data */ -#define DROPBEAR_DEV_URANDOM /* use /dev/urandom */ - -/*#undef DROPBEAR_PRNGD */ /* use prngd socket - you must manually set up prngd - to produce output */ -#ifndef DROPBEAR_PRNGD_SOCKET -#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng" -#endif +/* Random device to use - define either DROPBEAR_RANDOM_DEV or + * DROPBEAR_PRNGD_SOCKET. + * DROPBEAR_RANDOM_DEV is recommended on hosts with a good /dev/(u)random, + * otherwise use run prngd (or egd if you want), specifying the socket. + * The device will be queried for a few dozen bytes of seed a couple of times + * per session (or more for very long-lived sessions). */ + +/* If you are lacking entropy on the system then using /dev/urandom + * will prevent Dropbear from blocking on the device. This could + * however significantly reduce the security of your ssh connections + * if the PRNG state becomes simpler. */ +#define DROPBEAR_RANDOM_DEV "/dev/random" + +/* prngd must be manually set up to produce output */ +/*#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng"*/ /* Specify the number of clients we will allow to be connected but * not yet authenticated. After this limit, connections are rejected */ @@ -213,8 +215,6 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */ #define MAX_BANNER_SIZE 2000 /* this is 25*80 chars, any more is foolish */ #define MAX_BANNER_LINES 20 /* How many lines the client will display */ -#define DEV_URANDOM "/dev/urandom" - /* the number of NAME=VALUE pairs to malloc for environ, if we don't have * the clearenv() function */ #define ENV_SIZE 100 @@ -336,6 +336,14 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */ #error "You can't turn on PASSWORD and PAM auth both at once. Fix it in options.h" #endif +#if defined(DROPBEAR_RANDOM_DEV) && defined(DROPBEAR_PRNGD_SOCKET) +#error "You can't turn on DROPBEAR_PRNGD_SOCKET and DROPBEAR_RANDOM_DEV at once" +#endif + +#if !defined(DROPBEAR_RANDOM_DEV) && !defined(DROPBEAR_PRNGD_SOCKET) +#error "You must choose one of DROPBEAR_PRNGD_SOCKET or DROPBEAR_RANDOM_DEV in options.h" +#endif + /* We use dropbear_client and dropbear_server as shortcuts to avoid redundant * code, if we're just compiling as client or server */ #if defined(DROPBEAR_SERVER) && defined(DROPBEAR_CLIENT) diff --git a/random.c b/random.c index 65a9c64..e1c586e 100644 --- a/random.c +++ b/random.c @@ -38,7 +38,7 @@ unsigned char hashpool[SHA1_HASH_SIZE]; static void readrand(unsigned char* buf, unsigned int buflen); -/* The basic setup is we read some data from DEV_URANDOM or PRNGD and hash it +/* The basic setup is we read some data from /dev/(u)random or prngd and hash it * into hashpool. To read data, we hash together current hashpool contents, * and a counter. We feed more data in by hashing the current pool and new * data into the pool. @@ -53,19 +53,19 @@ static void readrand(unsigned char* buf, unsigned int buflen) { int readfd; unsigned int readpos; int readlen; -#ifdef DROPBEAR_EGD +#ifdef DROPBEAR_PRNGD_SOCKET struct sockaddr_un egdsock; char egdcmd[2]; #endif -#ifdef DROPBEAR_DEV_URANDOM - readfd = open(DEV_URANDOM, O_RDONLY); +#ifdef DROPBEAR_RANDOM_DEV + readfd = open(DROPBEAR_RANDOM_DEV, O_RDONLY); if (readfd < 0) { dropbear_exit("couldn't open random device"); } #endif -#ifdef DROPBEAR_EGD +#ifdef DROPBEAR_PRNGD_SOCKET memset((void*)&egdsock, 0x0, sizeof(egdsock)); egdsock.sun_family = AF_UNIX; strlcpy(egdsock.sun_path, DROPBEAR_EGD_SOCKET, @@ -105,7 +105,7 @@ static void readrand(unsigned char* buf, unsigned int buflen) { close (readfd); } -/* initialise the prng from /dev/urandom or prngd */ +/* initialise the prng from /dev/(u)random or prngd */ void seedrandom() { unsigned char readbuf[INIT_SEED_SIZE]; @@ -159,21 +159,3 @@ void genrandom(unsigned char* buf, unsigned int len) { } m_burn(hash, sizeof(hash)); } - -/* Adds entropy to the PRNG state. As long as the hash is strong, then we - * don't need to worry about entropy being added "diluting" the current - * state - it should only make it stronger. */ -void addrandom(unsigned char* buf, unsigned int len) { - - hash_state hs; - if (!donerandinit) { - dropbear_exit("seedrandom not done"); - } - - sha1_init(&hs); - sha1_process(&hs, (void*)buf, len); - sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); - sha1_done(&hs, hashpool); - counter = 0; - -} -- cgit v1.2.3 From 6d752982848c1dba3c776ec8365c7811322cbd73 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Mon, 27 Dec 2004 16:38:44 +0000 Subject: random.c: fix missed instance of DROPBEAR_EGD_SOCKET --HG-- extra : convert_revision : 0be7aaee2230fa65f252b2e74deee7102558ceb6 --- random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'random.c') diff --git a/random.c b/random.c index e1c586e..c69f641 100644 --- a/random.c +++ b/random.c @@ -68,7 +68,7 @@ static void readrand(unsigned char* buf, unsigned int buflen) { #ifdef DROPBEAR_PRNGD_SOCKET memset((void*)&egdsock, 0x0, sizeof(egdsock)); egdsock.sun_family = AF_UNIX; - strlcpy(egdsock.sun_path, DROPBEAR_EGD_SOCKET, + strlcpy(egdsock.sun_path, DROPBEAR_PRNGD_SOCKET, sizeof(egdsock.sun_path)); readfd = socket(PF_UNIX, SOCK_STREAM, 0); -- cgit v1.2.3 From b952231df1e7d8f890d7af9d7ce5c81f0e08150d Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sun, 24 Apr 2005 15:56:36 +0000 Subject: * warn if we seem to be blocking on /dev/random --HG-- extra : convert_revision : a160efd238030ac4f7fd8304c5a87928145feccc --- TODO | 3 --- random.c | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'random.c') diff --git a/TODO b/TODO index 7acc8c0..cfd045b 100644 --- a/TODO +++ b/TODO @@ -4,9 +4,6 @@ Things which might need doing: - Make options.h generated from configure perhaps? -- some sort of warning when blocking on random? (could be difficult, - investigate alarm() perhaps) - - Improved queueing of unauthed connections - handle /etc/environment in AIX diff --git a/random.c b/random.c index c69f641..e45f474 100644 --- a/random.c +++ b/random.c @@ -50,6 +50,7 @@ static void readrand(unsigned char* buf, unsigned int buflen); static void readrand(unsigned char* buf, unsigned int buflen) { + static int already_blocked = 0; int readfd; unsigned int readpos; int readlen; @@ -92,6 +93,24 @@ static void readrand(unsigned char* buf, unsigned int buflen) { /* read the actual random data */ readpos = 0; do { + if (!already_blocked) + { + int ret; + struct timeval timeout; + fd_set read_fds; + + timeout.tv_sec = 2; /* two seconds should be enough */ + timeout.tv_usec = 0; + + FD_ZERO(&read_fds); + FD_SET(readfd, &read_fds); + ret = select(readfd + 1, &read_fds, NULL, NULL, &timeout); + if (ret == 0) + { + dropbear_log(LOG_INFO, "Warning: Reading the random source seems to have blocked.\nIf you experience problems, you probably need to find a better entropy source."); + already_blocked = 1; + } + } readlen = read(readfd, &buf[readpos], buflen - readpos); if (readlen <= 0) { if (readlen < 0 && errno == EINTR) { -- cgit v1.2.3 From cf585ba1dee7a7e1f2fbc90d2251d99b7da66a7e Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 5 May 2005 03:58:21 +0000 Subject: - refactored random mp_int generation and byte->mp_int code - added RSA blinding --HG-- extra : convert_revision : 5d5b4657a24a1c8f53c6fc45d5ec29ddb85fb45a --- bignum.c | 4 +-- bignum.h | 2 +- common-kex.c | 24 +++-------------- dss.c | 30 ++++++--------------- gendss.c | 28 +++----------------- genrsa.c | 5 +--- random.c | 36 +++++++++++++++++++++++++ random.h | 3 +++ rsa.c | 86 +++++++++++++++++++++++++++++++++++++++--------------------- 9 files changed, 115 insertions(+), 103 deletions(-) (limited to 'random.c') diff --git a/bignum.c b/bignum.c index 97901fb..60b5220 100644 --- a/bignum.c +++ b/bignum.c @@ -52,9 +52,9 @@ void m_mp_init_multi(mp_int *mp, ...) va_end(args); } -void bytestomp(mp_int *mp, unsigned char* bytes, unsigned int len) { +void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len) { - if (mp_read_unsigned_bin(mp, bytes, len) != MP_OKAY) { + if (mp_read_unsigned_bin(mp, (unsigned char*)bytes, len) != MP_OKAY) { dropbear_exit("mem alloc error"); } } diff --git a/bignum.h b/bignum.h index 2a807af..042f811 100644 --- a/bignum.h +++ b/bignum.h @@ -29,7 +29,7 @@ void m_mp_init(mp_int *mp); void m_mp_init_multi(mp_int *mp, ...); -void bytestomp(mp_int *mp, unsigned char* bytes, unsigned int len); +void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len); void sha1_process_mp(hash_state *hs, mp_int *mp); #endif /* _BIGNUM_H_ */ diff --git a/common-kex.c b/common-kex.c index a2336c5..8a8aa93 100644 --- a/common-kex.c +++ b/common-kex.c @@ -469,18 +469,13 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { DEF_MP_INT(dh_p); DEF_MP_INT(dh_q); DEF_MP_INT(dh_g); - unsigned char randbuf[DH_P_LEN]; - int dh_q_len; TRACE(("enter send_msg_kexdh_reply")) m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL); /* read the prime and generator*/ - if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN) - != MP_OKAY) { - dropbear_exit("Diffie-Hellman error"); - } + bytes_to_mp(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN); if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) { dropbear_exit("Diffie-Hellman error"); @@ -495,16 +490,8 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { dropbear_exit("Diffie-Hellman error"); } - dh_q_len = mp_unsigned_bin_size(&dh_q); - - /* calculate our random value dh_y */ - do { - assert((unsigned int)dh_q_len <= sizeof(randbuf)); - genrandom(randbuf, dh_q_len); - if (mp_read_unsigned_bin(dh_priv, randbuf, dh_q_len) != MP_OKAY) { - dropbear_exit("Diffie-Hellman error"); - } - } while (mp_cmp(dh_priv, &dh_q) == MP_GT || mp_cmp_d(dh_priv, 0) != MP_GT); + /* Generate a private portion 0 < dh_priv < dh_q */ + gen_random_mpint(&dh_q, dh_priv); /* f = g^y mod p */ if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) { @@ -526,10 +513,7 @@ void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, /* read the prime and generator*/ mp_init(&dh_p); - if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN) - != MP_OKAY) { - dropbear_exit("Diffie-Hellman error"); - } + bytes_to_mp(&dh_p, dh_p_val, DH_P_LEN); /* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */ if (mp_cmp(dh_pub_them, &dh_p) != MP_LT diff --git a/dss.c b/dss.c index 5cf018d..cb877ca 100644 --- a/dss.c +++ b/dss.c @@ -190,10 +190,8 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, /* create the signature - s' and r' are the received signatures in buf */ /* w = (s')-1 mod q */ /* let val1 = s' */ - if (mp_read_unsigned_bin(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE) - != MP_OKAY) { - goto out; - } + bytes_to_mp(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE); + if (mp_cmp(&val1, key->q) != MP_LT) { TRACE(("verify failed, s' >= q")) goto out; @@ -205,9 +203,8 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, /* u1 = ((SHA(M')w) mod q */ /* let val1 = SHA(M') = msghash */ - if (mp_read_unsigned_bin(&val1, msghash, SHA1_HASH_SIZE) != MP_OKAY) { - goto out; - } + bytes_to_mp(&val1, msghash, SHA1_HASH_SIZE); + /* let val3 = u1 = ((SHA(M')w) mod q */ if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) { goto out; @@ -215,10 +212,7 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, /* u2 = ((r')w) mod q */ /* let val1 = r' */ - if (mp_read_unsigned_bin(&val1, &string[0], SHA1_HASH_SIZE) - != MP_OKAY) { - goto out; - } + bytes_to_mp(&val1, &string[0], SHA1_HASH_SIZE); if (mp_cmp(&val1, key->q) != MP_LT) { TRACE(("verify failed, r' >= q")) goto out; @@ -306,8 +300,6 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data, unsigned char *privkeytmp; unsigned char proto_k[SHA512_HASH_SIZE]; DEF_MP_INT(dss_protok); -#else - unsigned char kbuf[SHA1_HASH_SIZE]; #endif DEF_MP_INT(dss_k); DEF_MP_INT(dss_m); @@ -345,22 +337,16 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data, /* generate k */ m_mp_init(&dss_protok); - bytestomp(&dss_protok, proto_k, SHA512_HASH_SIZE); + bytes_to_mp(&dss_protok, proto_k, SHA512_HASH_SIZE); mp_mod(&dss_protok, key->q, &dss_k); mp_clear(&dss_protok); m_burn(proto_k, SHA512_HASH_SIZE); #else /* DSS_PROTOK not defined*/ - do { - genrandom(kbuf, SHA1_HASH_SIZE); - if (mp_read_unsigned_bin(&dss_k, kbuf, SHA1_HASH_SIZE) != MP_OKAY) { - dropbear_exit("dss error"); - } - } while (mp_cmp(&dss_k, key->q) == MP_GT || mp_cmp_d(&dss_k, 0) != MP_GT); - m_burn(kbuf, SHA1_HASH_SIZE); + gen_random_mpint(key->q, &dss_k); #endif /* now generate the actual signature */ - bytestomp(&dss_m, msghash, SHA1_HASH_SIZE); + bytes_to_mp(&dss_m, msghash, SHA1_HASH_SIZE); /* g^k mod p */ if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) != MP_OKAY) { diff --git a/gendss.c b/gendss.c index d589722..bf46d3d 100644 --- a/gendss.c +++ b/gendss.c @@ -77,10 +77,7 @@ static void getq(dss_key *key) { buf[0] |= 0x80; /* top bit high */ buf[QSIZE-1] |= 0x01; /* bottom bit high */ - if (mp_read_unsigned_bin(key->q, buf, QSIZE) != MP_OKAY) { - fprintf(stderr, "dss key generation failed\n"); - exit(1); - } + bytes_to_mp(key->q, buf, QSIZE); /* 18 rounds are required according to HAC */ if (mp_prime_next_prime(key->q, 18, 0) != MP_OKAY) { @@ -116,10 +113,7 @@ static void getp(dss_key *key, unsigned int size) { buf[0] |= 0x80; /* set the top bit high */ /* X is a random mp_int */ - if (mp_read_unsigned_bin(&tempX, buf, size) != MP_OKAY) { - fprintf(stderr, "dss key generation failed\n"); - exit(1); - } + bytes_to_mp(&tempX, buf, size); /* C = X mod 2q */ if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) { @@ -147,6 +141,7 @@ static void getp(dss_key *key, unsigned int size) { } while (!result); mp_clear_multi(&tempX, &tempC, &tempP, &temp2q, NULL); + m_burn(buf, size); m_free(buf); } @@ -189,22 +184,7 @@ static void getg(dss_key * key) { static void getx(dss_key *key) { - DEF_MP_INT(val); - char buf[QSIZE]; - - m_mp_init(&val); - - do { - genrandom(buf, QSIZE); - - if (mp_read_unsigned_bin(&val, buf, QSIZE) != MP_OKAY) { - fprintf(stderr, "dss key generation failed\n"); - } - } while ((mp_cmp_d(&val, 1) == MP_GT) && (mp_cmp(&val, key->q) == MP_LT)); - - mp_copy(&val, key->x); - mp_clear(&val); - + gen_random_mpint(key->q, key->x); } static void gety(dss_key *key) { diff --git a/genrsa.c b/genrsa.c index 5711519..73a7984 100644 --- a/genrsa.c +++ b/genrsa.c @@ -108,10 +108,7 @@ static void getrsaprime(mp_int* prime, mp_int *primeminus, genrandom(buf, size+1); buf[0] |= 0x80; /* MSB set */ - if (mp_read_unsigned_bin(prime, buf, size+1) != MP_OKAY) { - fprintf(stderr, "rsa generation failed\n"); - exit(1); - } + bytes_to_mp(prime, buf, size+1); /* find the next integer which is prime, 8 round of miller-rabin */ if (mp_prime_next_prime(prime, 8, 0) != MP_OKAY) { diff --git a/random.c b/random.c index c69f641..2b2777a 100644 --- a/random.c +++ b/random.c @@ -25,6 +25,7 @@ #include "includes.h" #include "buffer.h" #include "dbutil.h" +#include "bignum.h" int donerandinit = 0; @@ -159,3 +160,38 @@ void genrandom(unsigned char* buf, unsigned int len) { } m_burn(hash, sizeof(hash)); } + +/* Generates a random mp_int. + * max is a *mp_int specifying an upper bound. + * rand must be an initialised *mp_int for the result. + * the result rand satisfies: 0 < rand < max + * */ +void gen_random_mpint(mp_int *max, mp_int *rand) { + + unsigned char *randbuf = NULL; + unsigned int len = 0; + const char masks[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; + + const int size_bits = mp_count_bits(max); + + len = size_bits / 8; + if ((size_bits % 8) != 0) { + len += 1; + } + + randbuf = (unsigned char*)m_malloc(len); + do { + genrandom(randbuf, len); + /* Mask out the unrequired bits - mp_read_unsigned_bin expects + * MSB first.*/ + randbuf[0] &= masks[size_bits % 8]; + + bytes_to_mp(rand, randbuf, len); + + /* keep regenerating until we get one satisfying + * 0 < rand < max */ + } while ( ( (max != NULL) && (mp_cmp(rand, max) != MP_LT) ) + || (mp_cmp_d(rand, 0) != MP_GT) ); + m_burn(randbuf, len); + m_free(randbuf); +} diff --git a/random.h b/random.h index 91aa342..5ec1f24 100644 --- a/random.h +++ b/random.h @@ -25,8 +25,11 @@ #ifndef _RANDOM_H_ #define _RANDOM_H_ +struct mp_int; + void seedrandom(); void genrandom(unsigned char* buf, int len); void addrandom(unsigned char* buf, int len); +void gen_random_mpint(mp_int *max, mp_int *rand); #endif /* _RANDOM_H_ */ diff --git a/rsa.c b/rsa.c index 1ac0357..8b24360 100644 --- a/rsa.c +++ b/rsa.c @@ -38,8 +38,9 @@ #ifdef DROPBEAR_RSA -static mp_int * rsa_pad_em(rsa_key * key, - const unsigned char * data, unsigned int len); +static void rsa_pad_em(rsa_key * key, + const unsigned char * data, unsigned int len, + mp_int * rsa_em); /* Load a public rsa key from a buffer, initialising the values. * The key will have the same format as buf_put_rsa_key. @@ -203,14 +204,14 @@ int buf_rsa_verify(buffer * buf, rsa_key *key, const unsigned char* data, unsigned int slen; DEF_MP_INT(rsa_s); DEF_MP_INT(rsa_mdash); - mp_int *rsa_em = NULL; + DEF_MP_INT(rsa_em); int ret = DROPBEAR_FAILURE; TRACE(("enter buf_rsa_verify")) assert(key != NULL); - m_mp_init_multi(&rsa_mdash, &rsa_s, NULL); + m_mp_init_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL); slen = buf_getint(buf); if (slen != (unsigned int)mp_unsigned_bin_size(key->n)) { @@ -231,29 +232,25 @@ int buf_rsa_verify(buffer * buf, rsa_key *key, const unsigned char* data, } /* create the magic PKCS padded value */ - rsa_em = rsa_pad_em(key, data, len); + rsa_pad_em(key, data, len, &rsa_em); if (mp_exptmod(&rsa_s, key->e, key->n, &rsa_mdash) != MP_OKAY) { TRACE(("failed exptmod rsa_s")) goto out; } - if (mp_cmp(rsa_em, &rsa_mdash) == MP_EQ) { + if (mp_cmp(&rsa_em, &rsa_mdash) == MP_EQ) { /* signature is valid */ TRACE(("success!")) ret = DROPBEAR_SUCCESS; } out: - if (rsa_em) { - mp_clear(rsa_em); - m_free(rsa_em); - } - mp_clear_multi(&rsa_mdash, &rsa_s, NULL); + mp_clear_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL); TRACE(("leave buf_rsa_verify: ret %d", ret)) return ret; - } + #endif /* DROPBEAR_SIGNKEY_VERIFY */ /* Sign the data presented with key, writing the signature contents @@ -264,22 +261,56 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data, unsigned int nsize, ssize; unsigned int i; DEF_MP_INT(rsa_s); - mp_int *rsa_em = NULL; + DEF_MP_INT(rsa_tmp1); + DEF_MP_INT(rsa_tmp2); + DEF_MP_INT(rsa_tmp3); + unsigned char *tmpbuf; TRACE(("enter buf_put_rsa_sign")) assert(key != NULL); - rsa_em = rsa_pad_em(key, data, len); + m_mp_init_multi(&rsa_s, &rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL); - m_mp_init(&rsa_s); + rsa_pad_em(key, data, len, &rsa_tmp1); /* the actual signing of the padded data */ + +#define RSA_BLINDING +#ifdef RSA_BLINDING + + /* With blinding, s = (r^(-1))((em)*r^e)^d mod n */ + + /* generate the r blinding value */ + /* rsa_tmp2 is r */ + gen_random_mpint(key->n, &rsa_tmp2); + + /* rsa_tmp1 is em */ + /* em' = em * r^e mod n */ + + mp_exptmod(&rsa_tmp2, key->e, key->n, &rsa_s); /* rsa_s used as a temp var*/ + mp_invmod(&rsa_tmp2, key->n, &rsa_tmp3); + mp_mulmod(&rsa_tmp1, &rsa_s, key->n, &rsa_tmp2); + + /* rsa_tmp2 is em' */ + /* s' = (em')^d mod n */ + mp_exptmod(&rsa_tmp2, key->d, key->n, &rsa_tmp1); + + /* rsa_tmp1 is s' */ + /* rsa_tmp3 is r^(-1) mod n */ + /* s = (s')r^(-1) mod n */ + mp_mulmod(&rsa_tmp1, &rsa_tmp3, key->n, &rsa_s); + +#else + /* s = em^d mod n */ - if (mp_exptmod(rsa_em, key->d, key->n, &rsa_s) != MP_OKAY) { + /* rsa_tmp1 is em */ + if (mp_exptmod(&rsa_tmp1, key->d, key->n, &rsa_s) != MP_OKAY) { dropbear_exit("rsa error"); } - mp_clear(rsa_em); - m_free(rsa_em); + +#endif /* RSA_BLINDING */ + + mp_clear_multi(&rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL); /* create the signature to return */ buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN); @@ -318,9 +349,12 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data, * * prefix is the ASN1 designator prefix, * hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 + * + * rsa_em must be a pointer to an initialised mp_int. */ -static mp_int * rsa_pad_em(rsa_key * key, - const unsigned char * data, unsigned int len) { +static void rsa_pad_em(rsa_key * key, + const unsigned char * data, unsigned int len, + mp_int * rsa_em) { /* ASN1 designator (including the 0x00 preceding) */ const char rsa_asn1_magic[] = @@ -330,7 +364,6 @@ static mp_int * rsa_pad_em(rsa_key * key, buffer * rsa_EM = NULL; hash_state hs; unsigned int nsize; - mp_int * rsa_em = NULL; assert(key != NULL); assert(data != NULL); @@ -358,16 +391,9 @@ static mp_int * rsa_pad_em(rsa_key * key, /* Create the mp_int from the encoded bytes */ buf_setpos(rsa_EM, 0); - rsa_em = (mp_int*)m_malloc(sizeof(mp_int)); - m_mp_init(rsa_em); - if (mp_read_unsigned_bin(rsa_em, buf_getptr(rsa_EM, rsa_EM->size), - rsa_EM->size) != MP_OKAY) { - dropbear_exit("rsa error"); - } + bytes_to_mp(rsa_em, buf_getptr(rsa_EM, rsa_EM->size), + rsa_EM->size); buf_free(rsa_EM); - - return rsa_em; - } #endif /* DROPBEAR_RSA */ -- cgit v1.2.3 From 0f0a8472d7b42b34e7aef276f765fd3ef76e8ae4 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 10 May 2005 17:02:05 +0000 Subject: * add a "label" argument to printhex() * make some vars static in random.c --HG-- extra : convert_revision : ef941a918e42e8af23b132946f44e6836a327e71 --- dbutil.c | 3 ++- dbutil.h | 2 +- random.c | 6 +++--- rsa.c | 7 ++++--- 4 files changed, 10 insertions(+), 8 deletions(-) (limited to 'random.c') diff --git a/dbutil.c b/dbutil.c index 5f3a45d..45c720e 100644 --- a/dbutil.c +++ b/dbutil.c @@ -430,10 +430,11 @@ char* getaddrhostname(struct sockaddr_storage * addr) { } #ifdef DEBUG_TRACE -void printhex(unsigned char* buf, int len) { +void printhex(const char * label, const unsigned char * buf, int len) { int i; + fprintf(stderr, "%s\n", label); for (i = 0; i < len; i++) { fprintf(stderr, "%02x", buf[i]); if (i % 16 == 15) { diff --git a/dbutil.h b/dbutil.h index 6363f70..d904949 100644 --- a/dbutil.h +++ b/dbutil.h @@ -41,7 +41,7 @@ void dropbear_close(const char* format, ...); void dropbear_log(int priority, const char* format, ...); #ifdef DEBUG_TRACE void dropbear_trace(const char* format, ...); -void printhex(unsigned char* buf, int len); +void printhex(const char * label, const unsigned char * buf, int len); extern int debug_trace; #endif char * stripcontrol(const char * text); diff --git a/random.c b/random.c index 8012148..d58c8a8 100644 --- a/random.c +++ b/random.c @@ -27,13 +27,13 @@ #include "dbutil.h" #include "bignum.h" -int donerandinit = 0; +static int donerandinit = 0; /* this is used to generate unique output from the same hashpool */ -unsigned int counter = 0; +static unsigned int counter = 0; #define MAX_COUNTER 1000000/* the max value for the counter, so it won't loop */ -unsigned char hashpool[SHA1_HASH_SIZE]; +static unsigned char hashpool[SHA1_HASH_SIZE]; #define INIT_SEED_SIZE 32 /* 256 bits */ diff --git a/rsa.c b/rsa.c index 8b24360..f86fdd9 100644 --- a/rsa.c +++ b/rsa.c @@ -333,7 +333,7 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data, mp_clear(&rsa_s); #if defined(DEBUG_RSA) && defined(DEBUG_TRACE) - printhex(buf->data, buf->len); + printhex("RSA sig", buf->data, buf->len); #endif @@ -357,10 +357,11 @@ static void rsa_pad_em(rsa_key * key, mp_int * rsa_em) { /* ASN1 designator (including the 0x00 preceding) */ - const char rsa_asn1_magic[] = + const unsigned char rsa_asn1_magic[] = {0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}; -#define RSA_ASN1_MAGIC_LEN 16 + const unsigned int RSA_ASN1_MAGIC_LEN = 16; + buffer * rsa_EM = NULL; hash_state hs; unsigned int nsize; -- cgit v1.2.3 From 1eb9209afef2046bbf74f8d2ffb0f357bdb992bb Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sat, 11 Feb 2006 15:15:37 +0000 Subject: Only read /dev/random once when the program starts rather than for every connection, to "conserve entropy". --HG-- extra : convert_revision : 21df240b71c0af8454725dec9abb428dd4bb97a2 --- cli-session.c | 8 +++----- random.c | 31 ++++++++++++++++++++++++++++--- random.h | 1 + svr-chansession.c | 2 +- svr-main.c | 4 +++- svr-session.c | 6 +++--- 6 files changed, 39 insertions(+), 13 deletions(-) (limited to 'random.c') diff --git a/cli-session.c b/cli-session.c index 0e906e6..35510fa 100644 --- a/cli-session.c +++ b/cli-session.c @@ -76,12 +76,14 @@ static const struct ChanType *cli_chantypes[] = { void cli_session(int sock, char* remotehost) { + seedrandom(); + crypto_init(); + common_session_init(sock, remotehost); chaninitialise(cli_chantypes); - /* Set up cli_ses vars */ cli_session_init(); @@ -91,12 +93,8 @@ void cli_session(int sock, char* remotehost) { /* Exchange identification */ session_identification(); - seedrandom(); - send_msg_kexinit(); - /* XXX here we do stuff differently */ - session_loop(cli_sessionloop); /* Not reached */ diff --git a/random.c b/random.c index d58c8a8..cbbe016 100644 --- a/random.c +++ b/random.c @@ -30,8 +30,8 @@ static int donerandinit = 0; /* this is used to generate unique output from the same hashpool */ -static unsigned int counter = 0; -#define MAX_COUNTER 1000000/* the max value for the counter, so it won't loop */ +static uint32_t counter = 0; +#define MAX_COUNTER 1<<31 /* the max value for the counter, so it won't loop */ static unsigned char hashpool[SHA1_HASH_SIZE]; @@ -132,7 +132,8 @@ void seedrandom() { hash_state hs; - /* initialise so compilers will be happy about hashing it */ + /* initialise so that things won't warn about + * hashing an undefined buffer */ if (!donerandinit) { m_burn(hashpool, sizeof(hashpool)); } @@ -150,6 +151,30 @@ void seedrandom() { donerandinit = 1; } +/* hash the current random pool with some unique identifiers + * for this process and point-in-time. this is used to separate + * the random pools for fork()ed processes. */ +void reseedrandom() { + + pid_t pid; + struct timeval tv; + + if (!donerandinit) { + dropbear_exit("seedrandom not done"); + } + + pid = getpid(); + gettimeofday(&tv, NULL); + + hash_state hs; + unsigned char hash[SHA1_HASH_SIZE]; + sha1_init(&hs); + sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); + sha1_process(&hs, (void*)&pid, sizeof(pid)); + sha1_process(&hs, (void*)&tv, sizeof(tv)); + sha1_done(&hs, hashpool); +} + /* return len bytes of pseudo-random data */ void genrandom(unsigned char* buf, unsigned int len) { diff --git a/random.h b/random.h index 5ec1f24..84a0a39 100644 --- a/random.h +++ b/random.h @@ -28,6 +28,7 @@ struct mp_int; void seedrandom(); +void reseedrandom(); void genrandom(unsigned char* buf, int len); void addrandom(unsigned char* buf, int len); void gen_random_mpint(mp_int *max, mp_int *rand); diff --git a/svr-chansession.c b/svr-chansession.c index 03ac40a..a645f69 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -833,7 +833,7 @@ static void execchild(struct ChanSess *chansess) { svr_opts.hostkey = NULL; /* overwrite the prng state */ - seedrandom(); + reseedrandom(); /* close file descriptors except stdin/stdout/stderr * Need to be sure FDs are closed here to avoid reading files as root */ diff --git a/svr-main.c b/svr-main.c index 4641e24..aef00f6 100644 --- a/svr-main.c +++ b/svr-main.c @@ -83,7 +83,7 @@ static void main_inetd() { int remoteaddrlen; char * addrstring = NULL; - /* Set up handlers, syslog */ + /* Set up handlers, syslog, seed random */ commonsetup(); remoteaddrlen = sizeof(remoteaddr); @@ -359,6 +359,8 @@ static void commonsetup() { /* Now we can setup the hostkeys - needs to be after logging is on, * otherwise we might end up blatting error messages to the socket */ loadhostkeys(); + + seedrandom(); } /* Set up listening sockets for all the requested ports */ diff --git a/svr-session.c b/svr-session.c index 408209d..70029f8 100644 --- a/svr-session.c +++ b/svr-session.c @@ -78,7 +78,9 @@ void svr_session(int sock, int childpipe, char* remotehost, char *addrstring) { struct timeval timeout; - + + reseedrandom(); + crypto_init(); common_session_init(sock, remotehost); @@ -110,8 +112,6 @@ void svr_session(int sock, int childpipe, /* exchange identification, version etc */ session_identification(); - seedrandom(); - /* start off with key exchange */ send_msg_kexinit(); -- cgit v1.2.3