]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afs.c
365fca87cbea7cb08bd95481cbe38be824480e6b
[netatalk.git] / etc / afpd / afs.c
1 /*
2  * $Id: afs.c,v 1.13 2002-10-11 14:18:24 didg Exp $
3  * Copyright (c) 1990,1993 Regents of The University of Michigan.
4  * All Rights Reserved.  See COPYRIGHT.
5  */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif /* HAVE_CONFIG_H */
10
11 #ifdef AFS
12
13 #include <string.h>
14 #include <sys/types.h>
15 #include <atalk/logger.h>
16 #include <netatalk/endian.h>
17 #include <netinet/in.h>
18 #include <afs/venus.h>
19 #include <afs/afsint.h>
20 #include <atalk/afp.h>
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif /* HAVE_UNISTD_H */
24
25 #include "globals.h"
26 #include "directory.h"
27 #include "volume.h"
28 #include "misc.h"
29
30 afs_getvolspace( vol, bfree, btotal, bsize )
31 struct vol      *vol;
32 VolSpace        *bfree, *btotal;
33 u_int32_t   *bsize;
34 {
35     struct ViceIoctl    vi;
36     struct VolumeStatus *vs;
37     char                venuspace[ sizeof( struct VolumeStatus ) + 3 ];
38     int                 total, free;
39
40     vi.in_size = 0;
41     vi.out_size = sizeof( venuspace );
42     vi.out = venuspace;
43     if ( pioctl( vol->v_path, VIOCGETVOLSTAT, &vi, 1 ) < 0 ) {
44         return( AFPERR_PARAM );
45     }
46
47     vs = (struct VolumeStatus *)venuspace;
48
49     if ( vs->PartBlocksAvail > 0 ) {
50         if ( vs->MaxQuota != 0 ) {
51 #define min(x,y)        (((x)<(y))?(x):(y))
52             free = min( vs->MaxQuota - vs->BlocksInUse, vs->PartBlocksAvail );
53         } else {
54             free = vs->PartBlocksAvail;
55         }
56     } else {
57         free = 0;
58     }
59
60     if ( vs->MaxQuota != 0 ) {
61         total = free + vs->BlocksInUse;
62     } else {
63         total = vs->PartMaxBlocks;
64     }
65
66     *bsize = 1024;
67     *bfree = (VolSpace) free * 1024;
68     *btotal = (VolSpace) total * 1024;
69
70     return( AFP_OK );
71 }
72
73 afp_getdiracl(obj, ibuf, ibuflen, rbuf, rbuflen )
74 AFPObj      *obj;
75 char    *ibuf, *rbuf;
76 int             ibuflen, *rbuflen;
77 {
78     struct ViceIoctl    vi;
79     struct vol          *vol;
80     struct dir          *dir;
81     struct path         *path;
82     u_int32_t           did;
83     u_int16_t           vid;
84
85     ibuf += 2;
86     memcpy( &vid, ibuf, sizeof( vid ));
87     ibuf += sizeof( short );
88     if (( vol = getvolbyvid( vid )) == NULL ) {
89         *rbuflen = 0;
90         return( AFPERR_PARAM );
91     }
92
93     memcpy( &did, ibuf, sizeof( did ));
94     ibuf += sizeof( int );
95     if (( dir = dirlookup( vol, did )) == NULL ) {
96         *rbuflen = 0;
97         return( AFPERR_NOOBJ );
98     }
99
100     if (( path = cname( vol, dir, &ibuf )) == NULL ) {
101         *rbuflen = 0;
102         return( AFPERR_NOOBJ );
103     }
104     if ( *path->m_name != '\0' ) {
105         *rbuflen = 0;
106         return( AFPERR_BITMAP );
107     }
108
109     vi.in_size = 0;
110     vi.out_size = *rbuflen;
111     vi.out = rbuf;
112     if ( pioctl( ".", VIOCGETAL, &vi, 1 ) < 0 ) {
113         *rbuflen = 0;
114         return( AFPERR_PARAM );
115     }
116     *rbuflen = strlen( vi.out ) + 1;
117     return( AFP_OK );
118 }
119
120 /*
121  * Calculate the mode for a directory in AFS.  First, make sure the
122  * directory is in AFS.  Could probably use something less heavy than
123  * VIOCGETAL.  If the directory is on AFS, use access() calls to
124  * estimate permission, a la mdw.
125  */
126 #ifdef accessmode
127     #undef accessmode
128 #endif
129
130 afsmode( path, ma, dir, st )
131 char            *path;
132 struct maccess  *ma;
133 struct dir      *dir;
134 struct stat     *st;
135 {
136     struct ViceIoctl    vi;
137     char                buf[ 1024 ];
138
139     if (( dir->d_flags & DIRF_FSMASK ) == DIRF_NOFS ) {
140         vi.in_size = 0;
141         vi.out_size = sizeof( buf );
142         vi.out = buf;
143         if ( pioctl( path, VIOCGETAL, &vi, 1 ) < 0 ) {
144             dir->d_flags |= DIRF_UFS;
145         } else {
146             dir->d_flags |= DIRF_AFS;
147         }
148     }
149
150     if (( dir->d_flags & DIRF_FSMASK ) != DIRF_AFS ) {
151         return;
152     }
153
154     accessmode( path, &ma, dir, st );
155
156     return;
157 }
158
159 extern struct dir       *curdir;
160 /*
161  * cmd | 0 | vid | did | pathtype | pathname | 0 | acl
162  */
163 afp_setdiracl(obj, ibuf, ibuflen, rbuf, rbuflen )
164 AFPObj      *obj;
165 char    *ibuf, *rbuf;
166 int             ibuflen, *rbuflen;
167 {
168     struct ViceIoctl    vi;
169     struct vol          *vol;
170     struct dir          *dir;
171     char                *iend;
172     struct path         *path;
173     u_int32_t           did;
174     u_int16_t           vid;
175
176     *rbuflen = 0;
177     iend = ibuf + ibuflen;
178     ibuf += 2;
179     memcpy( &vid, ibuf, sizeof( vid ));
180     ibuf += sizeof( short );
181     if (( vol = getvolbyvid( vid )) == NULL ) {
182         *rbuflen = 0;
183         return( AFPERR_PARAM );
184     }
185
186     memcpy( &did, ibuf, sizeof( did ));
187     ibuf += sizeof( int );
188     if (( dir = dirlookup( vol, did )) == NULL ) {
189         *rbuflen = 0;
190         return( AFPERR_NOOBJ );
191     }
192
193     if (( path = cname( vol, dir, &ibuf )) == NULL ) {
194         *rbuflen = 0;
195         return( AFPERR_NOOBJ );
196     }
197     if ( *path->m_name != '\0' ) {
198         *rbuflen = 0;
199         return( AFPERR_BITMAP );
200     }
201
202     if ((int)ibuf & 1 ) {
203         ibuf++;
204     }
205
206     vi.in_size = iend - ibuf;
207     vi.in = ibuf;
208     vi.out_size = 0;
209
210     if ( pioctl( ".", VIOCSETAL, &vi, 1 ) < 0 ) {
211         *rbuflen = 0;
212         return( AFPERR_PARAM );
213     }
214     pioctl( ".AppleDouble", VIOCSETAL, &vi, 1 );
215     if ( curdir->d_did  == DIRDID_ROOT ) {
216         pioctl( ".AppleDesktop", VIOCSETAL, &vi, 1 );
217     }
218
219     return( AFP_OK );
220 }
221
222
223 #ifdef UAM_AFSKRB
224
225 #include <krb.h>
226 #include <des.h>
227 #include <afs/kauth.h>
228 #include <afs/kautils.h>
229
230 extern C_Block          seskey;
231 extern Key_schedule     seskeysched;
232
233 afp_afschangepw(obj, ibuf, ibuflen, rbuf, rbuflen )
234 AFPObj      *obj;
235 char    *ibuf, *rbuf;
236 int             ibuflen, *rbuflen;
237 {
238     char        name[ MAXKTCNAMELEN ], instance[ MAXKTCNAMELEN ];
239     char        realm[ MAXKTCREALMLEN ];
240     char        oldpw[ 9 ], newpw[ 9 ];
241     int         len, rc;
242     u_int16_t   clen;
243     struct ktc_encryptionKey    oldkey, newkey;
244     struct ktc_token            adtok;
245     struct ubik_client          *conn;
246
247     *rbuflen = 0;
248     ++ibuf;
249     len = (unsigned char) *ibuf++;
250     ibuf[ len ] = '\0';
251     *name = *instance = *realm = '\0';
252     ka_ParseLoginName( ibuf, name, instance, realm );
253     ucase( realm );
254     if ( *realm == '\0' ) {
255         if ( krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
256             LOG(log_error, logtype_afpd, "krb_get_lrealm failed" );
257             return( AFPERR_BADUAM );
258         }
259     }
260
261     if ( strlen( name ) < 2 || strlen( name ) > 18 ) {
262         return( AFPERR_PARAM );
263     }
264     ibuf += len;
265
266     memcpy( &clen, ibuf, sizeof( clen ));
267     clen = ntohs( clen );
268     if ( clen % 8 != 0 ) {
269         return( AFPERR_PARAM );
270     }
271
272     ibuf += sizeof( short );
273     pcbc_encrypt((C_Block *)ibuf, (C_Block *)ibuf,
274                  clen, seskeysched, seskey, DES_DECRYPT );
275
276     len = (unsigned char) *ibuf++;
277     if ( len > 8 ) {
278         return( AFPERR_PARAM );
279     }
280     memset( oldpw, 0, sizeof( oldpw ));
281     memcpy( oldpw, ibuf, len );
282     ibuf += len;
283     oldpw[ len ] = '\0';
284
285     len = (unsigned char) *ibuf++;
286     if ( len > 8 ) {
287         return( AFPERR_PARAM );
288     }
289     memset( newpw, 0, sizeof( newpw ));
290     memcpy( newpw, ibuf, len );
291     ibuf += len;
292     newpw[ len ] = '\0';
293
294     LOG(log_info, logtype_afpd,
295         "changing password for <%s>.<%s>@<%s>", name, instance, realm );
296
297     ka_StringToKey( oldpw, realm, &oldkey );
298     memset( oldpw, 0, sizeof( oldpw ));
299     ka_StringToKey( newpw, realm, &newkey );
300     memset( newpw, 0, sizeof( newpw ));
301
302     rc = ka_GetAdminToken( name, instance, realm, &oldkey, 60, &adtok, 0 );
303     memset( &oldkey, 0, sizeof( oldkey ));
304     switch ( rc ) {
305     case 0:
306         break;
307     case KABADREQUEST:
308         memset( &newkey, 0, sizeof( newkey ));
309         return( AFPERR_NOTAUTH );
310     default:
311         memset( &newkey, 0, sizeof( newkey ));
312         return( AFPERR_BADUAM );
313     }
314     if ( ka_AuthServerConn( realm, KA_MAINTENANCE_SERVICE, &adtok, &conn )
315             != 0 ) {
316         memset( &newkey, 0, sizeof( newkey ));
317         return( AFPERR_BADUAM );
318     }
319
320     rc = ka_ChangePassword( name, instance, conn, 0, &newkey );
321     memset( &newkey, 0, sizeof( newkey ));
322     if ( rc != 0 ) {
323         return( AFPERR_BADUAM );
324     }
325
326     LOG(log_debug, logtype_afpd, "password changed succeeded" );
327     return( AFP_OK );
328 }
329
330 #endif /* UAM_AFSKRB */
331 #endif /* AFS */