示例#1
0
static void wbsrv_accept(struct stream_connection *conn)
{
	struct wbsrv_listen_socket *listen_socket = talloc_get_type(conn->private_data,
								    struct wbsrv_listen_socket);
	struct wbsrv_connection *wbconn;

	wbconn = talloc_zero(conn, struct wbsrv_connection);
	if (!wbconn) {
		stream_terminate_connection(conn, "wbsrv_accept: out of memory");
		return;
	}
	wbconn->conn	      = conn;
	wbconn->listen_socket = listen_socket;
	wbconn->lp_ctx        = listen_socket->service->task->lp_ctx;
	conn->private_data    = wbconn;

	wbconn->packet = packet_init(wbconn);
	if (wbconn->packet == NULL) {
		wbsrv_terminate_connection(wbconn, "wbsrv_accept: out of memory");
		return;
	}
	packet_set_private(wbconn->packet, wbconn);
	packet_set_socket(wbconn->packet, conn->socket);
	packet_set_callback(wbconn->packet, wbsrv_samba3_process);
	packet_set_full_request(wbconn->packet, wbsrv_samba3_packet_full_request);
	packet_set_error_handler(wbconn->packet, wbsrv_recv_error);
	packet_set_event_context(wbconn->packet, conn->event.ctx);
	packet_set_fde(wbconn->packet, conn->event.fde);
	packet_set_serialise(wbconn->packet);
}
示例#2
0
/*
  create a transport structure based on an established socket
*/
struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock,
					       TALLOC_CTX *parent_ctx, 
					       bool primary, 
					       struct smbcli_options *options)
{
	struct smbcli_transport *transport;

	transport = talloc_zero(parent_ctx, struct smbcli_transport);
	if (!transport) return NULL;

	if (primary) {
		transport->socket = talloc_steal(transport, sock);
	} else {
		transport->socket = talloc_reference(transport, sock);
	}
	transport->negotiate.protocol = PROTOCOL_NT1;
	transport->options = *options;
	transport->negotiate.max_xmit = transport->options.max_xmit;

	/* setup the stream -> packet parser */
	transport->packet = packet_init(transport);
	if (transport->packet == NULL) {
		talloc_free(transport);
		return NULL;
	}
	packet_set_private(transport->packet, transport);
	packet_set_socket(transport->packet, transport->socket->sock);
	packet_set_callback(transport->packet, smbcli_transport_finish_recv);
	packet_set_full_request(transport->packet, packet_full_request_nbt);
	packet_set_error_handler(transport->packet, smbcli_transport_error);
	packet_set_event_context(transport->packet, transport->socket->event.ctx);
	packet_set_nofree(transport->packet);
	packet_set_initial_read(transport->packet, 4);

	smbcli_init_signing(transport);

	ZERO_STRUCT(transport->called);

	/* take over event handling from the socket layer - it only
	   handles events up until we are connected */
	talloc_free(transport->socket->event.fde);
	transport->socket->event.fde = event_add_fd(transport->socket->event.ctx,
						    transport->socket->sock,
						    socket_get_fd(transport->socket->sock),
						    EVENT_FD_READ,
						    smbcli_transport_event_handler,
						    transport);

	packet_set_fde(transport->packet, transport->socket->event.fde);
	packet_set_serialise(transport->packet);
	talloc_set_destructor(transport, transport_destructor);

	return transport;
}
示例#3
0
文件: winsrepl.c 项目: gojdic/samba
/*
  initialise a wrepl_socket from an already existing connection
*/
struct wrepl_socket *wrepl_socket_merge(TALLOC_CTX *mem_ctx,
                                        struct tevent_context *event_ctx,
                                        struct socket_context *sock,
                                        struct packet_context *pack)
{
    struct wrepl_socket *wrepl_socket;

    wrepl_socket = talloc_zero(mem_ctx, struct wrepl_socket);
    if (wrepl_socket == NULL) goto failed;

    wrepl_socket->event.ctx = talloc_reference(wrepl_socket, event_ctx);
    if (wrepl_socket->event.ctx == NULL) goto failed;

    wrepl_socket->sock = sock;
    talloc_steal(wrepl_socket, wrepl_socket->sock);


