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 31int 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 74int 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 128void 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 153extern struct dir *curdir; 154/* 155 * cmd | 0 | vid | did | pathtype | pathname | 0 | acl 156 */ 157int 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 221extern C_Block seskey; 222extern Key_schedule seskeysched; 223 224int 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 */ 320