~ubuntu-branches/ubuntu/dapper/freeradius/dapper-updates

« back to all changes in this revision

Viewing changes to src/modules/rlm_x99_token/x99_util.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Hampson
  • Date: 2006-01-15 13:34:13 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060115133413-92geefww41y7hqi8
Tags: 1.1.0-1
* ReDebianise upstream tarball:
  - Deleted RFCs: 2243 2289 2433 2548 2618 2619 2620 2621 2716 2759 2809 2865
                  2866 2867 2868 2869 2882 2924 3162 3575 3576 3579 3580
                  draft-kamath-pppext-eap-mschapv2-00

* New FreeRADIUS modules marked stable by new upstream release
  - rlm_perl
  - rlm_sqlcounter
  - rlm_sql_log + radsqlrelay
  - rlm_otp (formerly rlm_x99_token, not built as it depends on OpenSSL)

* Remove upstream-integrated patches:
  - 02_EAP-SIM_doesnt_need_openssl
  - 03_X99_is_not_stable
  - 07_manpage_fixups
  - 09_use_crypth_if_we_have_it
  - 10_escape_entire_ldap_string
  - 11_dont_xlat_possibly_bad_usernames_in_bad_accounting_packets
  - 12_dialup_admin_various_fixes

* More dialup-admin fixes from Arve Seljebu
  - Fix redirects in dialup-admin pages on servers with
    register_globals turned off.
    Closes: #333704
  - HTTP form fields will always fail is_int, use in_numeric instead
    Closes: #335149
  - Created 12_more_dialup_admin_various_fixes

* Update to Policy 3.6.2.0
* Upgrade Debhelper support to V5
* Don't install the .in files with the examples
* Prefer libmysqlclient15-dev
  Closes: #343779
* Shared secrets can only be 31 characters long, note this in clients.conf
  - Created 02_document_actual_shared_secret_maximum_length
  Closes: 344606
* Added support for lsb-init functions

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * x99_util.c
3
 
 * $Id: x99_util.c,v 1.12 2004/02/26 19:04:37 aland Exp $
4
 
 *
5
 
 *   This program is free software; you can redistribute it and/or modify
6
 
 *   it under the terms of the GNU General Public License as published by
7
 
 *   the Free Software Foundation; either version 2 of the License, or
8
 
 *   (at your option) any later version.
9
 
 *
10
 
 *   This program is distributed in the hope that it will be useful,
11
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *   GNU General Public License for more details.
14
 
 *
15
 
 *   You should have received a copy of the GNU General Public License
16
 
 *   along with this program; if not, write to the Free Software
17
 
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
 *
19
 
 * Copyright 2001,2002  Google, Inc.
20
 
 */
21
 
 
22
 
#ifdef FREERADIUS
23
 
#include "radiusd.h"
24
 
#endif
25
 
#include "x99.h"
26
 
 
27
 
#include <errno.h>
28
 
#include <stdlib.h>
29
 
#include <stdio.h>
30
 
#include <string.h>
31
 
#include <sys/types.h>
32
 
#include <sys/stat.h>
33
 
#include <fcntl.h>
34
 
#include <unistd.h>
35
 
#include <openssl/des.h> /* des_cblock */
36
 
 
37
 
 
38
 
static const char rcsid[] = "$Id: x99_util.c,v 1.12 2004/02/26 19:04:37 aland Exp $";
39
 
 
40
 
 
41
 
/* Card name to int mappings */
42
 
static struct {
43
 
    const char *name;
44
 
    uint32_t id;
45
 
} card[] = {
46
 
    { "x9.9",             CRYPTOCARD_H8_RC },
47
 
    { "generic",          CRYPTOCARD_H8_RC },
48
 
 
49
 
    { "cryptocard-h8-rc", CRYPTOCARD_H8_RC },
50
 
    { "cryptocard-d8-rc", CRYPTOCARD_D8_RC },
51
 
    { "cryptocard-h7-rc", CRYPTOCARD_H7_RC },
52
 
    { "cryptocard-d7-rc", CRYPTOCARD_D7_RC },
53
 
    { "cryptocard-h8-es", CRYPTOCARD_H8_ES },
54
 
    { "cryptocard-d8-es", CRYPTOCARD_D8_ES },
55
 
    { "cryptocard-h7-es", CRYPTOCARD_H7_ES },
56
 
    { "cryptocard-d7-es", CRYPTOCARD_D7_ES },
57
 
    { "cryptocard-h8-rs", CRYPTOCARD_H8_RS },
58
 
    { "cryptocard-d8-rs", CRYPTOCARD_D8_RS },
59
 
    { "cryptocard-h7-rs", CRYPTOCARD_H7_RS },
60
 
    { "cryptocard-d7-rs", CRYPTOCARD_D7_RS },
61
 
 
62
 
    { NULL, 0 }                         /* end of list */
63
 
};
64
 
 
65
 
 
66
 
