示例#1
0
EXPORT_SYM const char *
hdfs_namenode_invoke(struct hdfs_namenode *n, struct hdfs_object *rpc,
	struct hdfs_rpc_response_future *future)
{
	const char *error = NULL;
	bool nnlocked, needs_kick;
	int64_t msgno;
	struct hdfs_heap_buf hbuf = { 0 };

	needs_kick = false;

	ASSERT(future);
	ASSERT(!future->fu_namenode);

	ASSERT(rpc);
	ASSERT(rpc->ob_type == H_RPC_INVOCATION);

	_lock(&n->nn_lock);
	nnlocked = true;

	ASSERT(n->nn_refs >= 1);
	ASSERT(!n->nn_dead);

	if (n->nn_sock == -1) {
		error = "Not connected";
		goto out;
	}
	if (!n->nn_authed) {
		error = "Not authenticated";
		goto out;
	}

	// Take a number
	msgno = n->nn_msgno;
	n->nn_msgno++;

	future->fu_namenode = _namenode_copyref_unlocked(n);
	_namenode_pending_insert_unlocked(n, msgno, future,
	    _rpc2_slurper_for_rpc(rpc));

	if (!n->nn_recver_started)
		n->nn_recver_started = needs_kick = true;

	_unlock(&n->nn_lock);
	nnlocked = false;

	if (needs_kick) {
		int rc;

		rc = pipe(n->nn_recv_sigpipe);
		ASSERT(rc == 0);
		rc = pthread_create(&n->nn_recv_thr, NULL,
		    _namenode_recv_worker, n);
		ASSERT(rc == 0);
	}

	// Serialize rpc and transmit
	_rpc_invocation_set_msgno(rpc, msgno);
	_rpc_invocation_set_proto(rpc, n->nn_proto);
	_rpc_invocation_set_clientid(rpc, n->nn_client_id);

	hdfs_object_serialize(&hbuf, rpc);

	if (n->nn_sasl_ssf > 0)
		_sasl_encode_inplace(n->nn_sasl_ctx, &hbuf);

	_lock(&n->nn_sendlock);
	error = _write_all(n->nn_sock, hbuf.buf, hbuf.used);
	_unlock(&n->nn_sendlock);

