return NT_STATUS_OK;
}
-struct cldap_netlogon_state {
- struct cldap_search search;
-};
-
-char *cldap_netlogon_create_filter(TALLOC_CTX *mem_ctx,
- const struct cldap_netlogon *io)
-{
- char *filter;
-
- filter = talloc_asprintf(mem_ctx, "(&(NtVer=%s)",
- ldap_encode_ndr_uint32(mem_ctx, io->in.version));
-
- if (io->in.user) {
- talloc_asprintf_addbuf(&filter, "(User=%s)", io->in.user);
- }
- if (io->in.host) {
- talloc_asprintf_addbuf(&filter, "(Host=%s)", io->in.host);
- }
- if (io->in.realm) {
- talloc_asprintf_addbuf(&filter, "(DnsDomain=%s)", io->in.realm);
- }
- if (io->in.acct_control != -1) {
- talloc_asprintf_addbuf(
- &filter,
- "(AAC=%s)",
- ldap_encode_ndr_uint32(mem_ctx, io->in.acct_control));
- }
- if (io->in.domain_sid) {
- struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, io->in.domain_sid);
-
- talloc_asprintf_addbuf(&filter, "(domainSid=%s)",
- ldap_encode_ndr_dom_sid(mem_ctx, sid));
- }
- if (io->in.domain_guid) {
- struct GUID guid;
- GUID_from_string(io->in.domain_guid, &guid);
-
- talloc_asprintf_addbuf(&filter, "(DomainGuid=%s)",
- ldap_encode_ndr_GUID(mem_ctx, &guid));
- }
- talloc_asprintf_addbuf(&filter, ")");
-
- return filter;
-}
-
-static void cldap_netlogon_state_done(struct tevent_req *subreq);
-/*
- queue a cldap netlogon for send
-*/
-struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct cldap_socket *cldap,
- const struct cldap_netlogon *io)
-{
- struct tevent_req *req, *subreq;
- struct cldap_netlogon_state *state;
- char *filter;
- static const char * const attr[] = { "NetLogon", NULL };
-
- req = tevent_req_create(mem_ctx, &state,
- struct cldap_netlogon_state);
- if (!req) {
- return NULL;
- }
-
- filter = cldap_netlogon_create_filter(state, io);
- if (tevent_req_nomem(filter, req)) {
- goto post;
- }
-
- if (io->in.dest_address) {
- state->search.in.dest_address = talloc_strdup(state,
- io->in.dest_address);
- if (tevent_req_nomem(state->search.in.dest_address, req)) {
- goto post;
- }
- state->search.in.dest_port = io->in.dest_port;
- } else {
- state->search.in.dest_address = NULL;
- state->search.in.dest_port = 0;
- }
- state->search.in.filter = filter;
- state->search.in.attributes = attr;
- state->search.in.timeout = 2;
- state->search.in.retries = 2;
-
- subreq = cldap_search_send(state, ev, cldap, &state->search);
- if (tevent_req_nomem(subreq, req)) {
- goto post;
- }
- tevent_req_set_callback(subreq, cldap_netlogon_state_done, req);
-
- return req;
-post:
- return tevent_req_post(req, ev);
-}
-
-static void cldap_netlogon_state_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct cldap_netlogon_state *state = tevent_req_data(req,
- struct cldap_netlogon_state);
- NTSTATUS status;
-
- status = cldap_search_recv(subreq, state, &state->search);
- talloc_free(subreq);
-
- if (tevent_req_nterror(req, status)) {
- return;
- }
-
- tevent_req_done(req);
-}
-
-/*
- receive a cldap netlogon reply
-*/
-NTSTATUS cldap_netlogon_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- struct cldap_netlogon *io)
-{
- struct cldap_netlogon_state *state = tevent_req_data(req,
- struct cldap_netlogon_state);
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- DATA_BLOB *data;
-
- if (tevent_req_is_nterror(req, &status)) {
- goto failed;
- }
-
- if (state->search.out.response == NULL) {
- status = NT_STATUS_NOT_FOUND;
- goto failed;
- }
-
- if (state->search.out.response->num_attributes != 1 ||
- strcasecmp(state->search.out.response->attributes[0].name, "netlogon") != 0 ||
- state->search.out.response->attributes[0].num_values != 1 ||
- state->search.out.response->attributes[0].values->length < 2) {
- status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
- goto failed;
- }
- data = state->search.out.response->attributes[0].values;
-
- io->out.netlogon = talloc(mem_ctx, struct netlogon_samlogon_response);
- if (io->out.netlogon == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto failed;
- }
-
- status = pull_netlogon_samlogon_response(data,
- io->out.netlogon,
- io->out.netlogon);
- if (!NT_STATUS_IS_OK(status)) {
- goto failed;
- }
-
- status = NT_STATUS_OK;
-failed:
- tevent_req_received(req);
- return status;
-}
-
-/*
- sync cldap netlogon search
-*/
-NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
- TALLOC_CTX *mem_ctx,
- struct cldap_netlogon *io)
-{
- TALLOC_CTX *frame;
- struct tevent_req *req;
- struct tevent_context *ev;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
-
- if (cldap->searches.list) {
- return NT_STATUS_PIPE_BUSY;
- }
-
- if (cldap->incoming.handler) {
- return NT_STATUS_INVALID_PIPE_STATE;
- }
-
- frame = talloc_stackframe();
-
- ev = samba_tevent_context_init(frame);
- if (ev == NULL) {
- goto done;
- }
- req = cldap_netlogon_send(mem_ctx, ev, cldap, io);
- if (req == NULL) {
- goto done;
- }
- if (!tevent_req_poll_ntstatus(req, ev, &status)) {
- goto done;
- }
- status = cldap_netlogon_recv(req, mem_ctx, io);
- if (!NT_STATUS_IS_OK(status)) {
- goto done;
- }
-done:
- TALLOC_FREE(frame);
- return status;
-}
-
-
/*
send an empty reply (used on any error, so the client doesn't keep waiting
or send the bad request again)