Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  valid_hostname.c

  Sprache: C
 

/*++
/* NAME
/* valid_hostname 3
/* SUMMARY
/* network name validation
/* SYNOPSIS
/* #include <valid_hostname.h>
/*
/* int valid_hostname(name, flags)
/* const char *name;
/* int flags;
/*
/* int valid_hostaddr(addr, gripe)
/* const char *addr;
/* int gripe;
/*
/* int valid_ipv4_hostaddr(addr, gripe)
/* const char *addr;
/* int gripe;
/*
/* int valid_ipv6_hostaddr(addr, gripe)
/* const char *addr;
/* int gripe;
/*
/* int valid_hostport(port, gripe)
/* const char *port;
/* int gripe;
/* DESCRIPTION
/* valid_hostname() scrutinizes a hostname: the name should
/* be no longer than VALID_HOSTNAME_LEN characters, should
/* contain only letters, digits, dots and hyphens, no adjacent
/* dots, no leading or trailing dots or hyphens, no labels
/* longer than VALID_LABEL_LEN characters, and it should not
/* be all numeric.
/* The flags argument is the bit-wise or of zero or more of
/* DO_GRIPE or DO_WILDCARD (the latter allows the "*." name
/* prefix, which is rare but valid in some DNS responses and
/* queries).
/*
/* valid_hostaddr() requires that the input is a valid string
/* representation of an IPv4 or IPv6 network address as
/* described next.
/*
/* valid_ipv4_hostaddr() and valid_ipv6_hostaddr() implement
/* protocol-specific address syntax checks. A valid IPv4
/* address is in dotted-quad decimal form. A valid IPv6 address
/* has 16-bit hexadecimal fields separated by ":", and does not
/* include the RFC 2821 style "IPv6:" prefix.
/*
/* These routines operate silently unless the gripe parameter
/* specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
/* provide suitable constants.
/*
/* valid_hostport() requires that the input is a valid string
/* representation of a TCP or UDP port number.
/* BUGS
/* valid_hostmumble() does not guarantee that string lengths
/* fit the buffer sizes defined in myaddrinfo(3h).
/* DIAGNOSTICS
/* All functions return zero if they disagree with the input.
/* SEE ALSO
/* RFC 952, RFC 1123, RFC 1035, RFC 2373.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/


/* System library. */

#include <sys_defs.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

/* Utility library. */

#include "msg.h"
#include "mymalloc.h"
#include "stringops.h"
#include "valid_hostname.h"

/* valid_hostname - screen out bad hostnames */

int     valid_hostname(const char *name, int flags)
{
    const char *myname = "valid_hostname";
    const char *cp;
    int     label_length = 0;
    int     label_count = 0;
    int     non_numeric = 0;
    int     ch;
    int     gripe = flags & DO_GRIPE;

    /*
     * Trivial cases first.
     */

    if (*name == 0) {
 if (gripe)
     msg_warn("%s: empty hostname", myname);
 return (0);
    }

    /*
     * Find bad characters or label lengths. Find adjacent delimiters.
     */

    for (cp = name; (ch = *(unsigned char *) cp) != 0; cp++) {
 if (ISALNUM(ch) || ch == '_') {  /* grr.. */
     if (label_length == 0)
  label_count++;
     label_length++;
     if (label_length > VALID_LABEL_LEN) {
  if (gripe)
      msg_warn("%s: hostname label too long: %.100s", myname, name);
  return (0);
     }
     if (!ISDIGIT(ch))
  non_numeric = 1;
 } else if ((flags & DO_WILDCARD) && ch == '*') {
     if (label_length || label_count || (cp[1] && cp[1] != '.')) {
  if (gripe)
      msg_warn("%s: '*' can be the first label only: %.100s", myname, name);
  return (0);
     }
     label_count++;
     label_length++;
     non_numeric = 1;
 } else if (ch == '.') {
     if (label_length == 0 || cp[1] == 0) {
  if (gripe)
      msg_warn("%s: misplaced delimiter: %.100s", myname, name);
  return (0);
     }
     label_length = 0;
 } else if (ch == '-') {
     non_numeric = 1;
     label_length++;
     if (label_length == 1 || cp[1] == 0 || cp[1] == '.') {
  if (gripe)
      msg_warn("%s: misplaced hyphen: %.100s", myname, name);
  return (0);
     }
 }
#ifdef SLOPPY_VALID_HOSTNAME
 else if (ch == ':' && valid_ipv6_hostaddr(name, DONT_GRIPE)) {
     non_numeric = 0;
     break;
 }
#endif
 else {
     if (gripe)
  msg_warn("%s: invalid character %d(decimal): %.100s",
    myname, ch, name);
     return (0);
 }
    }

    if (non_numeric == 0) {
 if (gripe)
     msg_warn("%s: numeric hostname: %.100s", myname, name);
#ifndef SLOPPY_VALID_HOSTNAME
 return (0);
#endif
    }
    if (cp - name > VALID_HOSTNAME_LEN) {
 if (gripe)
     msg_warn("%s: bad length %d for %.100s...",
       myname, (int) (cp - name), name);
 return (0);
    }
    return (1);
}

