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 32int afs_getvolspace(struct vol *vol, VolSpace *bfree, VolSpace *btotal, u_int32_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 75int 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 u_int32_t did; 82 u_int16_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 129void 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 154extern struct dir *curdir; 155/* 156 * cmd | 0 | vid | did | pathtype | pathname | 0 | acl 157 */ 158int 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 u_int32_t did; 166 u_int16_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 222extern C_Block seskey; 223extern Key_schedule seskeysched; 224 225int 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 u_int16_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 */ 321