~ubuntu-branches/ubuntu/vivid/postfix/vivid-proposed

« back to all changes in this revision

Viewing changes to src/util/valid_hostname.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2005-02-27 09:33:07 UTC
  • Revision ID: james.westby@ubuntu.com-20050227093307-cn789t27ibnlh6tf
Tags: upstream-2.1.5
ImportĀ upstreamĀ versionĀ 2.1.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      valid_hostname 3
 
4
/* SUMMARY
 
5
/*      network name validation
 
6
/* SYNOPSIS
 
7
/*      #include <valid_hostname.h>
 
8
/*
 
9
/*      int     valid_hostname(name, gripe)
 
10
/*      const char *name;
 
11
/*      int     gripe;
 
12
/*
 
13
/*      int     valid_hostaddr(addr, gripe)
 
14
/*      const char *addr;
 
15
/*      int     gripe;
 
16
/*
 
17
/*      int     valid_hostliteral(addr, gripe)
 
18
/*      const char *addr;
 
19
/*      int     gripe;
 
20
/* DESCRIPTION
 
21
/*      valid_hostname() scrutinizes a hostname: the name should be no
 
22
/*      longer than VALID_HOSTNAME_LEN characters, should contain only
 
23
/*      letters, digits, dots and hyphens, no adjacent dots and hyphens,
 
24
/*      no leading or trailing dots or hyphens, no labels longer than
 
25
/*      VALID_LABEL_LEN characters, and no numeric top-level domain.
 
26
/*
 
27
/*      valid_hostaddr() requires that the input is a valid string
 
28
/*      representation of an internet network address.
 
29
/*
 
30
/*      valid_hostliteral() requires an address enclosed in [].
 
31
/*
 
32
/*      These routines operate silently unless the gripe parameter
 
33
/*      specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
 
34
/*      provide suitable constants.
 
35
/* DIAGNOSTICS
 
36
/*      Both functions return zero if they disagree with the input.
 
37
/* SEE ALSO
 
38
/*      RFC 952, 1123, RFC 1035
 
39
/* LICENSE
 
40
/* .ad
 
41
/* .fi
 
42
/*      The Secure Mailer license must be distributed with this software.
 
43
/* AUTHOR(S)
 
44
/*      Wietse Venema
 
45
/*      IBM T.J. Watson Research
 
46
/*      P.O. Box 704
 
47
/*      Yorktown Heights, NY 10598, USA
 
48
/*--*/
 
49
 
 
50
/* System library. */
 
51
 
 
52
#include <sys_defs.h>
 
53
#include <string.h>
 
54
#include <ctype.h>
 
55
 
 
56
/* Utility library. */
 
57
 
 
58
#include "msg.h"
 
59
#include "mymalloc.h"
 
60
#include "stringops.h"
 
61
#include "valid_hostname.h"
 
62
 
 
63
/* valid_hostname - screen out bad hostnames */
 
64
 
 
65
int     valid_hostname(const char *name, int gripe)
 
66
{
 
67
    char   *myname = "valid_hostname";
 
68
    const char *cp;
 
69
    int     label_length = 0;
 
70
    int     label_count = 0;
 
71
    int     non_numeric = 0;
 
72
    int     ch;
 
73
 
 
74
    /*
 
75
     * Trivial cases first.
 
76
     */
 
77
    if (*name == 0) {
 
78
        if (gripe)
 
79
            msg_warn("%s: empty hostname", myname);
 
80
        return (0);
 
81
    }
 
82
 
 
83
    /*
 
84
     * Find bad characters or label lengths. Find adjacent delimiters.
 
85
     */
 
86
    for (cp = name; (ch = *(unsigned char *) cp) != 0; cp++) {
 
87
        if (ISALNUM(ch) || ch == '_') {         /* grr.. */
 
88
            if (label_length == 0)
 
89
                label_count++;
 
90
            label_length++;
 
91
            if (label_length > VALID_LABEL_LEN) {
 
92
                if (gripe)
 
93
                    msg_warn("%s: hostname label too long: %.100s", myname, name);
 
94
                return (0);
 
95
            }
 
96
            if (!ISDIGIT(ch))
 
97
                non_numeric = 1;
 
98
        } else if (ch == '.') {
 
99
            if (label_length == 0 || cp[1] == 0) {
 
100
                if (gripe)
 
101
                    msg_warn("%s: misplaced delimiter: %.100s", myname, name);
 
102
                return (0);
 
103
            }
 
104
            label_length = 0;
 
105
        } else if (ch == '-') {
 
106
            label_length++;
 
107
            if (label_length == 1 || cp[1] == 0 || cp[1] == '.') {
 
108
                if (gripe)
 
109
                    msg_warn("%s: misplaced hyphen: %.100s", myname, name);
 
110
                return (0);
 
111
            }
 
112
        } else {
 
113
            if (gripe)
 
114
                msg_warn("%s: invalid character %d(decimal): %.100s",
 
115
                         myname, ch, name);
 
116
            return (0);
 
117
        }
 
118
    }
 
119
 
 
120
    if (non_numeric == 0) {
 
121
        if (gripe)
 
122
            msg_warn("%s: numeric hostname: %.100s", myname, name);
 
123
        /* NOT: return (0); this confuses users of the DNS client */
 
124
    }
 
125
    if (cp - name > VALID_HOSTNAME_LEN) {
 
126
        if (gripe)
 
127
            msg_warn("%s: bad length %d for %.100s...",
 
128
                     myname, (int) (cp - name), name);
 
129
        return (0);
 
130
    }
 
131
    return (1);
 
132
}
 