    wrepl_socket->request_timeout	= WREPL_SOCKET_REQUEST_TIMEOUT;

    wrepl_socket->event.fde = event_add_fd(wrepl_socket->event.ctx, wrepl_socket,
                                           socket_get_fd(wrepl_socket->sock),
                                           EVENT_FD_READ,
                                           wrepl_handler, wrepl_socket);
    if (wrepl_socket->event.fde == NULL) {
        goto failed;
    }

    wrepl_socket->packet = pack;
    talloc_steal(wrepl_socket, wrepl_socket->packet);
    packet_set_private(wrepl_socket->packet, wrepl_socket);
    packet_set_socket(wrepl_socket->packet, wrepl_socket->sock);
    packet_set_callback(wrepl_socket->packet, wrepl_finish_recv);
    packet_set_full_request(wrepl_socket->packet, packet_full_request_u32);
    packet_set_error_handler(wrepl_socket->packet, wrepl_error);
    packet_set_event_context(wrepl_socket->packet, wrepl_socket->event.ctx);
    packet_set_fde(wrepl_socket->packet, wrepl_socket->event.fde);
    packet_set_serialise(wrepl_socket->packet);

    talloc_set_destructor(wrepl_socket, wrepl_socket_destructor);

    return wrepl_socket;

failed:
    talloc_free(wrepl_socket);
    return NULL;
}
示例#4
0
文件: socket.c 项目: AIdrifter/samba
NTSTATUS gensec_socket_init(struct gensec_security *gensec_security,
			    TALLOC_CTX *mem_ctx,
			    struct socket_context *current_socket,
			    struct tevent_context *ev,
			    void (*recv_handler)(void *, uint16_t),
			    void *recv_private,
			    struct socket_context **new_socket)
{
	struct gensec_socket *gensec_socket;
	struct socket_context *new_sock;
	NTSTATUS nt_status;

	nt_status = socket_create_with_ops(mem_ctx, &gensec_socket_ops, &new_sock, 
					   SOCKET_TYPE_STREAM, current_socket->flags | SOCKET_FLAG_ENCRYPT);
	if (!NT_STATUS_IS_OK(nt_status)) {
		*new_socket = NULL;
		return nt_status;
	}

	new_sock->state = current_socket->state;

	gensec_socket = talloc(new_sock, struct gensec_socket);
	if (gensec_socket == NULL) {
		*new_socket = NULL;
		talloc_free(new_sock);
		return NT_STATUS_NO_MEMORY;
	}

	new_sock->private_data       = gensec_socket;
	gensec_socket->socket        = current_socket;

	/* Nothing to do here, if we are not actually wrapping on this socket */
	if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL) &&
	    !gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
		
		gensec_socket->wrap = false;
		talloc_steal(gensec_socket, current_socket);
		*new_socket = new_sock;
		return NT_STATUS_OK;
	}

	gensec_socket->gensec_security = gensec_security;

	gensec_socket->wrap          = true;
	gensec_socket->eof           = false;
	gensec_socket->error         = NT_STATUS_OK;
	gensec_socket->interrupted   = false;
	gensec_socket->in_extra_read = 0;

	gensec_socket->read_buffer   = data_blob(NULL, 0);

	gensec_socket->recv_handler  = recv_handler;
	gensec_socket->recv_private  = recv_private;
	gensec_socket->ev            = ev;

	gensec_socket->packet = packet_init(gensec_socket);
	if (gensec_socket->packet == NULL) {
		*new_socket = NULL;
		talloc_free(new_sock);
		return NT_STATUS_NO_MEMORY;
	}

	packet_set_private(gensec_socket->packet, gensec_socket);
	packet_set_socket(gensec_socket->packet, gensec_socket->socket);
	packet_set_callback(gensec_socket->packet, gensec_socket_unwrap);
	packet_set_full_request(gensec_socket->packet, gensec_socket_full_request);
	packet_set_error_handler(gensec_socket->packet, gensec_socket_error_handler);
	packet_set_serialise(gensec_socket->packet);

	/* TODO: full-request that knows about maximum packet size */

	talloc_steal(gensec_socket, current_socket);
	*new_socket = new_sock;
	return NT_STATUS_OK;
}
示例#5
0
/*
  initialise a server_context from a open socket and register a event handler
  for reading from that socket
*/
static void ldapsrv_accept(struct stream_connection *c,
			   struct auth_session_info *session_info)
{
	struct ldapsrv_service *ldapsrv_service = 
		talloc_get_type(c->private_data, struct ldapsrv_service);
	struct ldapsrv_connection *conn;
	struct cli_credentials *server_credentials;
	struct socket_address *socket_address;
	NTSTATUS status;
	int port;