/* valid_hostaddr - verify numerical address syntax */

int     valid_hostaddr(const char *addr, int gripe)
{
    const char *myname = "valid_hostaddr";

    /*
     * Trivial cases first.
     */

    if (*addr == 0) {
 if (gripe)
     msg_warn("%s: empty address", myname);
 return (0);
    }

    /*
     * Protocol-dependent processing next.
     */

    if (strchr(addr, ':') != 0)
 return (valid_ipv6_hostaddr(addr, gripe));
    else
 return (valid_ipv4_hostaddr(addr, gripe));
}

/* valid_ipv4_hostaddr - test dotted quad string for correctness */

int     valid_ipv4_hostaddr(const char *addr, int gripe)
{
    const char *cp;
    const char *myname = "valid_ipv4_hostaddr";
    int     in_byte = 0;
    int     byte_count = 0;
    int     byte_val = 0;
    int     ch;

#define BYTES_NEEDED 4

    /*
     * Scary code to avoid sscanf() overflow nasties.
     * 
     * This routine is called by valid_ipv6_hostaddr(). It must not call that
     * routine, to avoid deadly recursion.
     */

    for (cp = addr; (ch = *(unsigned const char *) cp) != 0; cp++) {
 if (ISDIGIT(ch)) {
     if (in_byte == 0) {
  in_byte = 1;
  byte_val = 0;
  byte_count++;
     }
     byte_val *= 10;
     byte_val += ch - '0';
     if (byte_val > 255) {
  if (gripe)
      msg_warn("%s: invalid octet value: %.100s", myname, addr);
  return (0);
     }
 } else if (ch == '.') {
     if (in_byte == 0 || cp[1] == 0) {
  if (gripe)
      msg_warn("%s: misplaced dot: %.100s", myname, addr);
  return (0);
     }
     /* XXX Allow 0.0.0.0 but not 0.1.2.3 */
     if (byte_count == 1 && byte_val == 0 && addr[strspn(addr, "0.")]) {
  if (gripe)
      msg_warn("%s: bad initial octet value: %.100s", myname, addr);
  return (0);
     }
     in_byte = 0;
 } else {
     if (gripe)
  msg_warn("%s: invalid character %d(decimal): %.100s",
    myname, ch, addr);
     return (0);
 }
    }

    if (byte_count != BYTES_NEEDED) {
 if (gripe)
     msg_warn("%s: invalid octet count: %.100s", myname, addr);
 return (0);
    }
    return (1);
}

/* valid_ipv6_hostaddr - validate IPv6 address syntax */

