Ejemplo n.º 1
0
int open64(const char *path, int flags, ...) {
    char *rpath, *strflags=str_flags(flags);
    va_list argptr;
    mode_t mode;
    int found;

    // If O_CREAT then mode is not set.
    if (flags & O_CREAT) {
        va_start(argptr, flags);
        mode=va_arg(argptr, mode_t);
        va_end(argptr);
    } else {
        mode=0;
    }

    sb_log(2, "Start open64(\"%s\", %s, %04o).", path, strflags, mode);
    rpath=rewrite(path, R_FILE);
    if ((found=has_access(rpath)) || ! (flags & (O_WRONLY|O_RDWR))) {
        // Disable O_CREAT when O_RDONLY
        if (!found) {
            flags&=~O_CREAT;
            strflags=str_flags(flags);
        }
        sb_log(4, "Do open64(\"%s\", %s, %04o).", path, strflags, mode);
        return _real_open64(path, flags, mode);
    }
    if (action==A_HALT) exit(0);
    sb_log(0, "Attempt to open64(\"%s\", %s, %04o).", rpath, strflags, mode);
    free(rpath);
    free(strflags);
    if (action==A_WARN) return devnull;
    errno=EACCES;
    return -1;
}
Ejemplo n.º 2
0
int rename(const char *oldpath, const char *newpath) {
    char *oldrpath, *newrpath;
    sb_log(2, "Start rename(\"%s\", \"%s\").", oldpath, newpath);
    oldrpath=rewrite(oldpath, R_LINK);
    newrpath=rewrite(newpath, R_FILE);
    if (has_access(oldrpath) && has_access(newrpath)) {
        sb_log(4, "Do rename(\"%s\", \"%s\").", oldpath, newpath);
        return _real_rename(oldpath, newpath);
    }
    if (action==A_HALT) exit(0);
    sb_log(0, "Attempt to rename(\"%s\", \"%s\").", oldrpath, newrpath);
    free(oldrpath);
    free(newrpath);
    if (action==A_WARN) return 0;
    errno=EACCES;
    return -1;
}
Ejemplo n.º 3
0
int utimes(const char *path, const struct timeval *tvp) {
    char *rpath;
    sb_log(2, "Start utimes(\"%s\", NULL).", path);
    rpath=rewrite(path, R_FILE);
    if (has_access(rpath)) {
        sb_log(4, "Do utimes(\"%s\", NULL).", path);
        return _real_utimes(path, tvp);
    }
    if (action==A_HALT) exit(0);
    sb_log(0, "Attempt to utimes(\"%s\", NULL).", rpath);
    free(rpath);
    if (action==A_WARN) return 0;
    errno=EACCES;
    return -1;
}
Ejemplo n.º 4
0
int unlink(const char *path) {
    char *rpath;
    sb_log(2, "Start unlink(\"%s\").", path);
    rpath=rewrite(path, R_LINK);
    if (has_access(rpath)) {
        sb_log(4, "Do unlink(\"%s\").", path);
        return _real_unlink(path);
    }
    if (action==A_HALT) exit(0);
    sb_log(0, "Attempt to unlink(\"%s\").", rpath);
    free(rpath);
    if (action==A_WARN) return 0;
    errno=EACCES;
    return -1;
}
Ejemplo n.º 5
0
int creat64(const char *path, mode_t mode) {
    char *rpath;
    sb_log(2, "Start creat64(\"%s\", %04o).", path, mode);
    rpath=rewrite(path, R_FILE);
    if (has_access(rpath)) {
        sb_log(4, "Do creat64(\"%s\", %04o).", path, mode);
        return _real_creat64(path, mode);
    }
    if (action==A_HALT) exit(0);
    sb_log(0, "Attempt to creat64(\"%s\", %04o).", rpath, mode);
    free(rpath);
    if (action==A_WARN) return devnull;
    errno=EACCES;
    return -1;
}
Ejemplo n.º 6
0
int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev) {
    char *rpath;
    sb_log(2, "Start __xmknod(%i, \"%s\", %04o).", ver, path, mode);
    rpath=rewrite(path, R_LINK);
    if (has_access(rpath)) {
        sb_log(4, "Do __xmknod(%i, \"%s\", %04o).", ver, path, mode);
        return _real___xmknod(ver, path, mode, dev);
    }
    if (action==A_HALT) exit(0);
    sb_log(0, "Attempt to __xmknod(%i, \"%s\", %04o).", ver, rpath, mode);
    free(rpath);
    if (action==A_WARN) return 0;
    errno=EACCES;
    return -1;
}
Ejemplo n.º 7
0
int lchown(const char *path, uid_t owner, gid_t group) {
    char *rpath;
    sb_log(2, "Start lchown(\"%s\", %i, %i).", path, owner, group);
    rpath=rewrite(path, R_LINK);
    if (has_access(rpath)) {
        sb_log(4, "Do lchown(\"%s\", %i, %i).", path, owner, group);
        return _real_lchown(path, owner, group);
    }
    if (action==A_HALT) exit(0);
    sb_log(0, "Attempt to lchown(\"%s\", %i, %i).", rpath, owner, group);
    free(rpath);
    if (action==A_WARN) return 0;
    errno=EACCES;
    return -1;
}
Ejemplo n.º 8
0
int symlink(const char *oldpath, const char *newpath) {
//	char *oldrpath;
    char *newrpath;
    sb_log(2, "Start symlink(\"%s\", \"%s\").", oldpath, newpath);
//	oldrpath=rewrite(oldpath, R_FILE);
    newrpath=rewrite(newpath, R_LINK);
    if (has_access(newrpath)) {
        sb_log(4, "Do symlink(\"%s\", \"%s\").", oldpath, newpath);
        return _real_symlink(oldpath, newpath);
    }
    if (action==A_HALT) exit(0);
    sb_log(0, "Attempt to symlink(\"%s\", \"%s\").", oldpath, newrpath);
    free(newrpath);
    if (action==A_WARN) return 0;
    errno=EACCES;
    return -1;
}
Ejemplo n.º 9
0
static bool bucket_list_keys(struct client *cli, const char *user,
			     const char *bucket)
{
	GHashTable *param;
	enum errcode err = InternalError;
	char *prefix, *marker, *maxkeys_str, *delim, *s;
	int maxkeys = 100, i, rc;
	GList *content, *tmpl;
	size_t pfx_len;
	struct bucket_list_info bli;
	bool rcb;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB_TXN *txn = NULL;
	DB *objs = tdbrep.tdb.objs;
	DBC *cur = NULL;
	DBT pkey, pval;
	struct db_obj_key *obj_key;
	size_t alloc_len;
	bool seen_prefix = false;
	int get_flags;

	/* verify READ access */
	if (!user || !has_access(user, bucket, NULL, "READ")) {
		err = AccessDenied;
		goto err_out;
	}

	/* parse URI query string */
	param = hreq_query(&cli->req);
	if (!param)
		goto err_out;

	/* read useful params from query string */
	prefix = g_hash_table_lookup(param, "prefix");
	pfx_len = prefix ? strlen(prefix) : 0;

	marker = g_hash_table_lookup(param, "marker");
	delim = g_hash_table_lookup(param, "delimiter");
	maxkeys_str = g_hash_table_lookup(param, "max-keys");
	if (maxkeys_str) {
		i = atoi(maxkeys_str);
		if (i > 0 && i < maxkeys)
			maxkeys = i;
	}

	/* open transaction */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_out;
	}

	/* search for (bucket, *) in object database, to see if
	 * any objects associated with this bucket exist
	 */
	rc = objs->cursor(objs, txn, &cur, 0);
	if (rc) {
		objs->err(objs, rc, "objs->cursor");
		goto err_out;
	}

	alloc_len = sizeof(*obj_key) +
		    (marker ? strlen(marker) : pfx_len) + 1;
	obj_key = alloca(alloc_len);

	memset(obj_key, 0, alloc_len);
	strncpy(obj_key->bucket, bucket, sizeof(obj_key->bucket));
	strcpy(obj_key->key, marker ? marker : prefix ? prefix : "");

	memset(&pkey, 0, sizeof(pkey));
	pkey.data = obj_key;
	pkey.size = alloc_len;

	memset(&bli, 0, sizeof(bli));
	bli.prefix = prefix;
	bli.pfx_len = pfx_len;
	bli.delim = delim;
	bli.common_pfx = g_hash_table_new_full(g_str_hash, g_str_equal,
					       free, NULL);
	bli.maxkeys = maxkeys;

	/* iterate through each returned data row */
	get_flags = DB_SET_RANGE;
	while (1) {
		struct obj_vitals v;
		struct db_obj_key *tmpkey;
		struct db_obj_ent *obj;

		memset(&pval, 0, sizeof(pval));
		pval.flags = DB_DBT_MALLOC;

		rc = cur->get(cur, &pkey, &pval, get_flags);
		if (rc) {
			if (rc != DB_NOTFOUND)
				objs->err(objs, rc, "bucket_list_keys iter");
			break;
		}

		get_flags = DB_NEXT;

		tmpkey = pkey.data;
		obj = pval.data;

		if (strcmp(tmpkey->bucket, bucket)) {
			free(obj);
			break;
		}
		if (prefix) {
			if (strncmp(tmpkey->key, prefix, pfx_len) != 0) {
				free(obj);
				if (!seen_prefix)
					/* continue searching for
					 * a record that begins with this
					 * prefix
					 */
					continue;
				else
					/* no more records with our prefix */
					break;
			}

			seen_prefix = true;
		}

		memset(&v, 0, sizeof(v));
		strcpy(v.md5, obj->md5);
		strncpy(v.owner, obj->owner, sizeof(v.owner)-1);
		if (!(GUINT32_FROM_LE(obj->flags) & DB_OBJ_INLINE))
			memcpy(&v.addr, &obj->d.a, sizeof(v.addr));
		v.mtime = GUINT64_FROM_LE(obj->mtime);
		v.size = GUINT64_FROM_LE(obj->size);
		free(obj);

		if (bucket_list_iter(tmpkey->key, &v, &bli))
			break;
	}

	/* close cursor, transaction */
	rc = cur->close(cur);
	if (rc) {
		objs->err(objs, rc, "objs->cursor close");
		goto err_out_rb;
	}

	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		goto err_out_param;
	}

	s = g_markup_printf_escaped(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
"<ListBucketResult xmlns=\"http://indy.yyz.us/doc/2006-03-01/\">\r\n"
"  <Name>%s</Name>\r\n"
"  <MaxKeys>%d</MaxKeys>\r\n"
"  <IsTruncated>%s</IsTruncated>\r\n",

		 bucket,
		 maxkeys,
		 bli.trunc ? "true" : "false");

	content = g_list_append(NULL, s);

	if (prefix) {
		s = g_markup_printf_escaped("  <Prefix>%s</Prefix>\n", prefix);
		content = g_list_append(content, s);
	}
	if (marker) {
		s = g_markup_printf_escaped("  <Marker>%s</Marker>\n", marker);
		content = g_list_append(content, s);
	}

	tmpl = bli.res;
	while (tmpl) {
		char timestr[64];
		struct obj_vitals *vp;

		vp = tmpl->data;
		tmpl = tmpl->next;

		/*
		 * FIXME Use the vp->addr to verify that key still exists.
		 * And if it doesn't, then what? (addr.nid can be 0 for inline)
		 */

		s = g_markup_printf_escaped(
                         "  <Contents>\r\n"
                         "    <Key>%s</Key>\r\n"
                         "    <LastModified>%s</LastModified>\r\n"
                         "    <ETag>%s</ETag>\r\n"
                         "    <Size>%llu</Size>\r\n"
                         "    <StorageClass>STANDARD</StorageClass>\r\n"
                         "    <Owner>\r\n"
                         "      <ID>%s</ID>\r\n"
                         "      <DisplayName>%s</DisplayName>\r\n"
                         "    </Owner>\r\n"
                         "  </Contents>\r\n",

			 vp->key,
			 hutil_time2str(timestr, sizeof(timestr), vp->mtime / 1000000),
			 vp->md5,
			 (unsigned long long) vp->size,
			 vp->owner,
			 vp->owner);

		content = g_list_append(content, s);

		free(vp->key);
		free(vp);
	}

	g_list_free(bli.res);

	content = bucket_list_pfx(content, bli.common_pfx, bli.delim);

	s = strdup("</ListBucketResult>\r\n");
	content = g_list_append(content, s);

	free(bli.last_comp);
	g_hash_table_destroy(bli.common_pfx);
	g_hash_table_destroy(param);

	rcb = cli_resp_xml(cli, 200, content);

	g_list_free(content);

	return rcb;

