~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to libntp/ntp_rfc2553.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-01-05 21:10:03 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090105211003-mh6zc3um4k1uhsj7
Tags: 1:4.2.4p4+dfsg-8
It did not properly check the return value of EVP_VerifyFinal
which results in an malformed DSA signature being treated as
a good signature rather than as an error.  (CVE-2009-0021)

Show diffs side-by-side

added added

removed removed

Lines of Context:
65
65
 * Compatability shims with the rfc2553 API to simplify ntp.
66
66
 */
67
67
 
68
 
#ifdef HAVE_CONFIG_H
69
68
#include <config.h>
70
 
#endif
71
69
 
72
70
#include <sys/types.h>
73
71
#include <ctype.h>
74
72
#include <sys/socket.h>
75
 
#include "ntp_rfc2553.h"
 
73
#include <isc/net.h>
76
74
#ifdef HAVE_NETINET_IN_H
77
75
#include <netinet/in.h>
78
76
#endif
79
 
#include <netdb.h>
 
77
#include "ntp_rfc2553.h"
80
78
 
81
79
#include "ntpd.h"
82
80
#include "ntp_malloc.h"
85
83
 
86
84
#ifndef ISC_PLATFORM_HAVEIPV6
87
85
 
88
 
#if defined(SYS_WINNT)
89
 
/* XXX This is the preferred way, but for some reason the SunOS compiler
90
 
 * does not like it.
91
 
 */
92
 
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
93
 
#else
94
 
const struct in6_addr in6addr_any;
95
 
#endif
96
 
 
97
86
static char *ai_errlist[] = {
98
87
        "Success",
99
88
        "Address family for hostname not supported",    /* EAI_ADDRFAMILY */
112
101
        "Unknown error",                                /* EAI_MAX        */
113
102
};
114
103
 
115
 
static  int ipv4_aton P((const char *, struct sockaddr_storage *));
 
104
/*
 
105
 * Local declaration
 
106
 */
 
107
int
 
108
DNSlookup_name(
 
109
        const char *name,
 
110
        int ai_family,
 
111
        struct hostent **Addresses
 
112
);
 
113
 
 
114
#ifndef SYS_WINNT
 
115
/*
 
116
 * Encapsulate gethostbyname to control the error code
 
117
 */
 
118
int
 
119
DNSlookup_name(
 
120
        const char *name,
 
121
        int ai_family,
 
122
        struct hostent **Addresses
 
123
)
 
124
{
 
125
        *Addresses = gethostbyname(name);
 
126
        return (h_errno);
 
127
}
 
128
#endif
 
129
 
116
130
static  int do_nodename P((const char *nodename, struct addrinfo *ai,
117
131
    const struct addrinfo *hints));
118
132
 
121
135
        const struct addrinfo *hints, struct addrinfo **res)
