~ubuntu-branches/debian/lenny/netatalk/lenny

« back to all changes in this revision

Viewing changes to etc/uams/uams_pgp.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: uams_pgp.c,v 1.7.2.1 2003/01/26 16:55:05 srittau Exp $
 
3
 *
 
4
 * Copyright (c) 1990,1993 Regents of The University of Michigan.
 
5
 * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
 
6
 * All Rights Reserved.  See COPYRIGHT.
 
7
 */
 
8
 
 
9
#ifdef HAVE_CONFIG_H
 
10
#include "config.h"
 
11
#endif /* HAVE_CONFIG_H */
 
12
 
 
13
#ifdef UAM_PGP
 
14
 
 
15
/* for crypt() */
 
16
#define _XOPEN_SOURCE
 
17
#include <stdio.h>
 
18
#include <stdlib.h>
 
19
#include <string.h>
 
20
#ifdef HAVE_UNISTD_H
 
21
#include <unistd.h>
 
22
#endif /* HAVE_UNISTD_H */
 
23
#include <pwd.h>
 
24
#include <atalk/logger.h>
 
25
 
 
26
#ifdef OPENSSL_DHX
 
27
#include <openssl/bn.h>
 
28
#include <openssl/dh.h>
 
29
#include <openssl/cast.h>
 
30
#else /* OPENSSL_DHX */
 
31
#include <bn.h>
 
32
#include <dh.h>
 
33
#include <cast.h>
 
34
#endif /* OPENSSL_DHX */
 
35
 
 
36
#include <atalk/afp.h>
 
37
#include <atalk/uam.h>
 
38
 
 
39
#define KEYSIZE 16
 
40
#define PASSWDLEN 64
 
41
#define CRYPTBUFLEN  (KEYSIZE*2)
 
42
#define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN)
 
43
 
 
44
/* hash a number to a 16-bit quantity */
 
45
#define pgphash(a) ((((unsigned long) (a) >> 8) ^ \
 
46
                     (unsigned long) (a)) & 0xffff)
 
47
 
 
48
/* the secret key */
 
49
static struct passwd *pgppwd;
 
50
static CAST_KEY castkey;
 
51
static u_int8_t randbuf[16];
 
52
 
 
53
/* pgp passwd */
 
54
static int pgp_login(void *obj, struct passwd **uam_pwd,
 
55
                     char *ibuf, int ibuflen,
 
56
                     char *rbuf, int *rbuflen)
 
57
{
 
58
    BIGNUM *bn, *gbn, *pbn;
 
59
    u_int16_t sessid;
 
60
    int len, i;
 
61
    char *name;
 
62
 
 
63
    *rbuflen = 0;
 
64
 
 
65
    if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &name, &i) < 0)
 
66
      return AFPERR_PARAM;
 
67
 
 
68
    len = (unsigned char) *ibuf++;
 
69
    if ( len > i ) {
 
70
        return( AFPERR_PARAM );
 
71
    }
 
72
 
 
73
    memcpy(name, ibuf, len );
 
74
    ibuf += len;
 
75
    name[ len ] = '\0';
 
76
    if ((unsigned long) ibuf & 1) /* padding */
 
77
      ++ibuf;
 
78
 
 
79
    if (( pgppwd = uam_getname(name, i)) == NULL ) {
 
80
      return AFPERR_PARAM;
 
81
    }
 
82
 
 
83
    LOG(log_info, logtype_uams, "pgp login: %s", name);
 
84
    if (uam_checkuser(pgppwd) < 0)
 
85
      return AFPERR_NOTAUTH;
 
86
 
 
87
    /* get the challenge */
 
88
    len = (unsigned char) *ibuf++;
 
89
    /* challenge */
 
90
    
 
91
    /* get the signature. it's always 16 bytes. */
 
92
    if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE, 
 
93
                             (void *) &name, NULL) < 0) {
 
94
      *rbuflen = 0;
 
95
      goto pgp_fail;
 
96
    }
 
