Compare commits

...
4 Commits
Author SHA1 Message Date
Simon Kelley 61ce600b20 --tftp-lowercase option. 2012-04-20 21:28:49 +01:00
Simon Kelley 7a14dfebbb Tidy previous commit. 2012-04-20 20:50:42 +01:00
Simon Kelley 42fb8153ba Sanitise filenames logged by TFTP 2012-04-20 17:15:01 +01:00
Simon Kelley 6f13e53886 Tidy up malloc-failure handling. 2012-04-17 14:25:06 +01:00
6 changed files with 54 additions and 30 deletions

No files matched your search

+3
View File
@@ -93,6 +93,9 @@ version 2.61
Give correct from-cache answers to explict CNAME queries. Give correct from-cache answers to explict CNAME queries.
Thanks to Rob Zwissler for spotting this. Thanks to Rob Zwissler for spotting this.
Add --dhcp-lowercase option. Thanks to Oliver Rath for the
patch.
version 2.60 version 2.60
Fix compilation problem in Mac OS X Lion. Thanks to Olaf Fix compilation problem in Mac OS X Lion. Thanks to Olaf
+6
View File
@@ -1385,6 +1385,12 @@ are accessible. It is not recommended to run dnsmasq as root with TFTP
enabled, and certainly not without specifying --tftp-root. Doing so enabled, and certainly not without specifying --tftp-root. Doing so
can expose any world-readable file on the server to any host on the net. can expose any world-readable file on the server to any host on the net.
.TP .TP
.B --tftp-lowercase
Convert filenames in TFTP requests to all lowercase. This is useful
for requests from Windows machines, which have case-insensitive
filesystems and tend to play fast-and-loose with case in filenames.
Note that dnsmasq's tftp server always converts "\\" to "/" in filenames.
.TP
.B --tftp-max=<connections> .B --tftp-max=<connections>
Set the maximum number of concurrent TFTP connections allowed. This Set the maximum number of concurrent TFTP connections allowed. This
defaults to 50. When serving a large number of TFTP connections, defaults to 50. When serving a large number of TFTP connections,
+2 -1
View File
@@ -217,7 +217,8 @@ struct event_desc {
#define OPT_CONNTRACK 35 #define OPT_CONNTRACK 35
#define OPT_FQDN_UPDATE 36 #define OPT_FQDN_UPDATE 36
#define OPT_RA 37 #define OPT_RA 37
#define OPT_LAST 38 #define OPT_TFTP_LC 38
#define OPT_LAST 39
/* extra flags for my_syslog, we use a couple of facilities since they are known /* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */ not to occupy the same bits as priorities, no matter how syslog.h is set up. */
+7 -4
View File
@@ -266,10 +266,13 @@ static int iface_allowed(struct irec **irecp, int if_index,
iface->dad = dad; iface->dad = dad;
iface->done = 0; iface->done = 0;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1))) if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
strcpy(iface->name, ifr.ifr_name); {
iface->next = *irecp; strcpy(iface->name, ifr.ifr_name);
*irecp = iface; iface->next = *irecp;
return 1; *irecp = iface;
return 1;
}
free(iface);
} }
errno = ENOMEM; errno = ENOMEM;
+3
View File
@@ -117,6 +117,7 @@ struct myoption {
#define LOPT_RA 306 #define LOPT_RA 306
#define LOPT_DUID 307 #define LOPT_DUID 307
#define LOPT_HOST_REC 308 #define LOPT_HOST_REC 308
#define LOPT_TFTP_LC 309
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
@@ -196,6 +197,7 @@ static const struct myoption opts[] =
{ "tftp-unique-root", 0, 0, LOPT_APREF }, { "tftp-unique-root", 0, 0, LOPT_APREF },
{ "tftp-root", 1, 0, LOPT_PREFIX }, { "tftp-root", 1, 0, LOPT_PREFIX },
{ "tftp-max", 1, 0, LOPT_TFTP_MAX }, { "tftp-max", 1, 0, LOPT_TFTP_MAX },
{ "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
{ "ptr-record", 1, 0, LOPT_PTR }, { "ptr-record", 1, 0, LOPT_PTR },
{ "naptr-record", 1, 0, LOPT_NAPTR }, { "naptr-record", 1, 0, LOPT_NAPTR },
{ "bridge-interface", 1, 0 , LOPT_BRIDGE }, { "bridge-interface", 1, 0 , LOPT_BRIDGE },
@@ -342,6 +344,7 @@ static struct {
{ LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL }, { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
{ LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" }, { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
{ LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL }, { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
{ LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
{ LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL }, { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
{ LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL }, { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
{ LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL }, { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
+33 -25
View File
@@ -24,6 +24,7 @@ static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
static ssize_t tftp_err_oops(char *packet, char *file); static ssize_t tftp_err_oops(char *packet, char *file);
static ssize_t get_block(char *packet, struct tftp_transfer *transfer); static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
static char *next(char **p, char *end); static char *next(char **p, char *end);
static void sanitise(char *buf);
#define OP_RRQ 1 #define OP_RRQ 1
#define OP_WRQ 2 #define OP_WRQ 2
@@ -344,9 +345,12 @@ void tftp_request(struct listener *listen, time_t now)
} }
/* cope with backslashes from windows boxen. */ /* cope with backslashes from windows boxen. */
while ((p = strchr(filename, '\\'))) for (p = filename; *p; p++)
*p = '/'; if (*p == '\\')
*p = '/';
else if (option_bool(OPT_TFTP_LC))
*p = tolower(*p);
strcpy(daemon->namebuff, "/"); strcpy(daemon->namebuff, "/");
if (prefix) if (prefix)
{ {
@@ -528,13 +532,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
if (!err) if (!err)
err = ""; err = "";
else else
{ sanitise(err);
unsigned char *q, *r;
for (q = r = (unsigned char *)err; *r; r++)
if (isprint(*r))
*(q++) = *r;
*q = 0;
}
my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"), my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
(int)ntohs(mess->block), err, (int)ntohs(mess->block), err,
@@ -562,27 +560,23 @@ void check_tftp_listeners(fd_set *rset, time_t now)
len = tftp_err_oops(daemon->packet, transfer->file->filename); len = tftp_err_oops(daemon->packet, transfer->file->filename);
endcon = 1; endcon = 1;
} }
else if (++transfer->backoff > 5) /* don't complain about timeout when we're awaiting the last
ACK, some clients never send it */
else if (++transfer->backoff > 5 && len != 0)
{ {
/* don't complain about timeout when we're awaiting the last endcon = 1;
ACK, some clients never send it */ len = 0;
if (len != 0)
{
my_syslog(MS_TFTP | LOG_ERR, _("failed sending %s to %s"),
transfer->file->filename, daemon->addrbuff);
len = 0;
endcon = 1;
}
} }
if (len != 0) if (len != 0)
while(sendto(transfer->sockfd, daemon->packet, len, 0, while(sendto(transfer->sockfd, daemon->packet, len, 0,
(struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR); (struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR);
if (endcon || len == 0) if (endcon || len == 0)
{ {
if (!endcon) strcpy(daemon->namebuff, transfer->file->filename);
my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, daemon->addrbuff); sanitise(daemon->namebuff);
my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
/* unlink */ /* unlink */
*up = tmp; *up = tmp;
/* put on queue to be sent to script and deleted */ /* put on queue to be sent to script and deleted */
@@ -621,6 +615,16 @@ static char *next(char **p, char *end)
return ret; return ret;
} }
static void sanitise(char *buf)
{
unsigned char *q, *r;
for (q = r = (unsigned char *)buf; *r; r++)
if (isprint(*r))
*(q++) = *r;
*q = 0;
}
static ssize_t tftp_err(int err, char *packet, char *message, char *file) static ssize_t tftp_err(int err, char *packet, char *message, char *file)
{ {
struct errmess { struct errmess {
@@ -629,7 +633,9 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
} *mess = (struct errmess *)packet; } *mess = (struct errmess *)packet;
ssize_t ret = 4; ssize_t ret = 4;
char *errstr = strerror(errno); char *errstr = strerror(errno);
sanitise(file);
mess->op = htons(OP_ERR); mess->op = htons(OP_ERR);
mess->err = htons(err); mess->err = htons(err);
ret += (snprintf(mess->message, 500, message, file, errstr) + 1); ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
@@ -640,7 +646,9 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
static ssize_t tftp_err_oops(char *packet, char *file) static ssize_t tftp_err_oops(char *packet, char *file)
{ {
return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file); /* May have >1 refs to file, so potentially mangle a copy of the name */
strcpy(daemon->namebuff, file);
return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), daemon->namebuff);
} }
/* return -1 for error, zero for done. */ /* return -1 for error, zero for done. */