int     valid_ipv6_hostaddr(const char *addr, int gripe)
{
    const char *myname = "valid_ipv6_hostaddr";
    int     null_field = 0;
    int     field = 0;
    unsigned char *cp = (unsigned char *) addr;
    int     len = 0;

    /*
     * FIX 200501 The IPv6 patch validated syntax with getaddrinfo(), but I
     * am not confident that everyone's system library routines are robust
     * enough, like buffer overflow free. Remember, the valid_hostmumble()
     * routines are meant to protect Postfix against malformed information in
     * data received from the network.
     * 
     * We require eight-field hex addresses of the form 0:1:2:3:4:5:6:7,
     * 0:1:2:3:4:5:6a.6b.7c.7d, or some :: compressed version of the same.
     * 
     * Note: the character position is advanced inside the loop. I have added
     * comments to show why we can't get stuck.
     */

    for (;;) {
 switch (*cp) {
 case 0:
     /* Terminate the loop. */
     if (field < 2) {
  if (gripe)
      msg_warn("%s: too few `:' in IPv6 address: %.100s",
        myname, addr);
  return (0);
     } else if (len == 0 && null_field != field - 1) {
  if (gripe)
      msg_warn("%s: bad null last field in IPv6 address: %.100s",
        myname, addr);
  return (0);
     } else
  return (1);
 case '.':
     /* Terminate the loop. */
     if (field < 2 || field > 6) {
  if (gripe)
      msg_warn("%s: malformed IPv4-in-IPv6 address: %.100s",
        myname, addr);
  return (0);
     } else
  /* NOT: valid_hostaddr(). Avoid recursion. */
  return (valid_ipv4_hostaddr((char *) cp - len, gripe));
 case ':':
     /* Advance by exactly 1 character position or terminate. */
     if (field == 0 && len == 0 && ISALNUM(cp[1])) {
  if (gripe)
      msg_warn("%s: bad null first field in IPv6 address: %.100s",
        myname, addr);
  return (0);
     }
     field++;
     if (field > 7) {
  if (gripe)
      msg_warn("%s: too many `:' in IPv6 address: %.100s",
        myname, addr);
  return (0);
     }
     cp++;
     len = 0;
     if (*cp == ':') {
  if (null_field > 0) {
      if (gripe)
   msg_warn("%s: too many `::' in IPv6 address: %.100s",
     myname, addr);
      return (0);
  }
  null_field = field;
     }
     break;
 default:
     /* Advance by at least 1 character position or terminate. */
     len = strspn((char *) cp, "0123456789abcdefABCDEF");
     if (len /* - strspn((char *) cp, "0") */ > 4) {
  if (gripe)
      msg_warn("%s: malformed IPv6 address: %.100s",
        myname, addr);
  return (0);
     }
     if (len <= 0) {
  if (gripe)
      msg_warn("%s: invalid character %d(decimal) in IPv6 address: %.100s",
        myname, *cp, addr);
  return (0);
     }
     cp += len;
     break;
 }
    }
}

/* valid_hostport - validate numeric port */

int     valid_hostport(const char *str, int gripe)
{
    const char *myname = "valid_hostport";
    int     port;

    if (str[0] == '0' && str[1] != 0) {
 if (gripe)
     msg_warn("%s: leading zero in port number: %.100s", myname, str);
 return (0);
    }
    if (alldig(str) == 0) {
 if (gripe)
     msg_warn("%s: non-numeric port number: %.100s", myname, str);
 return (0);
    }
    if (strlen(str) > strlen("65535")
 || (port = atoi(str)) > 65535 || port < 0) {
 if (gripe)
     msg_warn("%s: out-of-range port number: %.100s", myname, str);
 return (0);
    }
    return (1);
}

#ifdef TEST

 /*
  * Test program - reads hostnames from stdin, reports invalid hostnames to
  * stderr.
  */

#include <stdlib.h>

#include "vstring.h"
#include "vstream.h"
#include "vstring_vstream.h"
#include "msg_vstream.h"

int     main(int unused_argc, char **argv)
{
    VSTRING *buffer = vstring_alloc(1);

    msg_vstream_init(argv[0], VSTREAM_ERR);
    msg_verbose = 1;

    while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
 msg_info("testing: \"%s\"", vstring_str(buffer));
 valid_hostname(vstring_str(buffer), DO_GRIPE | DO_WILDCARD);
 if (strchr(vstring_str(buffer), '*') == 0)
     valid_hostaddr(vstring_str(buffer), DO_GRIPE);
    }
    exit(0);
}

#endif

Messung V0.5 in Prozent
C=72 H=94 G=83

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142