📄 socket.c
字号:
gensec_socket->read_buffer.data, uint8_t, gensec_socket->read_buffer.length); if (gensec_socket->read_buffer.length && gensec_socket->in_extra_read == 0 && gensec_socket->recv_handler) { /* Manually call a read event, to get this moving * again (as the socket should be dry, so the normal * event handler won't trigger) */ event_add_timed(gensec_socket->ev, gensec_socket, timeval_zero(), gensec_socket_trigger_read, gensec_socket); } return NT_STATUS_OK;}/* Completed SASL packet callback. When we have a 'whole' SASL * packet, decrypt it, and add it to the read buffer * * This function (and anything under it) MUST NOT call the event system */static NTSTATUS gensec_socket_unwrap(void *private, DATA_BLOB blob){ struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket); DATA_BLOB unwrapped; NTSTATUS nt_status; TALLOC_CTX *mem_ctx; size_t packet_size; mem_ctx = talloc_new(gensec_socket); if (!mem_ctx) { return NT_STATUS_NO_MEMORY; } nt_status = gensec_unwrap_packets(gensec_socket->gensec_security, mem_ctx, &blob, &unwrapped, &packet_size); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return nt_status; } if (packet_size != blob.length) { DEBUG(0, ("gensec_socket_unwrap: Did not consume entire packet!\n")); talloc_free(mem_ctx); return NT_STATUS_INTERNAL_ERROR; } /* We could change this into a linked list, and have * gensec_socket_recv() and gensec_socket_pending() walk the * linked list */ if (!data_blob_append(gensec_socket, &gensec_socket->read_buffer, unwrapped.data, unwrapped.length)) { talloc_free(mem_ctx); return NT_STATUS_NO_MEMORY; } talloc_free(mem_ctx); return NT_STATUS_OK;}/* when the data is sent, we know we have not been interrupted */static void send_callback(void *private) { struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket); gensec_socket->interrupted = false;}/* send data, but only as much as we allow in one packet. If this returns STATUS_MORE_ENTRIES, the caller must retry with exactly the same data, or a NULL blob.*/static NTSTATUS gensec_socket_send(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen){ NTSTATUS nt_status; struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket); DATA_BLOB wrapped; TALLOC_CTX *mem_ctx; if (!gensec_socket->wrap) { return socket_send(gensec_socket->socket, blob, sendlen); } *sendlen = 0; /* We have have been interupted, so the caller should be * giving us the same data again. */ if (gensec_socket->interrupted) { packet_queue_run(gensec_socket->packet); if (!NT_STATUS_IS_OK(gensec_socket->error)) { return gensec_socket->error; } else if (gensec_socket->interrupted) { return STATUS_MORE_ENTRIES; } else { *sendlen = gensec_socket->orig_send_len; gensec_socket->orig_send_len = 0; return NT_STATUS_OK; } } mem_ctx = talloc_new(gensec_socket); if (!mem_ctx) { return NT_STATUS_NO_MEMORY; } nt_status = gensec_wrap_packets(gensec_socket->gensec_security, mem_ctx, blob, &wrapped, &gensec_socket->orig_send_len); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return nt_status; } gensec_socket->interrupted = true; gensec_socket->error = NT_STATUS_OK; nt_status = packet_send_callback(gensec_socket->packet, wrapped, send_callback, gensec_socket); talloc_free(mem_ctx); packet_queue_run(gensec_socket->packet); if (!NT_STATUS_IS_OK(gensec_socket->error)) { return gensec_socket->error; } else if (gensec_socket->interrupted) { return STATUS_MORE_ENTRIES; } else { *sendlen = gensec_socket->orig_send_len; gensec_socket->orig_send_len = 0; return NT_STATUS_OK; }}/* Turn a normal socket into a potentially GENSEC wrapped socket */NTSTATUS gensec_socket_init(struct gensec_security *gensec_security, struct socket_context *current_socket, struct event_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(current_socket, &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; return NT_STATUS_NO_MEMORY; } new_sock->private_data = gensec_socket; gensec_socket->socket = current_socket; if (talloc_reference(gensec_socket, current_socket) == NULL) { *new_socket = NULL; return NT_STATUS_NO_MEMORY; } /* 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; *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; 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 */ *new_socket = new_sock; return NT_STATUS_OK;}static NTSTATUS gensec_socket_set_option(struct socket_context *sock, const char *option, const char *val){ set_socket_options(socket_get_fd(sock), option); return NT_STATUS_OK;}static char *gensec_socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx){ struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket); return socket_get_peer_name(gensec->socket, mem_ctx);}static struct socket_address *gensec_socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx){ struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket); return socket_get_peer_addr(gensec->socket, mem_ctx);}static struct socket_address *gensec_socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx){ struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket); return socket_get_my_addr(gensec->socket, mem_ctx);}static int gensec_socket_get_fd(struct socket_context *sock){ struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket); return socket_get_fd(gensec->socket);}static const struct socket_ops gensec_socket_ops = { .name = "gensec", .fn_init = gensec_socket_init_fn, .fn_recv = gensec_socket_recv, .fn_send = gensec_socket_send, .fn_pending = gensec_socket_pending, .fn_set_option = gensec_socket_set_option, .fn_get_peer_name = gensec_socket_get_peer_name, .fn_get_peer_addr = gensec_socket_get_peer_addr, .fn_get_my_addr = gensec_socket_get_my_addr, .fn_get_fd = gensec_socket_get_fd};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -