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