Fix buffer overflow in ppp command prompt parsing (OpenBSD errata 2008-009).
authorHasso Tepper <hasso@dragonflybsd.org>
Tue, 11 Mar 2008 10:53:07 +0000 (10:53 +0000)
committerHasso Tepper <hasso@dragonflybsd.org>
Tue, 11 Mar 2008 10:53:07 +0000 (10:53 +0000)
Obtained-from: OpenBSD

usr.sbin/ppp/command.c
usr.sbin/ppp/systems.c
usr.sbin/ppp/systems.h

index 69df8e0..ea72f58 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/usr.sbin/ppp/command.c,v 1.230.2.18 2003/04/05 10:48:08 ume Exp $
- * $DragonFly: src/usr.sbin/ppp/command.c,v 1.3 2007/05/17 08:19:03 swildner Exp $
+ * $DragonFly: src/usr.sbin/ppp/command.c,v 1.4 2008/03/11 10:53:07 hasso Exp $
  */
 
 #include <sys/param.h>
@@ -1107,7 +1107,11 @@ command_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset)
 {
   char buff2[LINE_LEN-offset];
 
-  InterpretArg(buff, buff2);
+  if (InterpretArg(buff, buff2, sizeof buff2) == NULL) {
+    log_Printf(LogWARN, "Failed to expand command '%s': too long for the "
+               "destination buffer\n", buff);
+    return -1;
+  }
   strncpy(buff, buff2, LINE_LEN - offset - 1);
   buff[LINE_LEN - offset - 1] = '\0';
 
index 05d67db..ea78d43 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/usr.sbin/ppp/systems.c,v 1.58.2.7 2002/09/01 02:12:32 brian Exp $
- * $DragonFly: src/usr.sbin/ppp/systems.c,v 1.2 2003/06/17 04:30:01 dillon Exp $
+ * $DragonFly: src/usr.sbin/ppp/systems.c,v 1.3 2008/03/11 10:53:07 hasso Exp $
  */
 
 #include <sys/param.h>
@@ -65,9 +65,12 @@ CloseSecret(FILE *fp)
   fclose(fp);
 }
 
-/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */
+/*
+ * Move string from ``from'' to ``to'', interpreting ``~'' and $....
+ * Returns NULL if string expansion failed due to lack of buffer space.
+ */
 const char *
-InterpretArg(const char *from, char *to)
+InterpretArg(const char *from, char *to, size_t tosiz)
 {
   char *ptr, *startto, *endto;
   struct passwd *pwd;
@@ -76,12 +79,14 @@ InterpretArg(const char *from, char *to)
 
   instring = 0;
   startto = to;
-  endto = to + LINE_LEN - 1;
+  endto = to + tosiz - 1;
 
   while(issep(*from))
     from++;
 
   while (*from != '\0') {
+    if (to >= endto)
+      return NULL;
     switch (*from) {
       case '"':
         instring = !instring;
@@ -97,6 +102,8 @@ InterpretArg(const char *from, char *to)
             *to++ = '\\';      /* Pass the escapes on, maybe skipping \# */
             break;
         }
+        if (to >= endto)
+          return NULL;
         *to++ = *from++;
         break;
       case '$':
@@ -108,7 +115,7 @@ InterpretArg(const char *from, char *to)
           if (ptr) {
             len = ptr - from - 2;
             if (endto - to < len )
-              len = endto - to;
+              return NULL;
             if (len) {
               strncpy(to, from+2, len);
               to[len] = '\0';
@@ -127,9 +134,13 @@ InterpretArg(const char *from, char *to)
             *ptr++ = *from;
           *ptr = '\0';
         }
+        if (to >= endto)
+          return NULL;
         if (*to == '\0')
           *to++ = '$';
         else if ((env = getenv(to)) != NULL) {
+          if (endto - to < strlen(env))
+            return NULL;
           strncpy(to, env, endto - to);
           *endto = '\0';
           to += strlen(to);
@@ -142,13 +153,19 @@ InterpretArg(const char *from, char *to)
         if (len == 0)
           pwd = getpwuid(ID0realuid());
         else {
+          if (endto - to < len)
+            return NULL;
           strncpy(to, from, len);
           to[len] = '\0';
           pwd = getpwnam(to);
         }
+        if (to >= endto)
+          return NULL;
         if (pwd == NULL)
           *to++ = '~';
         else {
+          if (endto - to < strlen(pwd->pw_dir))
+            return NULL;
           strncpy(to, pwd->pw_dir, endto - to);
           *endto = '\0';
           to += strlen(to);
@@ -179,12 +196,17 @@ InterpretArg(const char *from, char *to)
 #define CTRL_INCLUDE (1)
 
 static int
-DecodeCtrlCommand(char *line, char *arg)
+DecodeCtrlCommand(char *line, char *arg, size_t argsiz)
 {
   const char *end;
 
   if (!strncasecmp(line, "include", 7) && issep(line[7])) {
-    end = InterpretArg(line+8, arg);
+    end = InterpretArg(line+8, arg, argsiz);
+    if (end == NULL) {
+       log_Printf(LogWARN, "Failed to expand command '%s': too long for the "
+                  "destination buffer\n", line);
+       return CTRL_UNKNOWN;
+    }
     if (*end && *end != '#')
       log_Printf(LogWARN, "usage: !include filename\n");
     else
@@ -353,7 +375,7 @@ ReadSystem(struct bundle *bundle, const char *name, const char *file,
       break;
 
     case '!':
-      switch (DecodeCtrlCommand(cp+1, arg)) {
+      switch (DecodeCtrlCommand(cp+1, arg, LINE_LEN)) {
       case CTRL_INCLUDE:
         log_Printf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg);
         n = ReadSystem(bundle, name, arg, prompt, cx, how);
index b15ebdd..c8e7281 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/usr.sbin/ppp/systems.h,v 1.14.2.3 2002/09/01 02:12:32 brian Exp $
- * $DragonFly: src/usr.sbin/ppp/systems.h,v 1.2 2003/06/17 04:30:01 dillon Exp $
+ * $DragonFly: src/usr.sbin/ppp/systems.h,v 1.3 2008/03/11 10:53:07 hasso Exp $
  */
 
 struct prompt;
@@ -41,4 +41,4 @@ extern FILE *OpenSecret(const char *);
 extern void CloseSecret(FILE *);
 extern int AllowUsers(struct cmdargs const *);
 extern int AllowModes(struct cmdargs const *);
-extern const char *InterpretArg(const char *, char *);
+extern const char *InterpretArg(const char *, char *, size_t);