	conn = talloc_zero(c, struct ldapsrv_connection);
	if (!conn) {
		stream_terminate_connection(c, "ldapsrv_accept: out of memory");
		return;
	}

	conn->packet      = NULL;
	conn->connection  = c;
	conn->service     = ldapsrv_service;
	conn->sockets.raw = c->socket;
	conn->lp_ctx      = ldapsrv_service->task->lp_ctx;

	c->private_data   = conn;

	socket_address = socket_get_my_addr(c->socket, conn);
	if (!socket_address) {
		ldapsrv_terminate_connection(conn, "ldapsrv_accept: failed to obtain local socket address!");
		return;
	}
	port = socket_address->port;
	talloc_free(socket_address);

	if (port == 636) {
		struct socket_context *tls_socket = tls_init_server(ldapsrv_service->tls_params, c->socket, 
								    c->event.fde, NULL);
		if (!tls_socket) {
			ldapsrv_terminate_connection(conn, "ldapsrv_accept: tls_init_server() failed");
			return;
		}
		talloc_steal(c, tls_socket);
		c->socket = tls_socket;
		conn->sockets.tls = tls_socket;

	} else if (port == 3268) /* Global catalog */ {
		conn->global_catalog = true;
	}
	conn->packet = packet_init(conn);
	if (conn->packet == NULL) {
		ldapsrv_terminate_connection(conn, "out of memory");
		return;
	}

	packet_set_private(conn->packet, conn);
	packet_set_socket(conn->packet, c->socket);
	packet_set_callback(conn->packet, ldapsrv_decode);
	packet_set_full_request(conn->packet, ldap_full_packet);
	packet_set_error_handler(conn->packet, ldapsrv_error_handler);
	packet_set_event_context(conn->packet, c->event.ctx);
	packet_set_fde(conn->packet, c->event.fde);
	packet_set_serialise(conn->packet);

	if (conn->sockets.tls) {
		packet_set_unreliable_select(conn->packet);
	}

	/* Ensure we don't get packets until the database is ready below */
	packet_recv_disable(conn->packet);

	server_credentials = cli_credentials_init(conn);
	if (!server_credentials) {
		stream_terminate_connection(c, "Failed to init server credentials\n");
		return;
	}

	cli_credentials_set_conf(server_credentials, conn->lp_ctx);
	status = cli_credentials_set_machine_account(server_credentials, conn->lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		stream_terminate_connection(c, talloc_asprintf(conn, "Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
		return;
	}
	conn->server_credentials = server_credentials;

	conn->session_info = talloc_move(conn, &session_info);

	if (!NT_STATUS_IS_OK(ldapsrv_backend_Init(conn))) {
		ldapsrv_terminate_connection(conn, "backend Init failed");
		return;
	}

	/* load limits from the conf partition */
	ldapsrv_load_limits(conn); /* should we fail on error ? */

	/* register the server */	
	irpc_add_name(c->msg_ctx, "ldap_server");

	/* set connections limits */
	conn->limits.ite = event_add_timed(c->event.ctx, conn, 
					   timeval_current_ofs(conn->limits.initial_timeout, 0),
					   ldapsrv_conn_init_timeout, conn);

	packet_recv_enable(conn->packet);

}
示例#6
0
krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
					    void *data,
					    krb5_krbhst_info *hi,
					    time_t timeout,
					    const krb5_data *send_buf,
					    krb5_data *recv_buf)
{
	krb5_error_code ret;
	NTSTATUS status;
	struct socket_address *remote_addr;
	const char *name;
	struct addrinfo *ai, *a;
	struct smb_krb5_socket *smb_krb5;

	struct tevent_context *ev = talloc_get_type(data, struct tevent_context);

	DATA_BLOB send_blob = data_blob_const(send_buf->data, send_buf->length);

	ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
	if (ret) {
		return ret;
	}

	for (a = ai; a; a = ai->ai_next) {
		smb_krb5 = talloc(NULL, struct smb_krb5_socket);
		if (!smb_krb5) {
			return ENOMEM;
		}
		smb_krb5->hi = hi;

		switch (a->ai_family) {
		case PF_INET:
			name = "ipv4";
			break;
#ifdef HAVE_IPV6
		case PF_INET6:
			name = "ipv6";
			break;
#endif
		default:
			talloc_free(smb_krb5);
			return EINVAL;
		}

		status = NT_STATUS_INVALID_PARAMETER;
		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			status = socket_create(name, SOCKET_TYPE_DGRAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_TCP:
			status = socket_create(name, SOCKET_TYPE_STREAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(smb_krb5);
			return EINVAL;
		}
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}

		talloc_steal(smb_krb5, smb_krb5->sock);

		remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen);
		if (!remote_addr) {
			talloc_free(smb_krb5);
			continue;
		}

		status = socket_connect_ev(smb_krb5->sock, NULL, remote_addr, 0, ev);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}
		talloc_free(remote_addr);

