Mailing List Archive

svn commit: vpnc r541 - in /trunk: config.c sysdep.c sysdep.h vpnc.8.template
Author: Antonio Borneo
Date: Tue Feb 18 06:09:33 2014
New Revision: 541

Log:
terminate config reading on EOT/Ctl-D instead of just on pipe close

based on original patch from Dan Williams <dcbw@redhat.com>
http://lists.unix-ag.uni-kl.de/pipermail/vpnc-devel/2013-December/004043.html

vpnc's config file processing logic uses EOF to determine when to stop
processing the config input, but if stdin is actually a pipe from a
controlling process, EOF only happens if the pipe is closed. Which
means the controlling process can't respond to any interactive requests
for information. So we need to add some other mechanism to indicate
that config processing is done that does not rely on closing stdin to
indicate this.

Also, getline() only returns on EOF (which has the problems described
above) or when it encounters sufficient newline characters;
unfortunately this precludes using getline() to handle single bytes.
Switch to fgetc() and build up the line ourselves so that we can
recognize a custom CEOT character (0x04/Ctl-D) which also terminates
reading configuration without requiring the pipe to be closed.

Modification wrt Dan's proposal:
- use same prototype as getline();
- remove trailing newline. Avoids code duplication;
- allocate buffer only if required (as getline());
- pass error through errno since feof() is not valid on CEOT;
- remove getline() from sysdep.[ch].

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>

Modified:
trunk/config.c
trunk/sysdep.c
trunk/sysdep.h
trunk/vpnc.8.template

Modified: trunk/config.c
==============================================================================
--- trunk/config.c (original)
+++ trunk/config.c Tue Feb 18 06:09:33 2014
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
@@ -95,6 +96,68 @@
printf("%02x", p[i]);
}
printf("\n");
+}
+
+#define GETLINE_MAX_BUFLEN 200
+
+/*
+ * mostly match getline() semantics but:
+ * 1) accept CEOT (Ctrl-D, 0x04) at begining of line as an input terminator
+ * 2) allocate the buffer at max line size of GETLINE_MAX_BUFLEN bytes
+ * 3) remove trailing newline
+ *
+ * Returns:
+ * -1 for errors or no line (EOF or CEOT)
+ * n the characters in line, excluding (removed) newline and training '\0'
+ */
+static ssize_t vpnc_getline(char **lineptr, size_t *n, FILE *stream)
+{
+ char *buf;
+ size_t buflen, llen = 0;
+ int c, buf_allocated = 0;
+
+ if (lineptr == NULL || n == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ buf = *lineptr;
+ buflen = *n;
+ if (buf == NULL || buflen == 0) {
+ buflen = GETLINE_MAX_BUFLEN;
+ buf = (char *)malloc(buflen);
+ if (buf == NULL)
+ return -1;
+ buf_allocated = 1;
+ }
+
+ /* Read a line from the input */
+ while (llen < buflen - 1) {
+ c = fgetc(stream);
+ if (c == EOF || feof(stream)) {
+ if (llen == 0)
+ goto eof_or_ceot;
+ else
+ break;
+ }
+ if (llen == 0 && c == CEOT)
+ goto eof_or_ceot;
+ if (c == '\n' || c == '\r')
+ break;
+ buf[llen++] = (char) c;
+ }
+
+ buf[llen] = 0;
+ if (buf_allocated) {
+ *lineptr = buf;
+ *n = buflen;
+ }
+ return llen;
+
+eof_or_ceot:
+ if (buf_allocated)
+ free(buf);
+ return -1;
}

static void config_deobfuscate(int obfuscated, int clear)
@@ -511,15 +574,12 @@
ssize_t llen;
int i;

- llen = getline(&line, &line_length, f);
- if (llen == -1 && feof(f))
+ errno = 0;
+ llen = vpnc_getline(&line, &line_length, f);
+ if (llen == -1 && errno)
+ error(1, errno, "reading `%s'", realname);
+ if (llen == -1)
break;
- if (llen == -1)
- error(1, errno, "reading `%s'", realname);
- if (llen > 0 && line[llen - 1] == '\n')
- line[--llen] = 0;
- if (llen > 0 && line[llen - 1] == '\r')
- line[--llen] = 0;
linenum++;
for (i = 0; config_names[i].name != NULL; i++) {
if (strncasecmp(config_names[i].name, line,
@@ -824,10 +884,8 @@
case CONFIG_IPSEC_GATEWAY:
case CONFIG_IPSEC_ID:
case CONFIG_XAUTH_USERNAME:
- getline(&s, &s_len, stdin);
- }
- if (s != NULL && strlen(s) > 0 && s[strlen(s) - 1] == '\n')
- s[strlen(s) - 1] = 0;
+ vpnc_getline(&s, &s_len, stdin);
+ }
config[i] = s;
}


Modified: trunk/sysdep.c
==============================================================================
--- trunk/sysdep.c (original)
+++ trunk/sysdep.c Tue Feb 18 06:09:33 2014
@@ -750,38 +750,6 @@
}
#endif