97
    memcpy(rbuf + KEYSIZE, name, KEYSIZE); 
 
98
 
 
99
pgp_fail:
 
100
    return AFPERR_PARAM;
 
101
}
 
102
 
 
103
static int pgp_logincont(void *obj, struct passwd **uam_pwd,
 
104
                         char *ibuf, int ibuflen, 
 
105
                         char *rbuf, int *rbuflen)
 
106
{
 
107
        unsigned char iv[] = "RJscorat";
 
108
    BIGNUM *bn1, *bn2, *bn3;
 
109
    u_int16_t sessid;
 
110
    char *p;
 
111
 
 
112
    *rbuflen = 0;
 
113
 
 
114
    /* check for session id */
 
115
    memcpy(&sessid, ibuf, sizeof(sessid));
 
116
    if (sessid != pgphash(obj))
 
117
      return AFPERR_PARAM;
 
118
    ibuf += sizeof(sessid);
 
119
   
 
120
    /* use rbuf as scratch space */
 
121
    CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey,
 
122
                     iv, CAST_DECRYPT);
 
123
    
 
124
    /* check to make sure that the random number is the same. we
 
125
     * get sent back an incremented random number. */
 
126
    if (!(bn1 = BN_bin2bn(rbuf, KEYSIZE, NULL)))
 
127
      return AFPERR_PARAM;
 
128
 
 
129
    if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) {
 
130
      BN_free(bn1);
 
131
      return AFPERR_PARAM;
 
132
    }
 
133
      
 
134
    /* zero out the random number */
 
135
    memset(rbuf, 0, sizeof(randbuf));
 
136
    memset(randbuf, 0, sizeof(randbuf));
 
137
    rbuf += KEYSIZE;
 
138
 
 
139
    if (!(bn3 = BN_new())) {
 
140
      BN_free(bn2);
 
141
      BN_free(bn1);
 
142
      return AFPERR_PARAM;
 
143
    }
 
144
 
 
145
    BN_sub(bn3, bn1, bn2);
 
146
    BN_free(bn2);
 
147
    BN_free(bn1);
 
148
 
 
149
    /* okay. is it one more? */
 
150
    if (!BN_is_one(bn3)) {
 
151
      BN_free(bn3);
 
152
      return AFPERR_PARAM;
 
153
    }
 
154
    BN_free(bn3);
 
155
 
 
156
#ifdef AFS
 
157
    if ( kcheckuser(*uam_pwd, rbuf) == 0) {
 
158
      *uam_pwd = pgppwd;
 
159
      return AFP_OK;
 
160
    }
 
161
#endif /* AFS */
 
162
 
 
163
    rbuf[PASSWDLEN] = '\0';
 
164
    p = crypt( rbuf, pgppwd->pw_passwd );
 
165
    memset(rbuf, 0, PASSWDLEN);
 
166
    if ( strcmp( p, pgppwd->pw_passwd ) == 0 ) {
 
167
      *uam_pwd = pgppwd;
 
168
      return AFP_OK;
 
169
    }
 
170
 
 
171
    return AFPERR_NOTAUTH;
 
172
}
 
173
 
 
174
 
 
175
static int uam_setup(const char *path)
 
176
{
 
177
  if (uam_register(UAM_SERVER_LOGIN, path, "PGPuam 1.0",
 
178
                   pgp_login, pgp_logincont, NULL) < 0)
 
179
    return -1;
 
180
 
 
181
  return 0;
 
182
}
 
183
 
 
184
static void uam_cleanup(void)
 
185
{
 
186
  uam_unregister(UAM_SERVER_LOGIN, "PGPuam 1.0");
 
187
}
 
188
 
 
189
UAM_MODULE_EXPORT struct uam_export uams_pgp = {
 
190
  UAM_MODULE_SERVER,
 
191
  UAM_MODULE_VERSION,
 
192
  uam_setup, uam_cleanup
 
193
};
 
194
 
 
195
#endif /* UAM_PGP */