📄 dcerpc_util.c
字号:
struct composite_context); struct pipe_auth_state *s = talloc_get_type(c->private_data, struct pipe_auth_state); struct composite_context *sec_conn_req; c->status = dcerpc_bind_auth_recv(ctx); if (NT_STATUS_EQUAL(c->status, NT_STATUS_INVALID_PARAMETER)) { /* * Retry with NTLMSSP auth as fallback * send a request for secondary rpc connection */ sec_conn_req = dcerpc_secondary_connection_send(s->pipe, s->binding); composite_continue(c, sec_conn_req, continue_ntlmssp_connection, c); return; } else if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) { if (cli_credentials_wrong_password(s->credentials)) { /* * Retry SPNEGO with a better password * send a request for secondary rpc connection */ sec_conn_req = dcerpc_secondary_connection_send(s->pipe, s->binding); composite_continue(c, sec_conn_req, continue_spnego_after_wrong_pass, c); return; } } if (!composite_is_ok(c)) return; composite_done(c);}/* Stage 3 of pipe_auth (fallback to NTLMSSP case): Receive secondary rpc connection (the first one can't be used any more, due to the bind nak) and perform authenticated bind request*/static void continue_ntlmssp_connection(struct composite_context *ctx){ struct composite_context *c; struct pipe_auth_state *s; struct composite_context *auth_req; struct dcerpc_pipe *p2; c = talloc_get_type(ctx->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct pipe_auth_state); /* receive secondary rpc connection */ c->status = dcerpc_secondary_connection_recv(ctx, &p2); if (!composite_is_ok(c)) return; talloc_steal(s, p2); talloc_steal(p2, s->pipe); s->pipe = p2; /* initiate a authenticated bind */ auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, s->lp_ctx, DCERPC_AUTH_TYPE_NTLMSSP, dcerpc_auth_level(s->pipe->conn), s->table->authservices->names[0]); composite_continue(c, auth_req, continue_auth, c);}/* Stage 3 of pipe_auth (retry on wrong password): Receive secondary rpc connection (the first one can't be used any more, due to the bind nak) and perform authenticated bind request*/static void continue_spnego_after_wrong_pass(struct composite_context *ctx){ struct composite_context *c; struct pipe_auth_state *s; struct composite_context *auth_req; struct dcerpc_pipe *p2; c = talloc_get_type(ctx->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct pipe_auth_state); /* receive secondary rpc connection */ c->status = dcerpc_secondary_connection_recv(ctx, &p2); if (!composite_is_ok(c)) return; talloc_steal(s, p2); talloc_steal(p2, s->pipe); s->pipe = p2; /* initiate a authenticated bind */ auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, s->lp_ctx, DCERPC_AUTH_TYPE_SPNEGO, dcerpc_auth_level(s->pipe->conn), s->table->authservices->names[0]); composite_continue(c, auth_req, continue_auth, c);}/* Stage 2 of pipe_auth: Receive result of non-authenticated bind request*/static void continue_auth_none(struct composite_context *ctx){ struct composite_context *c = talloc_get_type(ctx->async.private_data, struct composite_context); c->status = dcerpc_bind_auth_none_recv(ctx); if (!composite_is_ok(c)) return; composite_done(c);}/* Request to perform an authenticated bind if required. Authentication is determined using credentials passed and binding flags.*/struct composite_context *dcerpc_pipe_auth_send(struct dcerpc_pipe *p, struct dcerpc_binding *binding, const struct ndr_interface_table *table, struct cli_credentials *credentials, struct loadparm_context *lp_ctx){ struct composite_context *c; struct pipe_auth_state *s; struct composite_context *auth_schannel_req; struct composite_context *auth_req; struct composite_context *auth_none_req; struct dcerpc_connection *conn; uint8_t auth_type; /* composite context allocation and setup */ c = composite_create(p, p->conn->event_ctx); if (c == NULL) return NULL; s = talloc_zero(c, struct pipe_auth_state); if (composite_nomem(s, c)) return c; c->private_data = s; /* store parameters in state structure */ s->binding = binding; s->table = table; s->credentials = credentials; s->pipe = p; s->lp_ctx = lp_ctx; conn = s->pipe->conn; conn->flags = binding->flags; /* remember the binding string for possible secondary connections */ conn->binding_string = dcerpc_binding_string(p, binding); if (cli_credentials_is_anonymous(s->credentials)) { auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe, s->table); composite_continue(c, auth_none_req, continue_auth_none, c); return c; } if ((binding->flags & DCERPC_SCHANNEL) && !cli_credentials_get_netlogon_creds(s->credentials)) { /* If we don't already have netlogon credentials for * the schannel bind, then we have to get these * first */ auth_schannel_req = dcerpc_bind_auth_schannel_send(c, s->pipe, s->table, s->credentials, s->lp_ctx, dcerpc_auth_level(conn)); composite_continue(c, auth_schannel_req, continue_auth_schannel, c); return c; } /* * we rely on the already authenticated CIFS connection * if not doing sign or seal */ if (conn->transport.transport == NCACN_NP && !(s->binding->flags & (DCERPC_SIGN|DCERPC_SEAL))) { auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe, s->table); composite_continue(c, auth_none_req, continue_auth_none, c); return c; } /* Perform an authenticated DCE-RPC bind */ if (!(conn->flags & (DCERPC_SIGN|DCERPC_SEAL))) { /* we are doing an authenticated connection, but not using sign or seal. We must force the CONNECT dcerpc auth type as a NONE auth type doesn't allow authentication information to be passed. */ conn->flags |= DCERPC_CONNECT; } if (s->binding->flags & DCERPC_AUTH_SPNEGO) { auth_type = DCERPC_AUTH_TYPE_SPNEGO; } else if (s->binding->flags & DCERPC_AUTH_KRB5) { auth_type = DCERPC_AUTH_TYPE_KRB5; } else if (s->binding->flags & DCERPC_SCHANNEL) { auth_type = DCERPC_AUTH_TYPE_SCHANNEL; } else if (s->binding->flags & DCERPC_AUTH_NTLM) { auth_type = DCERPC_AUTH_TYPE_NTLMSSP; } else { /* try SPNEGO with fallback to NTLMSSP */ auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, s->lp_ctx, DCERPC_AUTH_TYPE_SPNEGO, dcerpc_auth_level(conn), s->table->authservices->names[0]); composite_continue(c, auth_req, continue_auth_auto, c); return c; } auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, s->lp_ctx, auth_type, dcerpc_auth_level(conn), s->table->authservices->names[0]); composite_continue(c, auth_req, continue_auth, c); return c;}/* Receive result of authenticated bind request on dcerpc pipe This returns *p, which may be different to the one originally supllied, as it rebinds to a new pipe due to authentication fallback*/NTSTATUS dcerpc_pipe_auth_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct dcerpc_pipe **p){ NTSTATUS status; struct pipe_auth_state *s = talloc_get_type(c->private_data, struct pipe_auth_state); status = composite_wait(c); if (!NT_STATUS_IS_OK(status)) { char *uuid_str = GUID_string(s->pipe, &s->table->syntax_id.uuid); DEBUG(0, ("Failed to bind to uuid %s - %s\n", uuid_str, nt_errstr(status))); talloc_free(uuid_str); } else { talloc_steal(mem_ctx, s->pipe); *p = s->pipe; } talloc_free(c); return status;}/* Perform an authenticated bind if needed - sync version This may change *p, as it rebinds to a new pipe due to authentication fallback*/_PUBLIC_ NTSTATUS dcerpc_pipe_auth(TALLOC_CTX *mem_ctx, struct dcerpc_pipe **p, struct dcerpc_binding *binding, const struct ndr_interface_table *table, struct cli_credentials *credentials, struct loadparm_context *lp_ctx){ struct composite_context *c; c = dcerpc_pipe_auth_send(*p, binding, table, credentials, lp_ctx); return dcerpc_pipe_auth_recv(c, mem_ctx, p);}NTSTATUS dcerpc_generic_session_key(struct dcerpc_connection *c, DATA_BLOB *session_key){ /* this took quite a few CPU cycles to find ... */ session_key->data = discard_const_p(unsigned char, "SystemLibraryDTC"); session_key->length = 16; return NT_STATUS_OK;}/* fetch the user session key - may be default (above) or the SMB session key*/_PUBLIC_ NTSTATUS dcerpc_fetch_session_key(struct dcerpc_pipe *p, DATA_BLOB *session_key){ return p->conn->security_state.session_key(p->conn, session_key);}/* log a rpc packet in a format suitable for ndrdump. This is especially useful for sealed packets, where ethereal cannot easily see the contents this triggers on a debug level of >= 10*/_PUBLIC_ void dcerpc_log_packet(const struct ndr_interface_table *ndr, uint32_t opnum, uint32_t flags, DATA_BLOB *pkt){ const int num_examples = 20; int i; if (DEBUGLEVEL < 10) return; for (i=0;i<num_examples;i++) { char *name=NULL; asprintf(&name, "%s/rpclog/%s-%u.%d.%s", lp_lockdir(global_loadparm), ndr->name, opnum, i, (flags&NDR_IN)?"in":"out"); if (name == NULL) { return; } if (!file_exist(name)) { if (file_save(name, pkt->data, pkt->length)) { DEBUG(10,("Logged rpc packet to %s\n", name)); } free(name); break; } free(name); }}/* create a secondary context from a primary connection this uses dcerpc_alter_context() to create a new dcerpc context_id*/_PUBLIC_ NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p, struct dcerpc_pipe **pp2, const struct ndr_interface_table *table){ NTSTATUS status; struct dcerpc_pipe *p2; p2 = talloc_zero(p, struct dcerpc_pipe); if (p2 == NULL) { return NT_STATUS_NO_MEMORY; } p2->conn = talloc_reference(p2, p->conn); p2->request_timeout = p->request_timeout; p2->context_id = ++p->conn->next_context_id; p2->syntax = table->syntax_id; p2->transfer_syntax = ndr_transfer_syntax; p2->binding = talloc_reference(p2, p->binding); status = dcerpc_alter_context(p2, p2, &p2->syntax, &p2->transfer_syntax); if (!NT_STATUS_IS_OK(status)) { talloc_free(p2); return status; } *pp2 = p2; return NT_STATUS_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -