Пример #1
0
void unbecome_root(void)
{
    if (getuid() == 0) {
        if (saved_uid == -1 || seteuid(saved_uid) < 0)
            AFP_PANIC("Can't seteuid back");
        saved_uid = -1;
    }
}
Пример #2
0
/*
 * seteuid(0) and back, if either fails and panic != 0 we PANIC
 */
void become_root(void)
{
    if (getuid() == 0) {
        saved_uid = geteuid();
        if (seteuid(0) != 0)
            AFP_PANIC("Can't seteuid(0)");
    }
}
Пример #3
0
static void dsi_init_buffer(DSI *dsi)
{
    /* default is 12 * 300k = 3,6 MB (Apr 2011) */
    if ((dsi->buffer = malloc(dsi->dsireadbuf * dsi->server_quantum)) == NULL) {
        LOG(log_error, logtype_dsi, "dsi_init_buffer: OOM");
        AFP_PANIC("OOM in dsi_init_buffer");
    }
    dsi->start = dsi->buffer;
    dsi->eof = dsi->buffer;
    dsi->end = dsi->buffer + (dsi->dsireadbuf * dsi->server_quantum);
}
Пример #4
0
/* OpenSession. set up the connection */
void dsi_opensession(DSI *dsi)
{
  u_int32_t i = 0; /* this serves double duty. it must be 4-bytes long */
  int offs;

  dsi_init_buffer(dsi);
  if (setnonblock(dsi->socket, 1) < 0) {
      LOG(log_error, logtype_dsi, "dsi_opensession: setnonblock: %s", strerror(errno));
      AFP_PANIC("setnonblock error");
  }

  /* parse options */
  while (i < dsi->cmdlen) {
    switch (dsi->commands[i++]) {
    case DSIOPT_ATTNQUANT:
      memcpy(&dsi->attn_quantum, dsi->commands + i + 1, dsi->commands[i]);
      dsi->attn_quantum = ntohl(dsi->attn_quantum);

    case DSIOPT_SERVQUANT: /* just ignore these */
    default:
      i += dsi->commands[i] + 1; /* forward past length tag + length */
      break;
    }
  }

  /* let the client know the server quantum. we don't use the
   * max server quantum due to a bug in appleshare client 3.8.6. */
  dsi->header.dsi_flags = DSIFL_REPLY;
  dsi->header.dsi_code = 0;
  /* dsi->header.dsi_command = DSIFUNC_OPEN;*/

  dsi->cmdlen = 2 * (2 + sizeof(i)); /* length of data. dsi_send uses it. */

  /* DSI Option Server Request Quantum */
  dsi->commands[0] = DSIOPT_SERVQUANT;
  dsi->commands[1] = sizeof(i);
  i = htonl(( dsi->server_quantum < DSI_SERVQUANT_MIN || 
	      dsi->server_quantum > DSI_SERVQUANT_MAX ) ? 
	    DSI_SERVQUANT_DEF : dsi->server_quantum);
  memcpy(dsi->commands + 2, &i, sizeof(i));

  /* AFP replaycache size option */
  offs = 2 + sizeof(i);
  dsi->commands[offs] = DSIOPT_REPLCSIZE;
  dsi->commands[offs+1] = sizeof(i);
  i = htonl(REPLAYCACHE_SIZE);
  memcpy(dsi->commands + offs + 2, &i, sizeof(i));
  dsi_send(dsi);
}
Пример #5
0
int ad_lock(struct adouble *ad, uint32_t eid, int locktype, off_t off, off_t len, int fork)
{
    struct flock lock;
    struct ad_fd *adf;
    adf_lock_t *adflock;
    int oldlock;
    int i;
    int type;
    int ret = 0, fcntl_lock_err = 0;

    LOG(log_debug, logtype_default, "ad_lock(%s, %s, off: %jd (%s), len: %jd): BEGIN",
        eid == ADEID_DFORK ? "data" : "reso",
        locktypetostr(locktype),
        (intmax_t)off,
        shmdstrfromoff(off),
        (intmax_t)len);

    if ((locktype & ADLOCK_FILELOCK) && (len != 1))
        AFP_PANIC("lock API error");

    type = locktype;

    if (eid == ADEID_DFORK) {
        adf = &ad->ad_data_fork;
        lock.l_start = off;
    } else { /* rfork */
        if (type & ADLOCK_FILELOCK) {
            adf = &ad->ad_data_fork;
            lock.l_start = rf2off(off);
        } else {
            adf = ad->ad_rfp;
            lock.l_start = off + ad_getentryoff(ad, ADEID_RFORK);
        }
    }

    /* NOTE: we can't write lock a read-only file. on those, we just
     * make sure that we have a read lock set. that way, we at least prevent
     * someone else from really setting a deny read/write on the file.
     */
    if (!(adf->adf_flags & O_RDWR) && (type & ADLOCK_WR)) {
        type = (type & ~ADLOCK_WR) | ADLOCK_RD;
    }

    lock.l_type = XLATE_FCNTL_LOCK(type & ADLOCK_MASK);
    lock.l_whence = SEEK_SET;
    lock.l_len = len;

    /* byte_lock(len=-1) lock whole file */
    if (len == BYTELOCK_MAX) {
        lock.l_len -= lock.l_start; /* otherwise  EOVERFLOW error */
    }

    /* see if it's locked by another fork.
     * NOTE: this guarantees that any existing locks must be at most
     * read locks. we use ADLOCK_WR/RD because F_RD/WRLCK aren't
     * guaranteed to be ORable. */
    if (adf_findxlock(adf, fork, ADLOCK_WR |
                      ((type & ADLOCK_WR) ? ADLOCK_RD : 0),
                      lock.l_start, lock.l_len) > -1) {
        errno = EACCES;
        ret = -1;
        goto exit;
    }

    /* look for any existing lock that we may have */
    i = adf_findlock(adf, fork, ADLOCK_RD | ADLOCK_WR, lock.l_start, lock.l_len);
    adflock = (i < 0) ? NULL : adf->adf_lock + i;

    /* here's what we check for:
       1) we're trying to re-lock a lock, but we didn't specify an update.
       2) we're trying to free only part of a lock.
       3) we're trying to free a non-existent lock. */
    if ( (!adflock && (lock.l_type == F_UNLCK))
            ||
            (adflock
             && !(type & ADLOCK_UPGRADE)
             && ((lock.l_type != F_UNLCK)
                 || (adflock->lock.l_start != lock.l_start)
                 || (adflock->lock.l_len != lock.l_len) ))
       ) {
        errno = EINVAL;
        ret = -1;
        goto exit;
    }


    /* now, update our list of locks */
    /* clear the lock */
    if (lock.l_type == F_UNLCK) {
        adf_freelock(adf, i);
        goto exit;
    }

    /* attempt to lock the file. */
    if (set_lock(adf->adf_fd, F_SETLK, &lock) < 0) {
        ret = -1;
        goto exit;
    }

    /* we upgraded this lock. */
    if (adflock && (type & ADLOCK_UPGRADE)) {
        memcpy(&adflock->lock, &lock, sizeof(lock));
        goto exit;
    }

    /* it wasn't an upgrade */
    oldlock = -1;
    if (lock.l_type == F_RDLCK) {
        oldlock = adf_findxlock(adf, fork, ADLOCK_RD, lock.l_start, lock.l_len);
    }

    /* no more space. this will also happen if lockmax == lockcount == 0 */
    if (adf->adf_lockmax == adf->adf_lockcount) {
        adf_lock_t *tmp = (adf_lock_t *)
                          realloc(adf->adf_lock, sizeof(adf_lock_t)*
                                  (adf->adf_lockmax + ARRAY_BLOCK_SIZE));
        if (!tmp) {
            ret = fcntl_lock_err = -1;
            goto exit;
        }
        adf->adf_lock = tmp;
        adf->adf_lockmax += ARRAY_BLOCK_SIZE;
    }
    adflock = adf->adf_lock + adf->adf_lockcount;

    /* fill in fields */
    memcpy(&adflock->lock, &lock, sizeof(lock));
    adflock->user = fork;
    if (oldlock > -1) {
        adflock->refcount = (adf->adf_lock + oldlock)->refcount;
    } else if ((adflock->refcount = calloc(1, sizeof(int))) == NULL) {
        ret = fcntl_lock_err = 1;
        goto exit;
    }

    (*adflock->refcount)++;
    adf->adf_lockcount++;

exit:
    if (ret != 0) {
        if (fcntl_lock_err != 0) {
            lock.l_type = F_UNLCK;
            set_lock(adf->adf_fd, F_SETLK, &lock);
        }
    }
    LOG(log_debug, logtype_default, "ad_lock: END: %d", ret);
    return ret;
}