err_out_rb:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
err_out_param:
	g_hash_table_destroy(param);
err_out:
	return cli_err(cli, err);
}
Ejemplo n.º 10
0
bool bucket_add(struct client *cli, const char *user, const char *bucket)
{
	char *hdr, timestr[64];
	enum errcode err = InternalError;
	int rc;
	struct db_bucket_ent ent;
	bool setacl;			/* is ok to put pre-existing bucket */
	enum ReqACLC canacl;
	DB *buckets = tdbrep.tdb.buckets;
	DB *acls = tdbrep.tdb.acls;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB_TXN *txn = NULL;
	DBT key, val;

	if (!user)
		return cli_err(cli, AccessDenied);

	/* prepare parameters */
	setacl = false;
	if (cli->req.uri.query_len) {
		switch (hreq_is_query(&cli->req)) {
		case URIQ_ACL:
			setacl = true;
			break;
		default:
			err = InvalidURI;
			goto err_par;
		}
	}

	if ((rc = hreq_acl_canned(&cli->req)) == ACLCNUM) {
		err = InvalidArgument;
		goto err_par;
	}
	canacl = (rc == -1)? ACLC_PRIV: rc;

	/* begin trans */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_db;
	}

	memset(&key, 0, sizeof(key));
	memset(&val, 0, sizeof(val));
	memset(&ent, 0, sizeof(ent));
	strncpy(ent.name, bucket, sizeof(ent.name));
	strncpy(ent.owner, user, sizeof(ent.owner));
	ent.time_create = GUINT64_TO_LE(time(NULL));

	key.data = &ent.name;
	key.size = strlen(ent.name) + 1;

	val.data = &ent;
	val.size = sizeof(ent);

	if (setacl) {
		/* check if the bucket exists, else insert it */
		rc = bucket_find(txn, bucket, NULL, 0);
		if (rc) {
			if (rc != DB_NOTFOUND) {
				buckets->err(buckets, rc, "buckets->find");
				goto err_out;
			}

			rc = buckets->put(buckets, txn, &key, &val,
							DB_NOOVERWRITE);
			if (rc) {
				buckets->err(buckets, rc, "buckets->put");
				goto err_out;
			}
		} else {
			if (!has_access(user, bucket, NULL, "WRITE_ACP")) {
				err = AccessDenied;
				goto err_out;
			}
			if (!object_del_acls(txn, bucket, ""))
				goto err_out;
		}

	} else {
		/* attempt to insert new bucket */
		rc = buckets->put(buckets, txn, &key, &val, DB_NOOVERWRITE);
		if (rc) {
			if (rc == DB_KEYEXIST)
				err = BucketAlreadyExists;
			else
				buckets->err(buckets, rc, "buckets->put");
			goto err_out;
		}
	}

	/* insert bucket ACL */
	rc = add_access_canned(txn, bucket, "", user, canacl);
	if (rc) {
		acls->err(acls, rc, "acls->put");
		goto err_out;
	}

	/* commit -- no more exception emulation with goto. */
	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		return cli_err(cli, InternalError);
	}

	if (asprintf(&hdr,
"HTTP/%d.%d 200 x\r\n"
"Content-Length: 0\r\n"
"Date: %s\r\n"
"Location: /%s\r\n"
"Server: " PACKAGE_STRING "\r\n"
"\r\n",
		     cli->req.major,
		     cli->req.minor,
		     hutil_time2str(timestr, sizeof(timestr), time(NULL)),
		     bucket) < 0)
		return cli_err(cli, InternalError);

	rc = atcp_writeq(&cli->wst, hdr, strlen(hdr), atcp_cb_free, hdr);
	if (rc) {
		free(hdr);
		return true;
	}

	return atcp_write_start(&cli->wst);