133
 
 
134
/* valid_hostaddr - test dotted quad string for correctness */
 
135
 
 
136
int     valid_hostaddr(const char *addr, int gripe)
 
137
{
 
138
    const char *cp;
 
139
    char   *myname = "valid_hostaddr";
 
140
    int     in_byte = 0;
 
141
    int     byte_count = 0;
 
142
    int     byte_val = 0;
 
143
    int     ch;
 
144
 
 
145
#define BYTES_NEEDED    4
 
146
 
 
147
    /*
 
148
     * Trivial cases first.
 
149
     */
 
150
    if (*addr == 0) {
 
151
        if (gripe)
 
152
            msg_warn("%s: empty address", myname);
 
153
        return (0);
 
154
    }
 
155
 
 
156
    /*
 
157
     * Preliminary IPV6 support.
 
158
     */
 
159
    if (strchr(addr, ':')) {
 
160
        if (*(cp = addr + strspn(addr, ":./0123456789abcdefABCDEF")) != 0) {
 
161
            if (gripe)
 
162
                msg_warn("%s: invalid character %d(decimal): %.100s",
 
163
                         myname, *cp, addr);
 
164
            return (0);
 
165
        }
 
166
        return (1);
 
167
    }
 
168
 
 
169
    /*
 
170
     * Scary code to avoid sscanf() overflow nasties.
 
171
     */
 
172
    for (cp = addr; (ch = *(unsigned const char *) cp) != 0; cp++) {
 
173
        if (ISDIGIT(ch)) {
 
174
            if (in_byte == 0) {
 
175
                in_byte = 1;
 
176
                byte_val = 0;
 
177
                byte_count++;
 
178
            }
 
179
            byte_val *= 10;
 
180
            byte_val += ch - '0';
 
181
            if (byte_val > 255) {
 
182
                if (gripe)
 
183
                    msg_warn("%s: invalid octet value: %.100s", myname, addr);
 
184
                return (0);
 
185
            }
 
186
        } else if (ch == '.') {
 
187
            if (in_byte == 0 || cp[1] == 0) {
 
188
                if (gripe)
 
189
                    msg_warn("%s: misplaced dot: %.100s", myname, addr);
 
190
                return (0);
 
191
            }
 
192
            if ((byte_count == 1 && byte_val == 0)) {
 
193
                if (gripe)
 
194
                    msg_warn("%s: bad initial octet value: %.100s", myname, addr);
 
195
                return (0);
 
196
            }
 
197
            in_byte = 0;
 
198
        } else {
 
199
            if (gripe)
 
200
                msg_warn("%s: invalid character %d(decimal): %.100s",
 
201
                         myname, ch, addr);
 
202
            return (0);
 
203
        }
 
204
    }
 
205
 
 
206
    if (byte_count != BYTES_NEEDED) {
 
207
        if (gripe)
 
208
            msg_warn("%s: invalid octet count: %.100s", myname, addr);
 
209
        return (0);
 
210
    }
 
211
    return (1);
 
212
}
 
213
 
 
214
/* valid_hostliteral - validate address literal */
 
215
 
 
216
int     valid_hostliteral(const char *addr, int gripe)
 
217
{
 
218
    const char *myname = "valid_hostliteral";
 
219
    char    buf[100];
 
220
    const char *last;
 
221
 
 
222
    if (*addr != '[') {
 
223
        if (gripe)
 
224
            msg_warn("%s: '[' expected at start: %.100s", myname, addr);
 
225
        return (0);
 
226
    }
 
227
    if ((last = strchr(addr, ']')) == 0) {
 
228
        if (gripe)
 
229
            msg_warn("%s: ']' expected at end: %.100s", myname, addr);
 
230
        return (0);
 
231
    }
 
232
    if (last[1]) {
 
233
        if (gripe)
 
234
            msg_warn("%s: unexpected text after ']': %.100s", myname, addr);
 
235
        return (0);
 
236
    }
 
237
    if (last >= addr + sizeof(buf)) {
 
238
        if (gripe)
 
239
            msg_warn("%s: too much text: %.100s", myname, addr);
 
240
        return (0);
 
241
    }
 
242
    strncpy(buf, addr + 1, last - addr - 1);
 
243
    buf[last - addr - 1] = 0;
 
244
    return (valid_hostaddr(buf, gripe));
 
245
}
 
246
 
 
247
#ifdef TEST
 
248
 
 
249
 /*
 
250
  * Test program - reads hostnames from stdin, reports invalid hostnames to
 
251
  * stderr.
 
252
  */
 
253
#include <stdlib.h>
 
254
 
 
255
#include "vstring.h"
 
256
#include "vstream.h"
 
257
#include "vstring_vstream.h"
 
258
#include "msg_vstream.h"
 
259
 
 
260
int     main(int unused_argc, char **argv)
 
261
{
 
262
    VSTRING *buffer = vstring_alloc(1);
 
263
 
 
264
    msg_vstream_init(argv[0], VSTREAM_ERR);
 
265
    msg_verbose = 1;
 
266
 
 
267
    while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
 
268
        msg_info("testing: \"%s\"", vstring_str(buffer));
 
269
        valid_hostname(vstring_str(buffer), DO_GRIPE);
 
270
        valid_hostaddr(vstring_str(buffer), DO_GRIPE);
 
271
        valid_hostliteral(vstring_str(buffer), DO_GRIPE);
 
272
    }
 
273
    exit(0);
 
274
}
 
275
 
 
276
#endif