static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn) { struct tevent_req *subreq; if (timeval_is_zero(&conn->limits.endtime)) { conn->limits.endtime = timeval_current_ofs(conn->limits.initial_timeout, 0); } else { conn->limits.endtime = timeval_current_ofs(conn->limits.conn_idle_time, 0); } /* * The minimun size of a LDAP pdu is 7 bytes * * dumpasn1 -hh ldap-unbind-min.dat * * <30 05 02 01 09 42 00> * 0 5: SEQUENCE { * <02 01 09> * 2 1: INTEGER 9 * <42 00> * 5 0: [APPLICATION 2] * : Error: Object has zero length. * : } * * dumpasn1 -hh ldap-unbind-windows.dat * * <30 84 00 00 00 05 02 01 09 42 00> * 0 5: SEQUENCE { * <02 01 09> * 6 1: INTEGER 9 * <42 00> * 9 0: [APPLICATION 2] * : Error: Object has zero length. * : } * * This means using an initial read size * of 7 is ok. */ subreq = tstream_read_pdu_blob_send(conn, conn->connection->event.ctx, conn->sockets.active, 7, /* initial_read_size */ ldap_full_packet, conn); if (subreq == NULL) { ldapsrv_terminate_connection(conn, "ldapsrv_call_read_next: " "no memory for tstream_read_pdu_blob_send"); return false; } tevent_req_set_endtime(subreq, conn->connection->event.ctx, conn->limits.endtime); tevent_req_set_callback(subreq, ldapsrv_call_read_done, conn); return true; }
/* called when we get a new connection */ static void kdc_tcp_accept(struct stream_connection *conn) { struct kdc_socket *kdc_socket; struct kdc_tcp_connection *kdc_conn; struct tevent_req *subreq; int rc; kdc_conn = talloc_zero(conn, struct kdc_tcp_connection); if (kdc_conn == NULL) { stream_terminate_connection(conn, "kdc_tcp_accept: out of memory"); return; } kdc_conn->send_queue = tevent_queue_create(conn, "kdc_tcp_accept"); if (kdc_conn->send_queue == NULL) { stream_terminate_connection(conn, "kdc_tcp_accept: out of memory"); return; } kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket); TALLOC_FREE(conn->event.fde); rc = tstream_bsd_existing_socket(kdc_conn, socket_get_fd(conn->socket), &kdc_conn->tstream); if (rc < 0) { stream_terminate_connection(conn, "kdc_tcp_accept: out of memory"); return; } kdc_conn->conn = conn; kdc_conn->kdc_socket = kdc_socket; conn->private_data = kdc_conn; /* * The krb5 tcp pdu's has the length as 4 byte (initial_read_size), * packet_full_request_u32 provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(kdc_conn, kdc_conn->conn->event.ctx, kdc_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, kdc_conn); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_accept: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn); }
static void wbsrv_accept(struct stream_connection *conn) { struct wbsrv_listen_socket *wbsrv_socket = talloc_get_type(conn->private_data, struct wbsrv_listen_socket); struct wbsrv_connection *wbsrv_conn; struct tevent_req *subreq; int rc; wbsrv_conn = talloc_zero(conn, struct wbsrv_connection); if (wbsrv_conn == NULL) { stream_terminate_connection(conn, "wbsrv_accept: out of memory"); return; } wbsrv_conn->send_queue = tevent_queue_create(conn, "wbsrv_accept"); if (wbsrv_conn->send_queue == NULL) { stream_terminate_connection(conn, "wbsrv_accept: out of memory"); return; } TALLOC_FREE(conn->event.fde); rc = tstream_bsd_existing_socket(wbsrv_conn, socket_get_fd(conn->socket), &wbsrv_conn->tstream); if (rc < 0) { stream_terminate_connection(conn, "wbsrv_accept: out of memory"); return; } wbsrv_conn->conn = conn; wbsrv_conn->listen_socket = wbsrv_socket; wbsrv_conn->lp_ctx = wbsrv_socket->service->task->lp_ctx; conn->private_data = wbsrv_conn; /* * The winbind pdu's has the length as 4 byte (initial_read_size), * wbsrv_samba3_packet_full_request provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wbsrv_conn, wbsrv_conn->conn->event.ctx, wbsrv_conn->tstream, 4, /* initial_read_size */ wbsrv_samba3_packet_full_request, wbsrv_conn); if (subreq == NULL) { wbsrv_terminate_connection(wbsrv_conn, "wbsrv_accept: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn); }
static void wbsrv_call_loop(struct tevent_req *subreq) { struct wbsrv_connection *wbsrv_conn = tevent_req_callback_data(subreq, struct wbsrv_connection); struct wbsrv_samba3_call *call; NTSTATUS status; call = talloc_zero(wbsrv_conn, struct wbsrv_samba3_call); if (call == NULL) { wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: " "no memory for wbsrv_samba3_call"); return; } call->wbconn = wbsrv_conn; status = tstream_read_pdu_blob_recv(subreq, call, &call->in); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(wbsrv_conn, "wbsrv_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (!reason) { reason = nt_errstr(status); } wbsrv_terminate_connection(wbsrv_conn, reason); return; } DEBUG(10,("Received winbind TCP packet of length %lu from %s\n", (long) call->in.length, tsocket_address_string(wbsrv_conn->conn->remote_address, call))); status = wbsrv_samba3_process(call); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(wbsrv_conn, "wbsrv_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (!reason) { reason = nt_errstr(status); } wbsrv_terminate_connection(wbsrv_conn, reason); return; } /* * The winbind pdu's has the length as 4 byte (initial_read_size), * wbsrv_samba3_packet_full_request provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wbsrv_conn, wbsrv_conn->conn->event.ctx, wbsrv_conn->tstream, 4, /* initial_read_size */ wbsrv_samba3_packet_full_request, wbsrv_conn); if (subreq == NULL) { wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn); }
/* called when we get a new connection */ static void wreplsrv_accept(struct stream_connection *conn) { struct wreplsrv_service *service = talloc_get_type(conn->private_data, struct wreplsrv_service); struct wreplsrv_in_connection *wrepl_conn; struct tsocket_address *peer_addr; char *peer_ip; struct tevent_req *subreq; int rc; wrepl_conn = talloc_zero(conn, struct wreplsrv_in_connection); if (wrepl_conn == NULL) { stream_terminate_connection(conn, "wreplsrv_accept: out of memory"); return; } wrepl_conn->send_queue = tevent_queue_create(conn, "wrepl_accept"); if (wrepl_conn->send_queue == NULL) { stream_terminate_connection(conn, "wrepl_accept: out of memory"); return; } TALLOC_FREE(conn->event.fde); rc = tstream_bsd_existing_socket(wrepl_conn, socket_get_fd(conn->socket), &wrepl_conn->tstream); if (rc < 0) { stream_terminate_connection(conn, "wrepl_accept: out of memory"); return; } socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE); wrepl_conn->conn = conn; wrepl_conn->service = service; peer_addr = conn->remote_address; if (!tsocket_address_is_inet(peer_addr, "ipv4")) { DEBUG(0,("wreplsrv_accept: non ipv4 peer addr '%s'\n", tsocket_address_string(peer_addr, wrepl_conn))); wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: " "invalid peer IP"); return; } peer_ip = tsocket_address_inet_addr_string(peer_addr, wrepl_conn); if (peer_ip == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: " "could not convert peer IP into a string"); return; } wrepl_conn->partner = wreplsrv_find_partner(service, peer_ip); irpc_add_name(conn->msg_ctx, "wreplsrv_connection"); /* * The wrepl pdu's has the length as 4 byte (initial_read_size), * packet_full_request_u32 provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wrepl_conn, wrepl_conn->conn->event.ctx, wrepl_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, wrepl_conn); if (subreq == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wrepl_accept: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn); }
/* called when we get a new connection */ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner, uint32_t peer_assoc_ctx, struct tstream_context **stream, struct wreplsrv_in_connection **_wrepl_in) { struct wreplsrv_service *service = partner->service; struct wreplsrv_in_connection *wrepl_in; const struct model_ops *model_ops; struct stream_connection *conn; struct tevent_req *subreq; NTSTATUS status; /* within the wrepl task we want to be a single process, so ask for the single process model ops and pass these to the stream_setup_socket() call. */ model_ops = process_model_startup("single"); if (!model_ops) { DEBUG(0,("Can't find 'single' process model_ops")); return NT_STATUS_INTERNAL_ERROR; } wrepl_in = talloc_zero(partner, struct wreplsrv_in_connection); NT_STATUS_HAVE_NO_MEMORY(wrepl_in); wrepl_in->service = service; wrepl_in->partner = partner; wrepl_in->tstream = talloc_move(wrepl_in, stream); wrepl_in->assoc_ctx.peer_ctx = peer_assoc_ctx; status = stream_new_connection_merge(service->task->event_ctx, service->task->lp_ctx, model_ops, &wreplsrv_stream_ops, service->task->msg_ctx, wrepl_in, &conn); NT_STATUS_NOT_OK_RETURN(status); /* * make the wreplsrv_in_connection structure a child of the * stream_connection, to match the hierarchy of wreplsrv_accept */ wrepl_in->conn = conn; talloc_steal(conn, wrepl_in); wrepl_in->send_queue = tevent_queue_create(wrepl_in, "wreplsrv_in_connection_merge"); if (wrepl_in->send_queue == NULL) { stream_terminate_connection(conn, "wreplsrv_in_connection_merge: out of memory"); return NT_STATUS_NO_MEMORY; } /* * The wrepl pdu's has the length as 4 byte (initial_read_size), * packet_full_request_u32 provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wrepl_in, wrepl_in->conn->event.ctx, wrepl_in->tstream, 4, /* initial_read_size */ packet_full_request_u32, wrepl_in); if (subreq == NULL) { wreplsrv_terminate_in_connection(wrepl_in, "wreplsrv_in_connection_merge: " "no memory for tstream_read_pdu_blob_send"); return NT_STATUS_NO_MEMORY; } tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_in); *_wrepl_in = wrepl_in; return NT_STATUS_OK; }
static void wreplsrv_call_loop(struct tevent_req *subreq) { struct wreplsrv_in_connection *wrepl_conn = tevent_req_callback_data(subreq, struct wreplsrv_in_connection); struct wreplsrv_in_call *call; NTSTATUS status; call = talloc_zero(wrepl_conn, struct wreplsrv_in_call); if (call == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: " "no memory for wrepl_samba3_call"); return; } call->wreplconn = wrepl_conn; status = tstream_read_pdu_blob_recv(subreq, call, &call->in); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(call, "wreplsrv_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (!reason) { reason = nt_errstr(status); } wreplsrv_terminate_in_connection(wrepl_conn, reason); return; } DEBUG(10,("Received wrepl packet of length %lu from %s\n", (long) call->in.length, tsocket_address_string(wrepl_conn->conn->remote_address, call))); /* skip length header */ call->in.data += 4; call->in.length -= 4; status = wreplsrv_process(wrepl_conn, &call); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(call, "wreplsrv_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (reason == NULL) { reason = nt_errstr(status); } wreplsrv_terminate_in_connection(wrepl_conn, reason); return; } /* We handed over the connection so we're done here */ if (wrepl_conn->tstream == NULL) { return; } /* Invalid WINS-Replication packet, we just ignore it */ if (call == NULL) { goto noreply; } call->out_iov[0].iov_base = (char *) call->out.data; call->out_iov[0].iov_len = call->out.length; subreq = tstream_writev_queue_send(call, wrepl_conn->conn->event.ctx, wrepl_conn->tstream, wrepl_conn->send_queue, call->out_iov, 1); if (subreq == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: " "no memory for tstream_writev_queue_send"); return; } tevent_req_set_callback(subreq, wreplsrv_call_writev_done, call); noreply: /* * The wrepl pdu's has the length as 4 byte (initial_read_size), * provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wrepl_conn, wrepl_conn->conn->event.ctx, wrepl_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, wrepl_conn); if (subreq == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn); }
static void kdc_tcp_call_proxy_done(struct tevent_req *subreq) { struct kdc_tcp_call *call = tevent_req_callback_data(subreq, struct kdc_tcp_call); struct kdc_tcp_connection *kdc_conn = call->kdc_conn; NTSTATUS status; status = kdc_tcp_proxy_recv(subreq, call, &call->out); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { /* generate an error packet */ status = kdc_proxy_unavailable_error(kdc_conn->kdc_socket->kdc, call, &call->out); } if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(call, "kdc_tcp_call_proxy_done: " "kdc_proxy_unavailable_error - %s", nt_errstr(status)); if (!reason) { reason = "kdc_tcp_call_proxy_done: kdc_proxy_unavailable_error() failed"; } kdc_tcp_terminate_connection(call->kdc_conn, reason); return; } /* First add the length of the out buffer */ RSIVAL(call->out_hdr, 0, call->out.length); call->out_iov[0].iov_base = (char *) call->out_hdr; call->out_iov[0].iov_len = 4; call->out_iov[1].iov_base = (char *) call->out.data; call->out_iov[1].iov_len = call->out.length; subreq = tstream_writev_queue_send(call, kdc_conn->conn->event.ctx, kdc_conn->tstream, kdc_conn->send_queue, call->out_iov, 2); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for tstream_writev_queue_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call); /* * The krb5 tcp pdu's has the length as 4 byte (initial_read_size), * packet_full_request_u32 provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(kdc_conn, kdc_conn->conn->event.ctx, kdc_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, kdc_conn); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn); }
static void kdc_tcp_call_loop(struct tevent_req *subreq) { struct kdc_tcp_connection *kdc_conn = tevent_req_callback_data(subreq, struct kdc_tcp_connection); struct kdc_tcp_call *call; NTSTATUS status; enum kdc_process_ret ret; call = talloc(kdc_conn, struct kdc_tcp_call); if (call == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for kdc_tcp_call"); return; } call->kdc_conn = kdc_conn; status = tstream_read_pdu_blob_recv(subreq, call, &call->in); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(call, "kdc_tcp_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (!reason) { reason = nt_errstr(status); } kdc_tcp_terminate_connection(kdc_conn, reason); return; } DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n", (long) call->in.length, tsocket_address_string(kdc_conn->conn->remote_address, call))); /* skip length header */ call->in.data +=4; call->in.length -= 4; /* Call krb5 */ ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc, call, &call->in, &call->out, kdc_conn->conn->remote_address, kdc_conn->conn->local_address, 0 /* Stream */); if (ret == KDC_PROCESS_FAILED) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: process function failed"); return; } if (ret == KDC_PROCESS_PROXY) { uint16_t port; if (!kdc_conn->kdc_socket->kdc->am_rodc) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: proxying requested when not RODC"); return; } port = tsocket_address_inet_port(kdc_conn->conn->local_address); subreq = kdc_tcp_proxy_send(call, kdc_conn->conn->event.ctx, kdc_conn->kdc_socket->kdc, port, call->in); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: kdc_tcp_proxy_send failed"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_proxy_done, call); return; } /* First add the length of the out buffer */ RSIVAL(call->out_hdr, 0, call->out.length); call->out_iov[0].iov_base = (char *) call->out_hdr; call->out_iov[0].iov_len = 4; call->out_iov[1].iov_base = (char *) call->out.data; call->out_iov[1].iov_len = call->out.length; subreq = tstream_writev_queue_send(call, kdc_conn->conn->event.ctx, kdc_conn->tstream, kdc_conn->send_queue, call->out_iov, 2); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for tstream_writev_queue_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call); /* * The krb5 tcp pdu's has the length as 4 byte (initial_read_size), * packet_full_request_u32 provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(kdc_conn, kdc_conn->conn->event.ctx, kdc_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, kdc_conn); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn); }