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