Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#FFCCCC
void incorrect_password(const char *user) { 
  int ret;
  /* user names are restricted to 256 characters or less */ 
  static const char msg_format[] = "%s cannot be authenticated.\n"; 
  size_t len = strlen(user) + sizeof(msg_format); 
  char *msg = (char *)malloc(len); 
  if (msg == NULL) { 
    /* Handle error */ 
  } 
  ret = snprintf(msg, len, msg_format, user); 
  if (ret < 0) /* Handle error */ ;
  else if (ret >= len) /* Handle truncated output */ ;

  fprintf(stderr, msg); 
  free(msg); 
} 

The incorrect_password() function calculates the size of the message, allocates dynamic storage, and then constructs the message in the allocated memory using the snprintf() function. The addition operations are not checked for integer overflow because the length of the string referenced by user is known to be have a length of 256 or less. Because the %s characters are replaced by the string referenced by user in the call to snprintf(), one less byte is required to store the resulting string and terminating NULL-byte character. This is a common idiom for displaying the same message in multiple locations or when the message is difficult to build. The resulting code contains a format-string vulnerability, however, because the msg includes untrusted user input and is passed as the format-string argument in the call to fprintf().

...

Code Block
bgColor#ccccff
void incorrect_password(const char *user) { 
  int ret;
  /* user names are restricted to 256 characters or less */ 
  static const char msg_format[] = "%s cannot be authenticated.\n"; 
  size_t len = strlen(user) + sizeof(msg_format); 
  char *msg = (char *)malloc(len); 
  if (msg == NULL) { 
    /* Handle error */ 
  } 
  ret = snprintf(msg, len, msg_format, user); 
  if (ret < 0) /* Handle error */ ;
  else if (ret >= len) /* Handle truncated output */ ;

  if (fputs(msg, stderr) == EOF) {
    /* Handle error */
  }
  free(msg); 
} 

Compliant Solution (fprintf())

...

Code Block
bgColor#ccccff
void incorrect_password(const char *user) {
  static const char msg_format[] = "%s cannot be authenticated.\n"; 
  fprintf(stderr, msg_format, user);
}

...

Code Block
bgColor#FFCCCC
void incorrect_password(const char *user) {
  int ret;
  /* user names are restricted to 256 characters or less */
  static const char msg_format[] = "%s cannot be authenticated.\n"; 
  size_t len = strlen(user) + sizeof(msg_format);
  char *msg = (char *)malloc(len);
  if (msg != NULL) {
    /* Handle error */
  }
  ret = snprintf(msg, len, msg_format, user);
  if (ret < 0) /* Handle error */ ;
  else if (ret >= len) /* Handle truncated output */ ;

  syslog(LOG_INFO, msg);
  free(msg);
}

...

Code Block
bgColor#ccccff
void incorrect_password(const char *user) {
  static const char msg_format[] = "%s cannot be authenticated.\n"; 
  syslog(LOG_INFO, msg_format, user);
}

...

Compass/ROSE can detect violations of this rule.

Klocwork Version 8.0.4.16 can detect violations of this rule with the SV.FMTSTR.GENERIC and SV.TAINTED.FMTSTR checkers.  See Klocwork Cross Reference

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

...