	free(hbuf.buf);

out:
	if (nnlocked)
		_unlock(&n->nn_lock);
	return error;
}
示例#2
0
文件: net.c 项目: rom1v/serval-dna
ssize_t _write_str(int fd, const char *str, struct __sourceloc where)
{
    return _write_all(fd, str, strlen(str), where);
}
示例#3
0
EXPORT_SYM const char *
hdfs_namenode_authenticate_full(struct hdfs_namenode *n, const char *username,
	const char *real_user)
{
	const char *error = NULL;
	struct hdfs_object *header;
	struct hdfs_heap_buf hbuf = { 0 };
	char *inh = NULL, preamble[12];
	size_t preamble_len;

	_lock(&n->nn_lock);
	ASSERT(!n->nn_authed);
	ASSERT(n->nn_sock != -1);

	memset(preamble, 0, sizeof(preamble));
	if (n->nn_proto == HDFS_NN_v1) {
		sprintf(preamble, "hrpc\x04%c",
		    (n->nn_kerb == HDFS_NO_KERB)? 0x50 : 0x51);
		preamble_len = 6;

		header = hdfs_authheader_new_ext(n->nn_proto, username,
		    real_user, HDFS_NO_KERB);
	} else if (n->nn_proto == HDFS_NN_v2) {
		/* HDFSv2 has used both version 7 (2.0.0-2.0.2) and 8 (2.0.3+). */
		sprintf(preamble, "hrpc%c%c", 8 /* XXX Configurable? */,
		    (n->nn_kerb == HDFS_NO_KERB)? 0x50 : 0x51);
		/* There is a zero at the end: */
		preamble_len = 7;

		header = hdfs_authheader_new_ext(n->nn_proto, username,
		    real_user, n->nn_kerb);
	} else if (n->nn_proto == HDFS_NN_v2_2) {
		memcpy(preamble, "hrpc\x09", 5);
		preamble[5] = 0;
		preamble[6] = (n->nn_kerb == HDFS_NO_KERB)? 0 : -33;
		preamble_len = 7;

		header = hdfs_authheader_new_ext(n->nn_proto, username,
		    real_user, n->nn_kerb);
		_authheader_set_clientid(header, n->nn_client_id);
	} else {
		ASSERT(false);
	}

	// Serialize the connection header object (I am speaking ClientProtocol
	// and this is my username)
	hdfs_object_serialize(&hbuf, header);
	hdfs_object_free(header);

	if (n->nn_kerb == HDFS_NO_KERB) {
		// Prefix the header object with the protocol preamble
		hbuf.buf = realloc(hbuf.buf, hbuf.size + preamble_len);
		ASSERT(hbuf.buf);
		memmove(hbuf.buf + preamble_len, hbuf.buf, hbuf.used);
		memcpy(hbuf.buf, preamble, preamble_len);
		hbuf.used += preamble_len;
		hbuf.size += preamble_len;
	} else {
		/*
		 * XXX This is probably totally wrong for HDFSv2+. They start
		 * using protobufs at this point to wrap the SASL packets.
		 *
		 * To be fair, it's probably broken for HDFSv1 too :). I need
		 * to find a kerberized HDFS to test against.
		 */
		int r;
		sasl_interact_t *interactions = NULL;
		const char *out, *mechusing;
		unsigned outlen;
		struct iovec iov[3];
		uint32_t inlen;
		const uint32_t SWITCH_TO_SIMPLE_AUTH = (uint32_t)-1;

		uint8_t in[4], zero[4] = { 0 };

		do {
			r = sasl_client_start(n->nn_sasl_ctx, "GSSAPI",
			    &interactions, &out, &outlen, &mechusing);

			if (r == SASL_INTERACT)
				_sasl_interacts(interactions);
		} while (r == SASL_INTERACT);

		if (r != SASL_CONTINUE) {
			error = sasl_errstring(r, NULL, NULL);
			goto out;
		}

		// Send prefix, first auth token
		_be32enc(in, outlen);
		iov[0].iov_base = preamble;
		iov[0].iov_len = preamble_len;
		iov[1].iov_base = in;
		iov[1].iov_len = 4;
		iov[2].iov_base = __DECONST(void *, out);
		iov[2].iov_len = outlen;

		error = _writev_all(n->nn_sock, iov, 3);
		if (error)
			goto out;

		do {
			// read success / error status
			error = _read_all(n->nn_sock, in, 4);
			if (error)
				goto out;

			if (memcmp(in, zero, 4)) {
				// error. exception will be next on the wire,
				// but let's skip it.
				error = "Got error from server, bailing";
				goto out;
			}

			// read token len
			error = _read_all(n->nn_sock, in, 4);
			if (error)
				goto out;
			inlen = _be32dec(in);

			if (inlen == SWITCH_TO_SIMPLE_AUTH) {
				if (n->nn_kerb == HDFS_REQUIRE_KERB) {
					error = "Server tried to drop kerberos but "
					    "client requires it";
					goto out;
				}
				goto send_header;
			}

			// read token
			if (inh)
				free(inh);
			inh = NULL;
			if (inlen > 0) {
				inh = malloc(inlen);
				ASSERT(inh);
				error = _read_all(n->nn_sock, inh, inlen);
				if (error)
					goto out;
			}

			out = NULL;
			outlen = 0;
			r = sasl_client_step(n->nn_sasl_ctx, inh,
			    inlen, &interactions, &out, &outlen);

			if (r == SASL_INTERACT)
				_sasl_interacts(interactions);

			if (r == SASL_CONTINUE ||
			    (r == SASL_OK && out != NULL)) {
				_be32enc(in, outlen);
				iov[0].iov_base = in;
				iov[0].iov_len = 4;
				iov[1].iov_base = __DECONST(void *, out);
				iov[1].iov_len = outlen;

				error = _writev_all(n->nn_sock, iov, 2);
				if (error)
					goto out;
			}
		} while (r == SASL_INTERACT || r == SASL_CONTINUE);

		if (r != SASL_OK) {
			error = sasl_errstring(r, NULL, NULL);
			goto out;
		}

		// sasl connection established
		n->nn_sasl_ssf = _getssf(n->nn_sasl_ctx);
send_header:
		if (n->nn_sasl_ssf > 0)
			_sasl_encode_inplace(n->nn_sasl_ctx, &hbuf);
	}

	// send auth header
	error = _write_all(n->nn_sock, hbuf.buf, hbuf.used);
	n->nn_authed = true;

out:
	if (inh)
		free(inh);
	_unlock(&n->nn_lock);
	free(hbuf.buf);

	return error;
}