X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Ffile.c;h=8cd5f456947333a38372e90487aa78c7819eae70;hp=ce2ab545efd90edb12b869e7c4dfd80a0c3c230c;hb=4111aba41c36a99bfd7eb7e987b24314735cdd10;hpb=3399095adaa5fad2ec2c7fbbed1de9222106da59 diff --git a/etc/afpd/file.c b/etc/afpd/file.c index ce2ab545..8cd5f456 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "directory.h" #include "dircache.h" @@ -118,7 +119,7 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t if (!utf8) { /* want mac name */ - if (utf8_encoding()) { + if (utf8_encoding(vol->v_obj)) { /* but name is an utf8 mac name */ char *u, *m; @@ -238,32 +239,29 @@ restart: vol->v_path); vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL); if (vol->v_cdb) { - /* set ro mode*/ - vol->v_flags |= AFPVOL_RO; -#ifdef SERVERTEXT - /* kill ourself with SIGUSR2 aka msg pending */ - setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead." - "Check server messages for details. Switching to read-only mode."); - kill(getpid(), SIGUSR2); -#endif - goto restart; /* not try again with the temp CNID db */ + if (!(vol->v_flags & AFPVOL_TM)) { + vol->v_flags |= AFPVOL_RO; + setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead." + "Check server messages for details. Switching to read-only mode."); + kill(getpid(), SIGUSR2); + } + goto restart; /* now try again with the temp CNID db */ } else { -#ifdef SERVERTEXT setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB failed too!" "Check server messages for details, can't recover from this state!"); -#endif } } afp_errno = AFPERR_MISC; goto exit; } } - else if (adp && (adcnid != dbcnid)) { /* 4 */ + else if (adp && adcnid && (adcnid != dbcnid)) { /* 4 */ /* Update the ressource fork. For a folder adp is always null */ LOG(log_debug, logtype_afpd, "get_id(%s/%s): calling ad_setid(old: %u, new: %u)", getcwdpath(), upath, htonl(adcnid), htonl(dbcnid)); if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) { - ad_flush(adp); + if (ad_flush(adp) != 0) + LOG(log_error, logtype_afpd, "get_id(\"%s\"): can't flush", fullpathname(upath)); } } } @@ -274,10 +272,11 @@ exit: } /* -------------------------- */ -int getmetadata(struct vol *vol, - uint16_t bitmap, - struct path *path, struct dir *dir, - char *buf, size_t *buflen, struct adouble *adp) +int getmetadata(const AFPObj *obj, + struct vol *vol, + uint16_t bitmap, + struct path *path, struct dir *dir, + char *buf, size_t *buflen, struct adouble *adp) { char *data, *l_nameoff = NULL, *upath; char *utf_nameoff = NULL; @@ -297,7 +296,7 @@ int getmetadata(struct vol *vol, data = buf; if ( ((bitmap & ( (1 << FILPBIT_FINFO)|(1 << FILPBIT_LNAME)|(1 <m_name) - || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */ + || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding(obj)) /* FIXME should be m_name utf8 filename */ || (bitmap & (1 << FILPBIT_FNUM))) { if (!path->id) { bstring fullpath; @@ -314,7 +313,7 @@ int getmetadata(struct vol *vol, /* Get macname from unixname first */ if (path->m_name == NULL) { - if ((path->m_name = utompath(vol, upath, id, utf8_encoding())) == NULL) { + if ((path->m_name = utompath(vol, upath, id, utf8_encoding(obj))) == NULL) { LOG(log_error, logtype_afpd, "getmetadata: utompath error"); return AFPERR_MISC; } @@ -346,7 +345,7 @@ int getmetadata(struct vol *vol, return afp_errno; if (!path->m_name) { - path->m_name = utompath(vol, upath, id, utf8_encoding()); + path->m_name = utompath(vol, upath, id, utf8_encoding(vol->v_obj)); } } while ( bitmap != 0 ) { @@ -465,7 +464,7 @@ int getmetadata(struct vol *vol, to "pXYZ" when we created it. See IA, Ver 2. */ case FILPBIT_PDINFO : - if (afp_version >= 30) { /* UTF8 name */ + if (obj->afp_version >= 30) { /* UTF8 name */ utf8 = kTextEncodingUTF8; utf_nameoff = data; data += sizeof( uint16_t ); @@ -536,7 +535,7 @@ int getmetadata(struct vol *vol, break; case FILPBIT_UNIXPR : /* accessmode may change st_mode with ACLs */ - accessmode(vol, upath, &ma, dir , st); + accessmode(obj, vol, upath, &ma, dir , st); aint = htonl(st->st_uid); memcpy( data, &aint, sizeof( aint )); @@ -589,10 +588,8 @@ int getmetadata(struct vol *vol, } /* ----------------------- */ -int getfilparams(struct vol *vol, - uint16_t bitmap, - struct path *path, struct dir *dir, - char *buf, size_t *buflen ) +int getfilparams(const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct path *path, + struct dir *dir, char *buf, size_t *buflen, int in_enumerate) { struct adouble ad, *adp; int opened = 0; @@ -606,7 +603,12 @@ int getfilparams(struct vol *vol, if (opened) { char *upath; - flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0; + /* + * Dont check for and resturn open fork attributes when enumerating + * This saves a lot of syscalls, the client will hopefully only use the result + * in FPGetFileParms where we return the correct value + */ + flags = (!in_enumerate &&(bitmap & (1 << FILPBIT_ATTR))) ? ADFLAGS_CHECK_OF : 0; adp = of_ad(vol, path, &ad); upath = path->u_name; @@ -627,7 +629,7 @@ int getfilparams(struct vol *vol, } } } - rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp); + rc = getmetadata(obj, vol, bitmap, path, dir, buf, buflen, adp); ad_close(adp, ADFLAGS_HF | flags); return( rc ); @@ -699,6 +701,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, return( AFPERR_ACCESS ); case EDQUOT: case ENOSPC : + LOG(log_info, logtype_afpd, "afp_createfile: DISK FULL"); return( AFPERR_DFULL ); default : return( AFPERR_PARAM ); @@ -724,8 +727,14 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, return AFPERR_MISC; } - (void)get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath)); + cnid_t id; + if ((id = get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath))) == CNID_INVALID) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath); + goto createfile_iderr; + } + (void)ad_setid(&ad, st.st_dev, st.st_ino, id, dir->d_did, vol->v_stamp); +createfile_iderr: ad_flush(&ad); ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF ); fce_register_new_file(s_path); @@ -784,7 +793,7 @@ int afp_setfilparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ ibuf++; } - if (AFP_OK == ( rc = setfilparams(vol, s_path, bitmap, ibuf )) ) { + if (AFP_OK == ( rc = setfilparams(obj, vol, s_path, bitmap, ibuf )) ) { setvoltime(obj, vol ); } @@ -797,7 +806,7 @@ int afp_setfilparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ */ extern struct path Cur_Path; -int setfilparams(struct vol *vol, +int setfilparams(const AFPObj *obj, struct vol *vol, struct path *path, uint16_t f_bitmap, char *buf ) { struct adouble ad, *adp; @@ -828,7 +837,7 @@ int setfilparams(struct vol *vol, adp = of_ad(vol, path, &ad); upath = path->u_name; - if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) { + if (!vol_unix_priv(vol) && check_access(obj, vol, upath, OPENACC_WR ) < 0) { return AFPERR_ACCESS; } @@ -916,7 +925,7 @@ int setfilparams(struct vol *vol, } break; case FILPBIT_PDINFO : - if (afp_version < 30) { /* else it's UTF8 name */ + if (obj->afp_version < 30) { /* else it's UTF8 name */ achar = *buf; buf += 2; /* Keep special case to support crlf translations */ @@ -1001,7 +1010,7 @@ int setfilparams(struct vol *vol, } break; case FILPBIT_PDINFO : - if (afp_version < 30) { /* else it's UTF8 name */ + if (obj->afp_version < 30) { /* else it's UTF8 name */ memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 ); memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 ); break; @@ -1145,14 +1154,14 @@ size_t plen = 0; uint16_t len16; uint32_t hint; - if ( type != 2 && !(afp_version >= 30 && type == 3) ) { + if ( type != 2 && !(vol->v_obj->afp_version >= 30 && type == 3) ) { return -1; } ibuf++; switch (type) { case 2: if (( plen = (unsigned char)*ibuf++ ) != 0 ) { - if (afp_version >= 30) { + if (vol->v_obj->afp_version >= 30) { /* convert it to UTF8 */ if ((plen = mtoUTF8(vol, ibuf, plen, newname, AFPOBJ_TMPSIZ)) == (size_t)-1) @@ -1246,6 +1255,19 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) { return AFPERR_DENYCONF; } +#ifdef HAVE_FSHARE_T + fshare_t shmd; + shmd.f_access = F_RDACC; + shmd.f_deny = F_NODNY; + if (fcntl(ad_data_fileno(adp), F_SHARE, &shmd) != 0) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } + if (AD_RSRC_OPEN(adp) && fcntl(ad_reso_fileno(adp), F_SHARE, &shmd) != 0) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } +#endif denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 ); @@ -1296,7 +1318,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si /* newname is always only a filename so curdir *is* its * parent folder */ - if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding()))) { + if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding(d_vol->v_obj)))) { retvalue =AFPERR_PARAM; goto copy_exit; } @@ -1414,6 +1436,7 @@ done: case EDQUOT: case EFBIG: case ENOSPC: + LOG(log_info, logtype_afpd, "copyfile: DISK FULL"); return AFPERR_DFULL; case ENOENT: return AFPERR_NOOBJ; @@ -1673,7 +1696,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir) /* ------------------------------ resolve a file id */ -int afp_resolveid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +int afp_resolveid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { struct vol *vol; struct dir *dir; @@ -1759,17 +1782,17 @@ retry: /* directories are bad */ if (S_ISDIR(path.st.st_mode)) { /* OS9 and OSX don't return the same error code */ - return (afp_version >=30)?AFPERR_NOID:AFPERR_BADTYPE; + return (obj->afp_version >=30)?AFPERR_NOID:AFPERR_BADTYPE; } memcpy(&bitmap, ibuf, sizeof(bitmap)); bitmap = ntohs( bitmap ); - if (NULL == (path.m_name = utompath(vol, upath, cnid, utf8_encoding()))) { + if (NULL == (path.m_name = utompath(vol, upath, cnid, utf8_encoding(obj)))) { return AFPERR_NOID; } path.id = cnid; - if (AFP_OK != (err = getfilparams(vol, bitmap, &path , curdir, - rbuf + sizeof(bitmap), &buflen))) { + if (AFP_OK != (err = getfilparams(obj, vol, bitmap, &path , curdir, + rbuf + sizeof(bitmap), &buflen, 0))) { return err; } *rbuflen = buflen + sizeof(bitmap); @@ -1862,7 +1885,7 @@ delete: } /* ------------------------------ */ -static struct adouble *find_adouble(struct path *path, struct ofork **of, struct adouble *adp) +static struct adouble *find_adouble(const AFPObj *obj, struct vol *vol, struct path *path, struct ofork **of, struct adouble *adp) { int ret; @@ -1884,7 +1907,7 @@ static struct adouble *find_adouble(struct path *path, struct ofork **of, struct /* we use file_access both for legacy Mac perm and * for unix privilege, rename will take care of folder perms */ - if (file_access(path, OPENACC_WR ) < 0) { + if (file_access(obj, vol, path, OPENACC_WR ) < 0) { afp_errno = AFPERR_ACCESS; return NULL; } @@ -1931,9 +1954,6 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U uint32_t sid, did; uint16_t vid; - uid_t uid; - gid_t gid; - *rbuflen = 0; ibuf += 2; @@ -1980,7 +2000,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } ad_init(&ads, vol); - if (!(adsp = find_adouble( path, &s_of, &ads))) { + if (!(adsp = find_adouble(obj, vol, path, &s_of, &ads))) { return afp_errno; } @@ -2013,7 +2033,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } ad_init(&add, vol); - if (!(addp = find_adouble( path, &d_of, &add))) { + if (!(addp = find_adouble(obj, vol, path, &d_of, &add))) { err = afp_errno; goto err_exchangefile; } @@ -2101,13 +2121,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U /* change perms, src gets dest perm and vice versa */ - uid = geteuid(); - gid = getegid(); - if (seteuid(0)) { - LOG(log_error, logtype_afpd, "seteuid failed %s", strerror(errno)); - err = AFP_OK; /* ignore error */ - goto err_temp_to_dest; - } + become_root(); /* * we need to exchange ACL entries as well @@ -2131,10 +2145,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U setfilunixmode(vol, path, srcst.st_mode); setfilowner(vol, srcst.st_uid, srcst.st_gid, path); - if ( setegid(gid) < 0 || seteuid(uid) < 0) { - LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno)); - exit(EXITERR_SYS); - } + unbecome_root(); err = AFP_OK; goto err_exchangefile;