		/* Setup the FDE, start listening for read events
		 * from the start (otherwise we may miss a socket
		 * drop) and mark as AUTOCLOSE along with the fde */

		/* Ths is equivilant to EVENT_FD_READABLE(smb_krb5->fde) */
		smb_krb5->fde = tevent_add_fd(ev, smb_krb5->sock,
					      socket_get_fd(smb_krb5->sock),
					      TEVENT_FD_READ,
					      smb_krb5_socket_handler, smb_krb5);
		/* its now the job of the event layer to close the socket */
		tevent_fd_set_close_fn(smb_krb5->fde, socket_tevent_fd_close_fn);
		socket_set_flags(smb_krb5->sock, SOCKET_FLAG_NOCLOSE);

		tevent_add_timer(ev, smb_krb5,
				 timeval_current_ofs(timeout, 0),
				 smb_krb5_request_timeout, smb_krb5);

		smb_krb5->status = NT_STATUS_OK;
		smb_krb5->reply = data_blob(NULL, 0);

		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			TEVENT_FD_WRITEABLE(smb_krb5->fde);
			smb_krb5->request = send_blob;
			break;
		case KRB5_KRBHST_TCP:

			smb_krb5->packet = packet_init(smb_krb5);
			if (smb_krb5->packet == NULL) {
				talloc_free(smb_krb5);
				return ENOMEM;
			}
			packet_set_private(smb_krb5->packet, smb_krb5);
			packet_set_socket(smb_krb5->packet, smb_krb5->sock);
			packet_set_callback(smb_krb5->packet, smb_krb5_full_packet);
			packet_set_full_request(smb_krb5->packet, packet_full_request_u32);
			packet_set_error_handler(smb_krb5->packet, smb_krb5_error_handler);
			packet_set_event_context(smb_krb5->packet, ev);
			packet_set_fde(smb_krb5->packet, smb_krb5->fde);