122
136
{
123
137
        int rval;
124
 
        struct addrinfo *ai;
125
 
        struct sockaddr_in *sockin;
126
 
 
 
138
        struct servent *sp;
 
139
        struct addrinfo *ai = NULL;
 
140
        int port;
 
141
        const char *proto = NULL;
 
142
        int family, socktype, flags, protocol;
 
143
 
 
144
 
 
145
        /*
 
146
         * If no name is provide just return an error
 
147
         */
 
148
        if (nodename == NULL && servname == NULL)
 
149
                return (EAI_NONAME);
 
150
        
127
151
        ai = calloc(sizeof(struct addrinfo), 1);
128
152
        if (ai == NULL)
129
153
                return (EAI_MEMORY);
130
154
 
131
 
        if (nodename != NULL) {
132
 
                rval = do_nodename(nodename, ai, hints);
133
 
                if (rval != 0) {
134
 
                        freeaddrinfo(ai);
135
 
                        return (rval);
136
 
                }
137
 
        }
138
 
        if (nodename == NULL && hints != NULL) {
139
 
                ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
140
 
                if (ai->ai_addr == NULL) {
141
 
                        freeaddrinfo(ai);
142
 
                        return (EAI_MEMORY);
143
 
                }
144
 
                ai->ai_family = AF_INET;
145
 
                ai->ai_addrlen = sizeof(struct sockaddr_storage);
146
 
                sockin = (struct sockaddr_in *)ai->ai_addr;
147
 
                sockin->sin_family = AF_INET;
148
 
                sockin->sin_addr.s_addr = htonl(INADDR_ANY);
149
 
#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
150
 
                ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
 
155
        /*
 
156
         * Copy default values from hints, if available
 
157
         */
 
158
        if (hints != NULL) {
 
159
                ai->ai_flags = hints->ai_flags;
 
160
                ai->ai_family = hints->ai_family;
 
161
                ai->ai_socktype = hints->ai_socktype;
 
162
                ai->ai_protocol = hints->ai_protocol;
 
163
 
 
164
                family = hints->ai_family;
 
165
                socktype = hints->ai_socktype;
 
166
                protocol = hints->ai_protocol;
 
167
                flags = hints->ai_flags;
 
168
 
 
169
                switch (family) {
 
170
                case AF_UNSPEC:
 
171
                        switch (hints->ai_socktype) {
 
172
                        case SOCK_STREAM:
 
173
                                proto = "tcp";
 
174
                                break;
 
175
                        case SOCK_DGRAM:
 
176
                                proto = "udp";
 
177
                                break;
 
178
                        }
 
179
                        break;
 
180
                case AF_INET:
 
181
                case AF_INET6:
 
182
                        switch (hints->ai_socktype) {
 
183
                        case 0:
 
184
                                break;
 
185
                        case SOCK_STREAM:
 
186
                                proto = "tcp";
 
187
                                break;
 
188
                        case SOCK_DGRAM:
 
189
                                proto = "udp";
 
190
                                break;
 
191
                        case SOCK_RAW:
 
192
                                break;
 
193
                        default:
 
194
                                return (EAI_SOCKTYPE);
 
195
                        }
 
196
                        break;
 
197
#ifdef  AF_LOCAL
 
198
                case AF_LOCAL:
 
199
                        switch (hints->ai_socktype) {
 
200
                        case 0:
 
201
                                break;
 
202
                        case SOCK_STREAM:
 
203
                                break;
 
204
                        case SOCK_DGRAM:
 
205
                                break;
 
206
                        default:
 
207
                                return (EAI_SOCKTYPE);
 
208
                        }
 
209
                        break;
151
210
#endif
152
 
        }
 
211
                default:
 
212
                        return (EAI_FAMILY);
 
213
                }
 
214
        } else {
 
215
                protocol = 0;
 
216
                family = 0;
 
217
                socktype = 0;
 
218
                flags = 0;
 
219
        }
 
220
 
 
221
        rval = do_nodename(nodename, ai, hints);
 
222
        if (rval != 0) {
 
223
                freeaddrinfo(ai);
 
224
                return (rval);
 
225
        }
 
226
 
 
227
        /*
 
228
         * First, look up the service name (port) if it was
 
229
         * requested.  If the socket type wasn't specified, then
 
230
         * try and figure it out.
 
231
         */
153
232
        if (servname != NULL) {
154
 
                ai->ai_family = AF_INET;
155
 
                ai->ai_socktype = SOCK_DGRAM;
156
 
                if (strcmp(servname, "ntp") != 0) {
157
 
                        freeaddrinfo(ai);
158
 
                        return (EAI_SERVICE);
 
233
                char *e;
 
234
 
 
235
                port = strtol(servname, &e, 10);
 
236
                if (*e == '\0') {
 
237
                        if (socktype == 0)
 
238
                                return (EAI_SOCKTYPE);
 
239
                        if (port < 0 || port > 65535)
 
240
                                return (EAI_SERVICE);
 
241
                        port = htons((unsigned short) port);
 
242
                } else {
 
243
                        sp = getservbyname(servname, proto);
 
244
                        if (sp == NULL)
 
245
                                return (EAI_SERVICE);
 
246
                        port = sp->s_port;
 
247
                        if (socktype == 0) {
 
248
                                if (strcmp(sp->s_proto, "tcp") == 0)
 
249
                                        socktype = SOCK_STREAM;
 
250
                                else if (strcmp(sp->s_proto, "udp") == 0)
 
251
                                        socktype = SOCK_DGRAM;
 
252
                        }
159
253
                }
160
 
                sockin = (struct sockaddr_in *)ai->ai_addr;
161
 
                sockin->sin_port = htons(NTP_PORT);
162
 
        }
 
254
        } else
 
255
                port = 0;
 
256
 
 
257
        /*
 
258
         *
 
259
         * Set up the port number
 
260
         */
 
261
        if (ai->ai_family == AF_INET)
 
262
                ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
 
263
        else if (ai->ai_family == AF_INET6)
 
264
                ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
163
265
        *res = ai;
164
266
        return (0);
165
267
}
168
270
freeaddrinfo(struct addrinfo *ai)
169
271
{
170
272
        if (ai->ai_canonname != NULL)
 
273
        {
171
274
                free(ai->ai_canonname);
 
275
                ai->ai_canonname = NULL;
 
276
        }
172
277
        if (ai->ai_addr != NULL)
 
278
        {
173
279
                free(ai->ai_addr);
 
280
                ai->ai_addr = NULL;
 
281
        }
174
282
        free(ai);
 
283
        ai = NULL;
175
284
}
176
285
 
