~ubuntu-branches/ubuntu/lucid/loop-aes-utils/lucid-security

« back to all changes in this revision

Viewing changes to login-utils/cryptocard.c

  • Committer: Bazaar Package Importer
  • Author(s): Max Vozeler
  • Date: 2008-08-22 11:57:17 UTC
  • mfrom: (8.1.3 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080822115717-v8wfa8pxwlfvyje0
Tags: 2.13.1-4
* patches/losetup_add_option_f.dpatch: 
  - Added to support "find next free loop" in losetup.
    (closes: #495682)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* cryptocard.c - support for the CRYPTOCard
2
 
   RB-1 Challenge-Response Token, initial code by 
3
 
   bentson@grieg.seaslug.org (Randolph Bentson) on 3-Dec-96,
4
 
   Hacked severely by poe@daimi.aau.dk.
5
 
   This relies on an implementation of DES in a library, currently
6
 
   it interfaces with the koontz-des.tar.gz implementation which
7
 
   can be found in:
8
 
 
9
 
      ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/des/
10
 
 
11
 
      (Link with the fdes.o file from that distribution)
12
 
 
13
 
   and with Eric A. Young's libdes implementation used in SSLeay. Also
14
 
   available from the above ftp site. Link with the libdes.a library.
15
 
 
16
 
   The sources for this code are maintained in
17
 
 
18
 
      ftp://ftp.daimi.aau.dk/pub/linux/poe/poeigl-X.XX.tar.gz
19
 
 
20
 
      1999-02-22 Arkadiusz Mi�kiewicz <misiek@pld.ORG.PL>
21
 
      - added Native Language Support
22
 
 
23
 
*/
24
 
#ifdef CRYPTOCARD
25
 
 
26
 
/******************** CONFIGURATION section *****************************/
27
 
/*--------------- select ONE DES implementation ------------------------*/
28
 
/*#define KOONTZ_DES */
29
 
#define EAY_LIBDES
30
 
/*--------------- define if on little endian machine (Intel x86) -------*/
31
 
#define LITTLE_ENDIAN
32
 
/******************** end of CONFIGURATION section **********************/
33
 
 
34
 
#define _BSD_SOURCE 
35
 
#define _GNU_SOURCE
36
 
 
37
 
#include <stdio.h>
38
 
#include <stdlib.h>
39
 
#include <stddef.h>
40
 
#include <string.h>
41
 
#include <unistd.h>
42
 
#include <fcntl.h>
43
 
#include <syslog.h>
44
 
#include <pwd.h>
45
 
#include <sys/param.h>
46
 
#include <sys/stat.h>
47
 
#include "nls.h"
48
 
 
49
 
#ifdef KOONTZ_DES
50
 
#include "../koontz-des/des.h"
51
 
#endif /* KOONTZ_DES */
52
 
 
53
 
#ifdef EAY_LIBDES
54
 
#include "../libdes/des.h"
55
 
#endif /* EAY_LIBDES */
56
 
 
57
 
#include "cryptocard.h"
58
 
 
59
 
static char *
60
 
generate_challenge(void)
61
 
{
62
 
    static char challenge_str[30];
63
 
    int rfd;
64
 
    unsigned long clong;
65
 
 
66
 
    /* create and present a challenge string */
67
 
    if ((rfd = open("/dev/urandom", O_RDONLY)) < 0) {
68
 
        syslog(LOG_NOTICE, _("couldn't open /dev/urandom"));
69
 
        return NULL;
70
 
    }
71
 
    if (read(rfd, &clong, 4) < 4) {
72
 
        close(rfd);
73
 
        syslog(LOG_NOTICE, _("couldn't read random data from /dev/urandom"));
74
 
        return NULL;
75
 
    }
76
 
    close(rfd);
77
 
 
78
 
    sprintf(challenge_str,"%08lu", clong);
79
 
    return challenge_str;
80
 
}
81
 
 
82
 
static char *
83
 
get_key()
84
 
{
85
 
    int success = 0;
86
 
    char keyfile[MAXPATHLEN];
87
 
    static char key[10];
88
 
    int rfd;
89
 
    struct stat statbuf;
90
 
 
91
 
    if (strlen(pwd->pw_dir) + 13 > sizeof(keyfile))
92
 
        goto bail_out;
93
 
    sprintf(keyfile, "%s/.cryptocard", pwd->pw_dir);
94
 
 
95
 
    if ((rfd = open(keyfile, O_RDONLY)) < 0) {
96
 
        syslog(LOG_NOTICE, _("can't open %s for reading"), keyfile);
97
 
        goto bail_out;
98
 
    }
99
 
    if (fstat(rfd, &statbuf) < 0) {
100
 
        syslog(LOG_NOTICE, _("can't stat(%s)"), keyfile);
101
 
        goto close_and_bail_out;
102
 
    }
103
 
    if ((statbuf.st_uid != pwd->pw_uid)
104
 
        || ((statbuf.st_mode & S_IFMT) != S_IFREG)
105
 
        || (statbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) {
106
 
        syslog(LOG_NOTICE, _("%s doesn't have the correct filemodes"), keyfile);
107
 
        goto close_and_bail_out;
108
 
    }
109
 
    
110
 
    if (read(rfd, key, 8) < 8) {
111
 
        syslog(LOG_NOTICE, _("can't read data from %s"), keyfile);
112
 
        goto close_and_bail_out;
113
 
    }
114
 
 
115
 
    key[8] = 0;
116
 
    success = 1;
117
 
    
118
 
close_and_bail_out:
119
 
    close(rfd);
120
 
 
121
 
bail_out:
122
 
    if (success)
123
 
        return key;
124
 
    else 
125
 
        return NULL;
126
 
}
127
 
 
128
 
static int
129
 
check_response(char *challenge, char *response, char *key)
130
 
{
131
 
    char buf[20];
132
 
 
133
 
#ifdef KOONTZ_DES
134
 
    extern void des (union LR_block *);
135
 
    extern void loadkey(char *,int);
136
 
    extern void set_des_mode(int);
137
 
 
138
 
    union LR_block data;
139
 
 
140
 
    strncpy((char *)data.string, (char *)challenge, 8);
141
 
    set_des_mode(ENCRYPT);
142
 
    loadkey(key, NOSHIFT);
143
 
    des(&data);
144
 
 
145
 
    memset(key, 0, 8); /* no need for the secret key anymore, scratch it */
146
 
 
147
 
    sprintf(buf, "%2.2X%2.2X%2.2X%2.2X",
148
 
            (int)(data.LR[0]) & 0xff,
149
 
            (int)(data.LR[0]>>8) & 0xff,
150
 
            (int)(data.LR[0]>>16) & 0xff,
151
 
            (int)(data.LR[0]>>24) & 0xff);
152
 
#endif /* KOONTZ_DES */
153
 
#ifdef EAY_LIBDES
154
 
    des_cblock       res;
155
 
    des_key_schedule ks;
156
 
    
157
 
    des_set_key((des_cblock *)key, ks);
158
 
    memset(key, 0, 8);
159
 
    des_ecb_encrypt((des_cblock *)challenge, &res, ks, DES_ENCRYPT);
160
 
 
161
 
#ifdef LITTLE_ENDIAN
162
 
    /* use this on Intel x86 boxes */
163
 
    sprintf(buf, "%2.2X%2.2X%2.2X%2.2X",
164
 
            res[0], res[1], res[2], res[3]);
165
 
#else /* ie. BIG_ENDIAN */
166
 
    /* use this on big endian RISC boxes */
167
 
    sprintf(buf, "%2.2X%2.2X%2.2X%2.2X",
168
 
            res[3], res[2], res[1], res[0]);
169
 
#endif /* LITTLE_ENDIAN */
170
 
#endif /* EAY_LIBDES */
171
 
 
172
 
    /* return success only if ALL requirements have been met */
173
 
    if (strncmp(buf, response, 8) == 0)
174
 
        return 1;
175
 
 
176
 
    return 0;
177
 
}
178
 
 
179
 
int
180
 
cryptocard(void)
181
 
{
182
 
    char prompt[80];
183
 
    char *challenge;
184
 
    char *key;
185
 
    char *response;
186
 
 
187
 
    challenge = generate_challenge();
188
 
    if (challenge == NULL) return 0;
189
 
 
190
 
    if (strlen(challenge) + 13 > sizeof(prompt)) return 0;
191
 
    sprintf(prompt, "%s Password: ", challenge);
192
 
 
193
 
    alarm((unsigned int)timeout);  /* give user time to fiddle with card */
194
 
    response = getpass(prompt);  /* presents challenge and gets response */
195
 
 
196
 
    if (response == NULL) return 0;
197
 
 
198
 
    /* This requires some explanation: As root we may not be able to
199
 
       read the directory of the user if it is on an NFS mounted
200
 
       filesystem. We temporarily set our effective uid to the user-uid
201
 
       making sure that we keep root privs. in the real uid. 
202
 
 
203
 
       A portable solution would require a fork(), but we rely on Linux
204
 
       having the BSD setreuid() */
205
 
 
206
 
    {
207
 
        uid_t ruid = getuid();
208
 
        gid_t egid = getegid();
209
 
 
210
 
        setregid(-1, pwd->pw_gid);
211
 
        setreuid(0, pwd->pw_uid);
212
 
 
213
 
        /* now we can access the file */
214
 
        /* get the (properly qualified) key */
215
 
        key = get_key();
216
 
 
217
 
        /* reset to root privs */
218
 
        setuid(0); /* setreuid doesn't do it alone! */
219
 
        setreuid(ruid, 0);
220
 
        setregid(-1, egid);
221
 
 
222
 
        if (key == NULL) return 0;
223
 
    }
224
 
 
225
 
    return check_response(challenge, response, key);
226
 
}
227
 
 
228
 
#endif /* CRYPTOCARD */