/*
67
 
 * Return a random challenge.
68
 
 * fd must be either -1 or an open fd to the random device.
69
 
 * challenge is filled in on successful return (must be size len+1).
70
 
 * Returns 0 on success, -1 on failure.
71
 
 */
72
 
int
73
 
x99_get_challenge(int fd, char *challenge, int len)
74
 
{
75
 
    unsigned char rawchallenge[MAX_CHALLENGE_LEN];
76
 
    int i;
77
 
 
78
 
    if (fd == -1) {
79
 
        if ((fd = open(DEVURANDOM, O_RDONLY)) == -1) {
80
 
            x99_log(X99_LOG_ERR, "error opening %s: %s", DEVURANDOM,
81
 
                    strerror(errno));
82
 
            return -1;
83
 
        }
84
 
    }
85
 
 
86
 
    if (x99_get_random(fd, rawchallenge, len) == -1) {
87
 
        x99_log(X99_LOG_ERR, "failed to obtain random data");
88
 
        return -1;
89
 
    }
90
 
    /* Convert the raw bytes to a decimal string. */
91
 
    for (i = 0; i < len; ++i)
92
 
        challenge[i] = '0' + rawchallenge[i] % 10;
93
 
    challenge[i] = '\0';
94
 
 
95
 
    return 0;
96
 
}
97
 
 
98
 
/*
99
 
 * Return some number of random bytes.
100
 
 * rnd_data must be allocated by the caller.
101
 
 * Returns 0 on success, -1 on failure, rnd_data is filled in.
102
 
 */
103
 
int
104
 
x99_get_random(int fd, unsigned char *rnd_data, int req_bytes)
105
 
{
106
 
    int bytes_read = 0;
107
 
 
108
 
    while (bytes_read < req_bytes) {
109
 
        int n;
110
 
 
111
 
        n = read(fd, rnd_data + bytes_read, req_bytes - bytes_read);
112
 
        if (n <= 0) {
113
 
            x99_log(X99_LOG_ERR, "x99_get_random: error reading from %s: %s",
114
 
                    DEVURANDOM, strerror(errno));
115
 
            return -1;
116
 
        }
117
 
        bytes_read += n;
118
 
    }
119
 
 
120
 
    return 0;
121
 
}
122
 
 
123
 
 
124
 
/*
125
 
 * Convert the ASCII string representation of a DES key to raw octets.
126
 
 * keyblock is filled in.  Returns 0 on success, -1 otherwise.
127
 
 */
128
 
int
129
 
x99_string_to_keyblock(const char *s, des_cblock keyblock)
130
 
{
131
 
    int i;
132
 
 
133
 
    if (s == NULL || strlen(s) < 16)
134
 
        return -1;
135
 
 
136
 
    /*
137
 
     * We could just use sscanf, but we do this a lot, and have very
138
 
     * specific needs, and it's easy to implement, so let's go for it!
139
 
     */
140
 
    for (i = 0; i < 8; ++i) {
141
 
        unsigned int n[2];
142
 
 
143
 
        n[0] = *s++ - '0';
144
 
        n[1] = *s++ - '0';
145
 
        if (n[0] > 9) {
146
 
            n[0] -= 'a' - '9' - 1;
147
 
        }
148
 
        if (n[1] > 9) {
149
 
            n[1] -= 'a' - '9' - 1;
150
 
        }
151
 
 
152
 
        keyblock[i]  = n[0] << 4;
153
 
        keyblock[i] += n[1];
154
 
    }
155
 
    return 0;
156
 
}
157
 
 
158
 
 
159
 
/* Character maps for generic hex and vendor specific decimal modes */
160
 
const char x99_hex_conversion[]         = "0123456789abcdef";
161
 
const char x99_cc_dec_conversion[]      = "0123456789012345";
162
 
const char x99_snk_dec_conversion[]     = "0123456789222333";
163
 
const char x99_sc_friendly_conversion[] = "0123456789ahcpef";
164
 
 
165
 
/*
166
 
 * Convert a DES keyblock to an ASCII string.
167
 
 * Fills in s, which must point to at least 17 bytes of space.
168
 
 * Note that each octet expands into 2 hex digits in ASCII (0xAA -> 0x4141);
169
 
 * add a NULL string terminator and you get the 17 byte requirement.
170
 
 */
171
 
void
172
 
x99_keyblock_to_string(char *s, const des_cblock keyblock,
173
 
                       const char conversion[17])
174
 
{
175
 
    int i;
176
 
 
177
 
    for (i = 0; i < 8; ++i) {
178
 
        unsigned n[2];
179
 
 
180
 
        n[0] = (keyblock[i] >> 4) & 0x0f;
181
 
        n[1] = keyblock[i] & 0x0f;
182
 
        s[2 * i + 0] = conversion[n[0]];
183
 
        s[2 * i + 1] = conversion[n[1]];
184
 
    }
185
 
    s[16] = '\0';
186
 
}
187
 
 
188
 
 
189
 