177
286
int
179
288
        size_t hostlen, char *serv, size_t servlen, int flags)
180
289
{
181
290
        struct hostent *hp;
 
291
        int namelen;
182
292
 
183
293
        if (sa->sa_family != AF_INET)
184
294
                return (EAI_FAMILY);
191
301
                else
192
302
                        return (EAI_FAIL);
193
303
        }
194
 
        if (host != NULL) {
195
 
                strncpy(host, hp->h_name, hostlen);
196
 
                host[hostlen] = '\0';
 
304
        if (host != NULL && hostlen > 0) {
 
305
                /*
 
306
                 * Don't exceed buffer
 
307
                 */
 
308
                namelen = min(strlen(hp->h_name), hostlen - 1);
 
309
                if (namelen > 0) {
 
310
                        strncpy(host, hp->h_name, namelen);
 
311
                        host[namelen] = '\0';
 
312
                }
197
313
        }
198
314
        return (0);
199
315
}
212
328
        struct addrinfo *ai,
213
329
        const struct addrinfo *hints)
214
330
{
215
 
        struct hostent *hp;
 
331
        struct hostent *hp = NULL;
216
332
        struct sockaddr_in *sockin;
 
333
        struct sockaddr_in6 *sockin6;
 
334
        int errval;
217
335
 
218
336
        ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
219
337
        if (ai->ai_addr == NULL)
220
338
                return (EAI_MEMORY);
221
339
 
222
 
        if (hints != NULL && hints->ai_flags & AI_NUMERICHOST) {
223
 
                if (ipv4_aton(nodename,
224
 
                    (struct sockaddr_storage *)ai->ai_addr) == 1) {
225
 
                        ai->ai_family = AF_INET;
226
 
                        ai->ai_addrlen = sizeof(struct sockaddr_in);
 
340
        /*
 
341
         * For an empty node name just use the wildcard.
 
342
         * NOTE: We need to assume that the address family is
 
343
         * set elsewhere so that we can set the appropriate wildcard
 
344
         */
 
345
        if (nodename == NULL) {
 
346
                ai->ai_addrlen = sizeof(struct sockaddr_storage);
 
347
                if (ai->ai_family == AF_INET)
 
348
                {
 
349
                        sockin = (struct sockaddr_in *)ai->ai_addr;
 
350
                        sockin->sin_family = (short) ai->ai_family;
 
351
                        sockin->sin_addr.s_addr = htonl(INADDR_ANY);
 
352
                }
 
353
                else
 
354
                {
 
355
                        sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
 
356
                        sockin6->sin6_family = (short) ai->ai_family;
 
357
                        /*
 
358
                         * we have already zeroed out the address
 
359
                         * so we don't actually need to do this
 
360
                         * This assignment is causing problems so
 
361
                         * we don't do what this would do.
 
362
                         sockin6->sin6_addr = in6addr_any;
 
363
                         */
 
364
                }
 
365
#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 
366
                ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
 
367
#endif
 
368
 
 
369
                return (0);
 
370
        }
 
371
 
 
372
        /*
 
373
         * See if we have an IPv6 address
 
374
         */
 
375
        if(strchr(nodename, ':') != NULL) {
 
376
                if (inet_pton(AF_INET6, nodename,
 
377
                    &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
 
378
                        ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
 
379
                        ai->ai_family = AF_INET6;
 
380
                        ai->ai_addrlen = sizeof(struct sockaddr_in6);
227
381
                        return (0);
228
382
                }
 
383
        }
 
384
 
 
385
        /*
 
386
         * See if we have an IPv4 address
 
387
         */
 
388
        if (inet_pton(AF_INET, nodename,
 
389
            &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
 
390
                ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
 
391
                ai->ai_family = AF_INET;
 
392
                ai->ai_addrlen = sizeof(struct sockaddr_in);
 
393
                return (0);
 
394
        }
 
395
 
 
396
        /*
 
397
         * If the numeric host flag is set, don't attempt resolution
 
398
         */
 
399
        if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
229
400
                return (EAI_NONAME);
230
 
        }
231
 
        hp = gethostbyname(nodename);
 
401
 
 
402
        /*
 
403
         * Look for a name
 
404
         */
 
405
 
 
406
        errval = DNSlookup_name(nodename, AF_INET, &hp);
 
407
 
232
408
        if (hp == NULL) {
233
 
                if (h_errno == TRY_AGAIN)
 
409
                if (errval == TRY_AGAIN || errval == EAI_AGAIN)
234
410
                        return (EAI_AGAIN);
235
 
                else {
236
 
                        if (ipv4_aton(nodename,
237
 
                            (struct sockaddr_storage *)ai->ai_addr) == 1) {
 
411
                else if (errval == EAI_NONAME) {
 
412
                        if (inet_pton(AF_INET, nodename,
 
413
                            &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
 
414
                                ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
238
415
                                ai->ai_family = AF_INET;
239
416
                                ai->ai_addrlen = sizeof(struct sockaddr_in);
240
417
                                return (0);
241
418
                        }
242
 
                        return (EAI_FAIL);
 
419
                        return (errval);
 
420
                }
 
421
                else
 
422
                {
 
423
                        return (errval);
243
424
                }
244
425
        }
245
426
        ai->ai_family = hp->h_addrtype;
259
440
        return (0);
260
441
}
261
442
 
262
 
/*
263
 
 * ipv4_aton - return a net number (this is crude, but careful)
264
 
 */
265
 
static int
266
 
ipv4_aton(
267
 
        const char *num,
268
 
        struct sockaddr_storage *saddr
269
 
        )
270
 
{
271
 
        const char *cp;
272
 
        char *bp;
273
 
        int i;
274
 
        int temp;
275
 
        char buf[80];           /* will core dump on really stupid stuff */
276
 
        u_int32 netnum;
277
 
        struct sockaddr_in *addr;
278
 
 
279
 
        cp = num;
280
 
        netnum = 0;
281
 
        for (i = 0; i < 4; i++) {
282
 
                bp = buf;
283
 
                while (isdigit((int)*cp))
284
 
                        *bp++ = *cp++;
285
 
                if (bp == buf)
286
 
                        break;
287
 
 
288
 
                if (i < 3) {
289
 
                        if (*cp++ != '.')
290
 
                                break;
291
 
                } else if (*cp != '\0')
292
 
                        break;
293
 
 
294
 
                *bp = '\0';
295
 
                temp = atoi(buf);
296
 
                if (temp > 255)
297
 
                        break;
298
 
                netnum <<= 8;
299
 
                netnum += temp;
300
 
#ifdef DEBUG
301
 
                if (debug > 3)
302
 
                        printf("ipv4_aton %s step %d buf %s temp %d netnum %lu\n",
303
 
                           num, i, buf, temp, (u_long)netnum);
304
 
#endif
305
 
        }
306
 
 
307
 
        if (i < 4) {
308
 
#ifdef DEBUG
309
 
                if (debug > 3)
310
 
                        printf(
311
 
                                "ipv4_aton: \"%s\" invalid host number, line ignored\n",
312
 
                                num);
313
 
#endif
314
 
                return (0);
315
 
        }
316
 
 
317
 
        /*
318
 
         * make up socket address.      Clear it out for neatness.
319
 
         */
320
 
        memset((void *)saddr, 0, sizeof(struct sockaddr_storage));
321
 
        addr = (struct sockaddr_in *)saddr;
322
 
        addr->sin_family = AF_INET;
323
 
        addr->sin_port = htons(NTP_PORT);
324
 
        addr->sin_addr.s_addr = htonl(netnum);
325
 
#ifdef DEBUG
326
 
        if (debug > 1)
327
 
                printf("ipv4_aton given %s, got %s.\n", num, ntoa(saddr));
328
 
#endif
329
 
        return (1);
330
 
}
331
443
#endif /* !ISC_PLATFORM_HAVEIPV6 */