			smb_krb5->request = data_blob_talloc(smb_krb5, NULL, send_blob.length + 4);
			RSIVAL(smb_krb5->request.data, 0, send_blob.length);
			memcpy(smb_krb5->request.data+4, send_blob.data, send_blob.length);
			packet_send(smb_krb5->packet, smb_krb5->request);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(smb_krb5);
			return EINVAL;
		}
		while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) {
			if (tevent_loop_once(ev) != 0) {
				talloc_free(smb_krb5);
				return EINVAL;
			}
		}
		if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) {
			talloc_free(smb_krb5);
			continue;
		}

		if (!NT_STATUS_IS_OK(smb_krb5->status)) {
			DEBUG(2,("Error reading smb_krb5 reply packet: %s\n", nt_errstr(smb_krb5->status)));
			talloc_free(smb_krb5);
			continue;
		}

		ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length);
		if (ret) {
			talloc_free(smb_krb5);
			return ret;
		}
		talloc_free(smb_krb5);

		break;
	}
	if (a) {
		return 0;
	}
	return KRB5_KDC_UNREACH;
}
krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
					    void *data,
					    krb5_krbhst_info *hi,
					    time_t timeout,
					    const krb5_data *send_buf,
					    krb5_data *recv_buf)
{
	krb5_error_code ret;
	NTSTATUS status;
	const char *name;
	struct addrinfo *ai, *a;
	struct smb_krb5_socket *smb_krb5;

	DATA_BLOB send_blob;

	struct tevent_context *ev;
	TALLOC_CTX *tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) {
		return ENOMEM;
	}

	if (!data) {
		/* If no event context was available, then create one for this loop */
		ev = samba_tevent_context_init(tmp_ctx);
		if (!ev) {
			talloc_free(tmp_ctx);
			return ENOMEM;
		}
	} else {
		ev = talloc_get_type_abort(data, struct tevent_context);
	}

	send_blob = data_blob_const(send_buf->data, send_buf->length);

	ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
	if (ret) {
		talloc_free(tmp_ctx);
		return ret;
	}

	for (a = ai; a; a = a->ai_next) {
		struct socket_address *remote_addr;
		smb_krb5 = talloc(tmp_ctx, struct smb_krb5_socket);
		if (!smb_krb5) {
			talloc_free(tmp_ctx);
			return ENOMEM;
		}
		smb_krb5->hi = hi;

		switch (a->ai_family) {
		case PF_INET:
			name = "ipv4";
			break;
#ifdef HAVE_IPV6
		case PF_INET6:
			name = "ipv6";
			break;
#endif
		default:
			talloc_free(tmp_ctx);
			return EINVAL;
		}

		status = NT_STATUS_INVALID_PARAMETER;
		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			status = socket_create(name, SOCKET_TYPE_DGRAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_TCP:
			status = socket_create(name, SOCKET_TYPE_STREAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(tmp_ctx);
			return EINVAL;
		}
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}

		talloc_steal(smb_krb5, smb_krb5->sock);

		remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen);
		if (!remote_addr) {
			talloc_free(smb_krb5);
			continue;
		}

		status = socket_connect_ev(smb_krb5->sock, NULL, remote_addr, 0, ev);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}

		/* Setup the FDE, start listening for read events
		 * from the start (otherwise we may miss a socket
		 * drop) and mark as AUTOCLOSE along with the fde */

		/* Ths is equivilant to EVENT_FD_READABLE(smb_krb5->fde) */
		smb_krb5->fde = tevent_add_fd(ev, smb_krb5->sock,
					      socket_get_fd(smb_krb5->sock),
					      TEVENT_FD_READ,
					      smb_krb5_socket_handler, smb_krb5);
		/* its now the job of the event layer to close the socket */
		tevent_fd_set_close_fn(smb_krb5->fde, socket_tevent_fd_close_fn);
		socket_set_flags(smb_krb5->sock, SOCKET_FLAG_NOCLOSE);

		tevent_add_timer(ev, smb_krb5,
				 timeval_current_ofs(timeout, 0),
				 smb_krb5_request_timeout, smb_krb5);

		smb_krb5->status = NT_STATUS_OK;
		smb_krb5->reply = data_blob(NULL, 0);

		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			TEVENT_FD_WRITEABLE(smb_krb5->fde);
			smb_krb5->request = send_blob;
			break;
		case KRB5_KRBHST_TCP:

			smb_krb5->packet = packet_init(smb_krb5);
			if (smb_krb5->packet == NULL) {
				talloc_free(smb_krb5);
				return ENOMEM;
			}
			packet_set_private(smb_krb5->packet, smb_krb5);
			packet_set_socket(smb_krb5->packet, smb_krb5->sock);
			packet_set_callback(smb_krb5->packet, smb_krb5_full_packet);
			packet_set_full_request(smb_krb5->packet, packet_full_request_u32);
			packet_set_error_handler(smb_krb5->packet, smb_krb5_error_handler);
			packet_set_event_context(smb_krb5->packet, ev);
			packet_set_fde(smb_krb5->packet, smb_krb5->fde);

			smb_krb5->request = data_blob_talloc(smb_krb5, NULL, send_blob.length + 4);
			RSIVAL(smb_krb5->request.data, 0, send_blob.length);
			memcpy(smb_krb5->request.data+4, send_blob.data, send_blob.length);
			packet_send(smb_krb5->packet, smb_krb5->request);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(tmp_ctx);
			return EINVAL;
		}
		while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) {
			if (tevent_loop_once(ev) != 0) {
				talloc_free(tmp_ctx);
				return EINVAL;
			}

			/* After each and every event loop, reset the
			 * send_to_kdc pointers to what they were when
			 * we entered this loop.  That way, if a
			 * nested event has invalidated them, we put
			 * it back before we return to the heimdal
			 * code */
			ret = krb5_set_send_to_kdc_func(context,
							smb_krb5_send_and_recv_func,
							data);
			if (ret != 0) {
				talloc_free(tmp_ctx);
				return ret;
			}
		}
		if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) {
			talloc_free(smb_krb5);
			continue;
		}

		if (!NT_STATUS_IS_OK(smb_krb5->status)) {
			struct tsocket_address *addr = socket_address_to_tsocket_address(smb_krb5, remote_addr);
			const char *addr_string = NULL;
			if (addr) {
				addr_string = tsocket_address_inet_addr_string(addr, smb_krb5);
			} else {
				addr_string = NULL;
			}
			DEBUG(2,("Error reading smb_krb5 reply packet: %s from %s\n", nt_errstr(smb_krb5->status),
				 addr_string));
			talloc_free(smb_krb5);
			continue;
		}

		ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length);
		if (ret) {
			talloc_free(tmp_ctx);
			return ret;
		}
		talloc_free(smb_krb5);

		break;
	}
	talloc_free(tmp_ctx);
	if (a) {
		return 0;
	}
	return KRB5_KDC_UNREACH;
}
示例#8
0
文件: kdc.c 项目: 0x24bin/winexe-1
/*
  called when we get a new connection
*/
static void kdc_tcp_accept(struct stream_connection *conn)
{
 	struct kdc_socket *kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket);
	struct kdc_tcp_connection *kdcconn;
	struct socket_address *src_addr;
	struct socket_address *my_addr;
	int ret;

	kdcconn = talloc_zero(conn, struct kdc_tcp_connection);
	if (!kdcconn) {
		stream_terminate_connection(conn, "kdc_tcp_accept: out of memory");
		return;
	}
	kdcconn->conn		= conn;
	kdcconn->kdc_socket	= kdc_socket;
	conn->private_data    = kdcconn;

	src_addr = socket_get_peer_addr(kdcconn->conn->socket, kdcconn);
	if (!src_addr) {
		kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory");
		return;
	}

	my_addr = socket_get_my_addr(kdcconn->conn->socket, kdcconn);
	if (!my_addr) {
		kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory");
		return;
	}

	ret = tsocket_address_bsd_from_sockaddr(kdcconn,
						src_addr->sockaddr,
						src_addr->sockaddrlen,
						&kdcconn->remote_address);
	if (ret < 0) {
		kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory");
		return;
	}

	ret = tsocket_address_bsd_from_sockaddr(kdcconn,
						my_addr->sockaddr,
						my_addr->sockaddrlen,
						&kdcconn->local_address);
	if (ret < 0) {
		kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory");
		return;
	}

	TALLOC_FREE(src_addr);
	TALLOC_FREE(my_addr);

	kdcconn->packet = packet_init(kdcconn);
	if (kdcconn->packet == NULL) {
		kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory");
		return;
	}
	packet_set_private(kdcconn->packet, kdcconn);
	packet_set_socket(kdcconn->packet, conn->socket);
	packet_set_callback(kdcconn->packet, kdc_tcp_recv);
	packet_set_full_request(kdcconn->packet, packet_full_request_u32);
	packet_set_error_handler(kdcconn->packet, kdc_tcp_recv_error);
	packet_set_event_context(kdcconn->packet, conn->event.ctx);
	packet_set_fde(kdcconn->packet, conn->event.fde);
	packet_set_serialise(kdcconn->packet);
}