err_out:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
err_db:
err_par:
	return cli_err(cli, err);
}
Ejemplo n.º 11
0
bool access_list(struct client *cli, const char *bucket, const char *key,
		 const char *user)
{
	struct macl {
		char		perm[128];		/* perm(s) granted */
		char		grantee[64];		/* grantee user */
	};

	GHashTable *param;
	enum errcode err = InternalError;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB *acls = tdbrep.tdb.acls;
	int alloc_len;
	char owner[64];
	GList *res;
	struct db_acl_key *acl_key;
	struct db_acl_ent *acl;
	DB_TXN *txn = NULL;
	DBC *cur = NULL;
	GList *content;
	DBT pkey, pval;
	struct macl *mp;
	char guser[64];
	GList *p;
	char *s;
	int str_len;
	int rc;
	bool rcb;

	/* verify READ access for ACL */
	if (!user || !has_access(user, bucket, key, "READ_ACP")) {
		err = AccessDenied;
		goto err_out;
	}

	/* parse URI query string */
	param = hreq_query(&cli->req);
	if (!param)
		goto err_out;

	res = NULL;

	alloc_len = sizeof(struct db_acl_key) + strlen(key) + 1;
	acl_key = alloca(alloc_len);
	memset(acl_key, 0, alloc_len);

	strncpy(acl_key->bucket, bucket, sizeof(acl_key->bucket));
	strcpy(acl_key->key, key);

	/* open transaction, search cursor */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_out_param;
	}

	rc = bucket_find(txn, bucket, &owner[0], sizeof(owner));
	if (rc) {
		if (rc == DB_NOTFOUND)
			err = InvalidBucketName;
		else
			dbenv->err(dbenv, rc, "bucket_find");
		goto err_out_rb;
	}

	rc = acls->cursor(acls, txn, &cur, 0);
	if (rc) {
		acls->err(acls, rc, "acls->cursor");
		goto err_out_rb;
	}

	memset(&pkey, 0, sizeof(pkey));
	pkey.data = acl_key;
	pkey.size = alloc_len;

	for (;; free(acl)) {

		memset(&pval, 0, sizeof(pval));
		pval.flags = DB_DBT_MALLOC;

		rc = cur->get(cur, &pkey, &pval, DB_NEXT);
		if (rc)
			break;

		acl = pval.data;

		/* This is a workaround, see FIXME about DB_NEXT. */
		if (strncmp(acl->bucket, bucket, sizeof(acl->bucket)))
			continue;
		if (strcmp(acl->key, key))
			continue;

		if ((mp = malloc(sizeof(struct macl))) == NULL) {
			free(acl);
			cur->close(cur);
			goto err_out_rb;
		}

		memcpy(mp->grantee, acl->grantee, sizeof(mp->grantee));
		mp->grantee[sizeof(mp->grantee)-1] = 0;

		memcpy(mp->perm, acl->perm, sizeof(mp->perm));

		/* lop off the trailing comma */
		mp->perm[sizeof(mp->perm)-1] = 0;
		str_len = strlen(mp->perm);
		if (str_len && mp->perm[str_len-1] == ',')
			mp->perm[--str_len] = 0;

		res = g_list_append(res, mp);
	}

	if (rc != DB_NOTFOUND)
		acls->err(acls, rc, "access_list iteration");

	/* close cursor, transaction */
	rc = cur->close(cur);
	if (rc)
		acls->err(acls, rc, "acls->cursor close");
	rc = txn->commit(txn, 0);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");

	/* dump collected acls -- no more exception handling */

	s = g_markup_printf_escaped(
		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
		"<AccessControlPolicy "
		     "xmlns=\"http://indy.yyz.us/doc/2006-03-01/\">\r\n"
		"  <Owner>\r\n"
		"    <ID>%s</ID>\r\n"
		"    <DisplayName>%s</DisplayName>\r\n"
		"  </Owner>\r\n",
		owner, owner);
	content = g_list_append(NULL, s);

	s = g_markup_printf_escaped(
		"  <AccessControlList>\r\n");
	content = g_list_append(content, s);

	for (p = res; p != NULL; p = p->next) {
		mp = p->data;

		if (!strcmp(DB_ACL_ANON, mp->grantee)) {
			strcpy(guser, "anonymous");
		} else {
			strncpy(guser, mp->grantee, sizeof(guser));
			guser[sizeof(guser)-1] = 0;
		}

		s = g_markup_printf_escaped(
			"    <Grant>\r\n"
			"      <Grantee xmlns:xsi=\"http://www.w3.org/2001/"
			"XMLSchema-instance\" xsi:type=\"CanonicalUser\">\r\n"
			"        <ID>%s</ID>\r\n"
			"        <DisplayName>%s</DisplayName>\r\n"
			"      </Grantee>\r\n",
			guser, guser);
		content = g_list_append(content, s);

		/*
		 * FIXME This parsing is totally lame, we should replace
		 * strings with a bit mask once we make sure this works.
		 */
		if (!strcmp(mp->perm, "READ,WRITE,READ_ACP,WRITE_ACP")) {
			s = g_markup_printf_escaped(
			   "      <Permission>FULL_CONTROL</Permission>\r\n");
		} else {
			s = g_markup_printf_escaped(
			   "      <Permission>%s</Permission>\r\n",
			   mp->perm);
		}
		content = g_list_append(content, s);

		s = g_markup_printf_escaped("    </Grant>\r\n");
		content = g_list_append(content, s);

		free(mp);
	}

	s = g_markup_printf_escaped("  </AccessControlList>\r\n");
	content = g_list_append(content, s);

	s = g_markup_printf_escaped("</AccessControlPolicy>\r\n");
	content = g_list_append(content, s);

	g_list_free(res);

	rcb = cli_resp_xml(cli, 200, content);
	g_list_free(content);
	return rcb;

err_out_rb:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	for (p = res; p != NULL; p = p->next)
		free(p->data);
	g_list_free(res);
err_out_param:
	g_hash_table_destroy(param);
err_out:
	return cli_err(cli, err);
}