-#ifndef HAVE_GETLINE
-int getline(char **line, size_t * length, FILE * stream)
-{
- size_t len;
-#ifdef HAVE_FGETLN
- char *tmpline;
-
- tmpline = fgetln(stream, &len);
-#else
- char tmpline[512];
-
- fgets(tmpline, sizeof(tmpline), stream);
- len = strlen(tmpline);
-#endif
- if (feof(stream))
- return -1;
- if (*line == NULL) {
- *line = malloc(len + 1);
- *length = len + 1;
- }
- if (*length < len + 1) {
- *line = realloc(*line, len + 1);
- *length = len + 1;
- }
- if (*line == NULL)
- return -1;
- memcpy(*line, tmpline, len);
- (*line)[len] = '\0';
- return len;
-}
-#endif
-
#ifndef HAVE_UNSETENV
int unsetenv(const char *name)
{

Modified: trunk/sysdep.h
==============================================================================
--- trunk/sysdep.h (original)
+++ trunk/sysdep.h Tue Feb 18 06:09:33 2014
@@ -43,7 +43,6 @@
#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
#define HAVE_ERROR 1
-#define HAVE_GETLINE 1
#define HAVE_UNSETENV 1
#define HAVE_SETENV 1
#endif
@@ -54,7 +53,6 @@

#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
-#define HAVE_FGETLN 1
#define HAVE_UNSETENV 1
#define HAVE_SETENV 1
#endif
@@ -67,7 +65,6 @@

#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
-#define HAVE_FGETLN 1
#define HAVE_UNSETENV 1
#define HAVE_SETENV 1
#endif
@@ -83,7 +80,6 @@

#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
-#define HAVE_FGETLN 1
#define HAVE_UNSETENV 1
#define HAVE_SETENV 1
#endif
@@ -94,7 +90,6 @@

#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
-#define HAVE_FGETLN 1
#define HAVE_UNSETENV 1
#define HAVE_SETENV 1
#endif
@@ -106,11 +101,9 @@

#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
-#define HAVE_FGETLN 1
#define HAVE_UNSETENV 1
#define HAVE_SETENV 1
#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1070
-#define HAVE_GETLINE 1
#endif
#endif

@@ -144,8 +137,6 @@
#if defined (__CYGWIN__)
#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
-#define HAVE_GETLINE 1
-#define HAVE_FGETLN 1
#define HAVE_UNSETENV 1
#define HAVE_SETENV 1

@@ -232,9 +223,6 @@
#ifndef HAVE_ERROR
extern void error(int fd, int errorno, const char *fmt, ...);
#endif
-#ifndef HAVE_GETLINE
-extern int getline(char **line, size_t * length, FILE * stream);
-#endif
#ifndef HAVE_VASPRINTF
#include <stdarg.h>
extern int vasprintf(char **strp, const char *fmt, va_list ap);

Modified: trunk/vpnc.8.template
==============================================================================
--- trunk/vpnc.8.template (original)
+++ trunk/vpnc.8.template Tue Feb 18 06:09:33 2014
@@ -79,6 +79,16 @@
.B /etc/vpnc.conf
will be loaded.

+.PP
+
+Additionally, if the configuration
+file "-" is specified on the command-line
+vpnc will read configuration from
+stdin. The configuration is parsed and
+the connection proceeds when stdin is
+closed or the special character CEOT
+(CTRL-D) is read.
+
.SH OPTIONS
The program options can be either given as arguments (but not all of them
for security reasons) or be stored in a configuration file.

_______________________________________________
vpnc-devel mailing list
vpnc-devel@unix-ag.uni-kl.de
https://lists.unix-ag.uni-kl.de/mailman/listinfo/vpnc-devel
http://www.unix-ag.uni-kl.de/~massar/vpnc/