/*
190
 
 * fillin user_info from our database (key file)
191
 
 * returns 0 on success, -1 for user not found, -2 for other errors.
192
 
 */
193
 
int
194
 
x99_get_user_info(const char *pwdfile, const char *username,
195
 
                  x99_user_info_t *user_info)
196
 
{
197
 
    FILE *fp;
198
 
    char s[80];
199
 
    char *p, *q;
200
 
    int found, i;
201
 
    struct stat st;
202
 
 
203
 
    /* Verify permissions first. */
204
 
    if (stat(pwdfile, &st) != 0) {
205
 
        x99_log(X99_LOG_ERR, "x99_get_user_info: pwdfile %s error: %s",
206
 
                pwdfile, strerror(errno));
207
 
        return -2;
208
 
    }
209
 
    if ((st.st_mode & (S_IXUSR|S_IRWXG|S_IRWXO)) != 0) {
210
 
        x99_log(X99_LOG_ERR,
211
 
                "x99_get_user_info: pwdfile %s has loose permissions", pwdfile);
212
 
        return -2;
213
 
    }
214
 
 
215
 
    if ((fp = fopen(pwdfile, "r")) == NULL) {
216
 
        x99_log(X99_LOG_ERR, "x99_get_user_info: error opening %s: %s",
217
 
                pwdfile, strerror(errno));
218
 
        return -2;
219
 
    }
220
 
 
221
 
    /*
222
 
     * Find the requested user.
223
 
     * Add a ':' to the username to make sure we don't match shortest prefix.
224
 
     */
225
 
    p = malloc(strlen(username) + 2);
226
 
    if (!p) {
227
 
        x99_log(X99_LOG_CRIT, "x99_get_user_info: out of memory");
228
 
        return -2;
229
 
    }
230
 
    (void) sprintf(p, "%s:", username);
231
 
    found = 0;
232
 
    while (!feof(fp)) {
233
 
        if (fgets(s, sizeof(s), fp) == NULL) {
234
 
            if (!feof(fp)) {
235
 
                x99_log(X99_LOG_ERR,
236
 
                        "x99_get_user_info: error reading from %s: %s",
237
 
                        pwdfile, strerror(errno));
238
 
                (void) fclose(fp);
239
 
                free(p);
240
 
                return -2;
241
 
            }
242
 
        } else if (!strncmp(s, p, strlen(p))) {
243
 
            found = 1;
244
 
            break;
245
 
        }
246
 
    }
247
 
    (void) fclose(fp);
248
 
    free(p);
249
 
    if (!found) {
250
 
#if 0
251
 
        /* Noisy ... let the caller report this. */
252
 
        x99_log(X99_LOG_AUTH, "x99_get_user_info: [%s] not found in %s",
253
 
                username, pwdfile);
254
 
#endif
255
 
        return -1;
256
 
    }
257
 
 
258
 
    /* Found him, skip to next field (card). */
259
 
    if ((p = strchr(s, ':')) == NULL) {
260
 
        x99_log(X99_LOG_ERR,
261
 
                "x99_get_user_info: invalid format for [%s] in %s",
262
 
                username, pwdfile);
263
 
        return -2;
264
 
    }
265
 
    p++;
266
 
    /* strtok() */
267
 
    if ((q = strchr(p, ':')) == NULL) {
268
 
        x99_log(X99_LOG_ERR,
269
 
                "x99_get_user_info: invalid format for [%s] in %s",
270
 
                username, pwdfile);
271
 
        return -2;
272
 
    }
273
 
    *q++ = '\0';
274
 
    /* p: card_type, q: key */
275
 
 
276
 
    /* Match against card types. */
277
 
    found = 0;
278
 
    for (i = 0; card[i].name; ++i) {
279
 
        if (!strcasecmp(p, card[i].name)) {
280
 
            found = 1;
281
 
            user_info->card_id = card[i].id;
282
 
            break;
283
 
        }
284
 
    }
285
 
    if (!found) {
286
 
        x99_log(X99_LOG_ERR,
287
 
                "x99_get_user_info: unknown card %s for [%s] in %s",
288
 
                p, username, pwdfile);
289
 
        return -2;
290
 
    }
291
 
 
292
 
    if (!(strlen(q) == 16 || (strlen(q) == 17 && q[16] == '\n'))) {
293
 
        /* 8 octets + possible trailing newline */
294
 
        x99_log(X99_LOG_ERR, "x99_get_user_info: invalid key for [%s] in %s",
295
 
                username, pwdfile);
296
 
        return -2;
297
 
    }
298
 
 
299
 
    /* Convert the key from ASCII to a keyblock. (+translate error code) */
300
 
    return x99_string_to_keyblock(q, user_info->keyblock) * -2;
301
 
}
302