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