~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr-util/crypto/getuuid.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/*
 
18
 * This attempts to generate V1 UUIDs according to the Internet Draft
 
19
 * located at http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt
 
20
 */
 
21
#include "apr.h"
 
22
#include "apr_uuid.h"
 
23
#include "apr_md5.h"
 
24
#include "apr_general.h"
 
25
#include "apr_portable.h"
 
26
 
 
27
 
 
28
#if APR_HAVE_UNISTD_H
 
29
#include <unistd.h>     /* for getpid, gethostname */
 
30
#endif
 
31
#if APR_HAVE_STDLIB_H
 
32
#include <stdlib.h>     /* for rand, srand */
 
33
#endif
 
34
 
 
35
 
 
36
#if APR_HAVE_STRING_H
 
37
#include <string.h>
 
38
#endif
 
39
#if APR_HAVE_STRINGS_H
 
40
#include <strings.h>
 
41
#endif
 
42
#if APR_HAVE_NETDB_H
 
43
#include <netdb.h>
 
44
#endif
 
45
#if APR_HAVE_SYS_TIME_H
 
46
#include <sys/time.h>   /* for gettimeofday */
 
47
#endif
 
48
 
 
49
#define NODE_LENGTH 6
 
50
 
 
51
static int uuid_state_seqnum;
 
52
static unsigned char uuid_state_node[NODE_LENGTH] = { 0 };
 
53
 
 
54
 
 
55
static void get_random_info(unsigned char node[NODE_LENGTH])
 
56
{
 
57
#if APR_HAS_RANDOM
 
58
 
 
59
    (void) apr_generate_random_bytes(node, NODE_LENGTH);
 
60
 
 
61
#else
 
62
 
 
63
    unsigned char seed[APR_MD5_DIGESTSIZE];
 
64
    apr_md5_ctx_t c;
 
65
 
 
66
    /* ### probably should revise some of this to be a bit more portable */
 
67
 
 
68
    /* Leach & Salz use Linux-specific struct sysinfo;
 
69
     * replace with pid/tid for portability (in the spirit of mod_unique_id) */
 
70
    struct {
 
71
        /* Add thread id here, if applicable, when we get to pthread or apr */
 
72
        pid_t pid;
 
73
#ifdef NETWARE
 
74
        apr_uint64_t t;
 
75
#else
 
76
        struct timeval t;
 
77
#endif
 
78
        char hostname[257];
 
79
 
 
80
    } r;
 
81
 
 
82
    apr_md5_init(&c);
 
83
#ifdef NETWARE
 
84
    r.pid = NXThreadGetId();
 
85
    NXGetTime(NX_SINCE_BOOT, NX_USECONDS, &(r.t));
 
86
#else
 
87
    r.pid = getpid();
 
88
    gettimeofday(&r.t, (struct timezone *)0);
 
89
#endif
 
90
    gethostname(r.hostname, 256);
 
91
    apr_md5_update(&c, (const unsigned char *)&r, sizeof(r));
 
92
    apr_md5_final(seed, &c);
 
93
 
 
94
    memcpy(node, seed, NODE_LENGTH);    /* use a subset of the seed bytes */
 
95
#endif
 
96
}
 
97
 
 
98
/* This implementation generates a random node ID instead of a
 
99
   system-dependent call to get IEEE node ID. This is also more secure:
 
100
   we aren't passing out our MAC address.
 
101
*/
 
102
static void get_pseudo_node_identifier(unsigned char *node)
 
103
{
 
104
    get_random_info(node);
 
105
    node[0] |= 0x01;                    /* this designates a random node ID */
 
106
}
 
107
 
 
108
static void get_system_time(apr_uint64_t *uuid_time)
 
