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