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( vol, bfree, btotal, bsize ) 33struct vol *vol; 34VolSpace *bfree, *btotal; 35u_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 78int 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 132void afsmode( path, ma, dir, st ) 133char *path; 134struct maccess *ma; 135struct dir *dir; 136struct 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 161extern struct dir *curdir; 162/* 163 * cmd | 0 | vid | did | pathtype | pathname | 0 | acl 164 */ 165int 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 229extern C_Block seskey; 230extern Key_schedule seskeysched; 231 232int 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 */ 328