109
{
 
110
    /* ### fix this call to be more portable? */
 
111
    *uuid_time = apr_time_now();
 
112
 
 
113
    /* Offset between UUID formatted times and Unix formatted times.
 
114
       UUID UTC base time is October 15, 1582.
 
115
       Unix base time is January 1, 1970.      */
 
116
    *uuid_time = (*uuid_time * 10) + APR_TIME_C(0x01B21DD213814000);
 
117
}
 
118
 
 
119
/* true_random -- generate a crypto-quality random number. */
 
120
static int true_random(void)
 
121
{
 
122
    apr_uint64_t time_now;
 
123
 
 
124
#if APR_HAS_RANDOM
 
125
    unsigned char buf[2];
 
126
 
 
127
    if (apr_generate_random_bytes(buf, 2) == APR_SUCCESS) {
 
128
        return (buf[0] << 8) | buf[1];
 
129
    }
 
130
#endif
 
131
 
 
132
    /* crap. this isn't crypto quality, but it will be Good Enough */
 
133
 
 
134
    get_system_time(&time_now);
 
135
    srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff));
 
136
 
 
137
    return rand() & 0x0FFFF;
 
138
}
 
139
 
 
140
static void init_state(void)
 
141
{
 
142
    uuid_state_seqnum = true_random();
 
143
    get_pseudo_node_identifier(uuid_state_node);
 
144
}
 
145
 
 
146
static void get_current_time(apr_uint64_t *timestamp)
 
147
{
 
148
    /* ### this needs to be made thread-safe! */
 
149
 
 
150
    apr_time_t time_now;
 
151
    static apr_interval_time_t time_last = 0;
 
152
    static apr_interval_time_t fudge = 0;
 
153
 
 
154
    time_now = apr_time_now();
 
155
        
 
156
    /* if clock reading changed since last UUID generated... */
 
157
    if (time_last != time_now) {
 
158
        /* The clock reading has changed since the last UUID was generated.
 
159
           Reset the fudge factor. if we are generating them too fast, then
 
160
           the fudge may need to be reset to something greater than zero. */
 
161
        if (time_last + fudge > time_now)
 
162
            fudge = time_last + fudge - time_now + 1;
 
163
        else
 
164
            fudge = 0;
 
165
        time_last = time_now;
 
166
    }
 
167
    else {
 
168
        /* We generated two really fast. Bump the fudge factor. */
 
169
        ++fudge;
 
170
    }
 
171
 
 
172
    *timestamp = time_now + fudge;
 
173
}
 
174
 
 
175
APU_DECLARE(void) apr_uuid_get(apr_uuid_t *uuid)
 
176
{
 
177
    apr_uint64_t timestamp;
 
178
    unsigned char *d = uuid->data;
 
179
 
 
180
#if APR_HAS_OS_UUID
 
181
    if (apr_os_uuid_get(d) == APR_SUCCESS) {
 
182
        return;
 
183
    }
 
184
#endif /* !APR_HAS_OS_UUID */
 
185
 
 
186
    if (!uuid_state_node[0])
 
187
        init_state();
 
188
 
 
189
    get_current_time(&timestamp);
 
190
 
 
191
    d[0] = (unsigned char)timestamp;
 
192
    d[1] = (unsigned char)(timestamp >> 8);
 
193
    d[2] = (unsigned char)(timestamp >> 16);
 
194
    d[3] = (unsigned char)(timestamp >> 24);
 
195
    d[4] = (unsigned char)(timestamp >> 32);
 
196
    d[5] = (unsigned char)(timestamp >> 40);
 
197
    d[6] = (unsigned char)(timestamp >> 48);
 
198
    d[7] = (unsigned char)(((timestamp >> 56) & 0x0F) | 0x10);
 
199
 
 
200
    d[8] = (unsigned char)(((uuid_state_seqnum >> 8) & 0x3F) | 0x80);
 
201
    d[9] = (unsigned char)uuid_state_seqnum;
 
202
 
 
203
    memcpy(&d[10], uuid_state_node, NODE_LENGTH);
 
204
}