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