static struct cli_state *cli_cm_find(struct cli_state *cli, const char *server, const char *share) { struct cli_state *p; if (cli == NULL) { return NULL; } /* Search to the start of the list. */ for (p = cli; p; p = DLIST_PREV(p)) { const char *remote_name = smbXcli_conn_remote_name(p->conn); if (strequal(server, remote_name) && strequal(share,p->share)) { return p; } } /* Search to the end of the list. */ for (p = cli->next; p; p = p->next) { const char *remote_name = smbXcli_conn_remote_name(p->conn); if (strequal(server, remote_name) && strequal(share,p->share)) { return p; } } return NULL; }
static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc, const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { struct client_pipe_connection *p; for (p = ipc->pipe_connections; p; p = p->next) { const char *ipc_remote_name; if (!rpccli_is_connected(p->pipe)) { return NT_STATUS_PIPE_EMPTY; } ipc_remote_name = smbXcli_conn_remote_name(ipc->cli->conn); if (strequal(ipc_remote_name, p->pipe->desthost) && ndr_syntax_id_equal(&p->pipe->abstract_syntax, &table->syntax_id)) { *presult = p->pipe; return NT_STATUS_OK; } } return NT_STATUS_PIPE_NOT_AVAILABLE; }
void cli_cm_display(struct cli_state *cli) { int i; for (i=0; cli; cli = cli->next,i++ ) { d_printf("%d:\tserver=%s, share=%s\n", i, smbXcli_conn_remote_name(cli->conn), cli->share); } }
static struct client_ipc_connection *ipc_cm_find( struct libnetapi_private_ctx *priv_ctx, const char *server_name) { struct client_ipc_connection *p; for (p = priv_ctx->ipc_connections; p; p = p->next) { const char *remote_name = smbXcli_conn_remote_name(p->cli->conn); if (strequal(remote_name, server_name)) { return p; } } return NULL; }
static int rap_printq_info(struct net_context *c, int argc, const char **argv) { struct cli_state *cli; int ret; if (argc == 0 || c->display_usage) return net_rap_printq_usage(c, argc, argv); if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli))) return -1; d_printf(PRINTQ_ENUM_DISPLAY, smbXcli_conn_remote_name(cli->conn)); /* list header */ ret = cli_NetPrintQGetInfo(cli, argv[0], enum_queue, enum_jobs); cli_shutdown(cli); return ret; }
int net_rap_printq(struct net_context *c, int argc, const char **argv) { struct cli_state *cli; int ret; struct functable func[] = { { "info", rap_printq_info, NET_TRANSPORT_RAP, N_("Display info about print queues and jobs"), N_("net rap printq info [queue]\n" " Display info about print jobs in queue.\n" " If queue is not specified, all queues are " "listed") }, { "delete", rap_printq_delete, NET_TRANSPORT_RAP, N_("Delete print job(s)"), N_("net rap printq delete\n" " Delete print job(s)") }, {NULL, NULL, 0, NULL, NULL} }; if (argc == 0) { if (c->display_usage) { d_printf(_("Usage:\n")); d_printf(_("net rap printq\n" " List the print queue\n")); net_display_usage_from_functable(func); return 0; } if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli))) return -1; d_printf(PRINTQ_ENUM_DISPLAY, smbXcli_conn_remote_name(cli->conn)); /* list header */ ret = cli_NetPrintQEnum(cli, enum_queue, enum_jobs); cli_shutdown(cli); return ret; } return net_run_function(c, argc, argv, "net rap printq", func); }
static char *cli_dfs_make_full_path(TALLOC_CTX *ctx, struct cli_state *cli, const char *dir) { char path_sep = '\\'; /* Ensure the extrapath doesn't start with a separator. */ while (IS_DIRECTORY_SEP(*dir)) { dir++; } if (cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) { path_sep = '/'; } return talloc_asprintf(ctx, "%c%s%c%s%c%s", path_sep, smbXcli_conn_remote_name(cli->conn), path_sep, cli->share, path_sep, dir); }
/* Modern, all singing, all dancing extended security (and possibly SPNEGO) request */ static NTSTATUS session_setup_spnego(struct composite_context *c, struct smbcli_session *session, struct smb_composite_sesssetup *io, struct smbcli_request **req) { struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); NTSTATUS status; const char *chosen_oid = NULL; state->setup.spnego.level = RAW_SESSSETUP_SPNEGO; state->setup.spnego.in.bufsize = session->transport->options.max_xmit; state->setup.spnego.in.mpx_max = session->transport->options.max_mux; state->setup.spnego.in.vc_num = 1; state->setup.spnego.in.sesskey = io->in.sesskey; state->setup.spnego.in.capabilities = io->in.capabilities; state->setup.spnego.in.os = "Unix"; state->setup.spnego.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING); state->setup.spnego.in.workgroup = io->in.workgroup; status = gensec_client_start(session, &session->gensec, io->in.gensec_settings); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status))); return status; } gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY); status = gensec_set_credentials(session->gensec, io->in.credentials); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client credentials: %s\n", nt_errstr(status))); return status; } status = gensec_set_target_hostname(session->gensec, smbXcli_conn_remote_name(session->transport->conn)); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", nt_errstr(status))); return status; } status = gensec_set_target_service(session->gensec, "cifs"); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC target service: %s\n", nt_errstr(status))); return status; } if (session->transport->negotiate.secblob.length) { chosen_oid = GENSEC_OID_SPNEGO; status = gensec_start_mech_by_oid(session->gensec, chosen_oid); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client mechanism %s: %s\n", gensec_get_name_by_oid(session->gensec, chosen_oid), nt_errstr(status))); chosen_oid = GENSEC_OID_NTLMSSP; status = gensec_start_mech_by_oid(session->gensec, chosen_oid); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set (fallback) GENSEC client mechanism %s: %s\n", gensec_get_name_by_oid(session->gensec, chosen_oid), nt_errstr(status))); return status; } } } else { /* without a sec blob, means raw NTLMSSP */ chosen_oid = GENSEC_OID_NTLMSSP; status = gensec_start_mech_by_oid(session->gensec, chosen_oid); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client mechanism %s: %s\n", gensec_get_name_by_oid(session->gensec, chosen_oid), nt_errstr(status))); } } if (strequal(chosen_oid, GENSEC_OID_SPNEGO)) { status = gensec_update(session->gensec, state, c->event_ctx, session->transport->negotiate.secblob, &state->setup.spnego.in.secblob); } else { status = gensec_update(session->gensec, state, c->event_ctx, data_blob(NULL, 0), &state->setup.spnego.in.secblob); } if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed initial gensec_update with mechanism %s: %s\n", gensec_get_name_by_oid(session->gensec, chosen_oid), nt_errstr(status))); return status; } state->gensec_status = status; *req = smb_raw_sesssetup_send(session, &state->setup); if (!*req) { return NT_STATUS_NO_MEMORY; } /* * we need to check the signature ourself * as the session key might be the acceptor subkey * which comes within the response itself */ if (!smb1cli_conn_signing_is_active((*req)->transport->conn)) { (*req)->sign_caller_checks = true; } return (*req)->status; }
/* * Connect to a server for getting/setting attributes, possibly on an existing * connection. This works similarly to SMBC_server(). */ SMBCSRV * SMBC_attr_server(TALLOC_CTX *ctx, SMBCCTX *context, const char *server, uint16_t port, const char *share, char **pp_workgroup, char **pp_username, char **pp_password) { int flags; struct cli_state *ipc_cli = NULL; struct rpc_pipe_client *pipe_hnd = NULL; NTSTATUS nt_status; SMBCSRV *srv=NULL; SMBCSRV *ipc_srv=NULL; /* * Use srv->cli->desthost and srv->cli->share instead of * server and share below to connect to the actual share, * i.e., a normal share or a referred share from * 'msdfs proxy' share. */ srv = SMBC_server(ctx, context, true, server, port, share, pp_workgroup, pp_username, pp_password); if (!srv) { return NULL; } server = smbXcli_conn_remote_name(srv->cli->conn); share = srv->cli->share; /* * See if we've already created this special connection. Reference * our "special" share name '*IPC$', which is an impossible real share * name due to the leading asterisk. */ ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$", pp_workgroup, pp_username, pp_password); if (!ipc_srv) { int signing_state = SMB_SIGNING_DEFAULT; /* We didn't find a cached connection. Get the password */ if (!*pp_password || (*pp_password)[0] == '\0') { /* ... then retrieve it now. */ SMBC_call_auth_fn(ctx, context, server, share, pp_workgroup, pp_username, pp_password); if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; return NULL; } } flags = 0; if (smbc_getOptionUseKerberos(context)) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } if (smbc_getOptionUseCCache(context)) { flags |= CLI_FULL_CONNECTION_USE_CCACHE; } if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) { signing_state = SMB_SIGNING_REQUIRED; } nt_status = cli_full_connection(&ipc_cli, lp_netbios_name(), server, NULL, 0, "IPC$", "?????", *pp_username, *pp_workgroup, *pp_password, flags, signing_state); if (! NT_STATUS_IS_OK(nt_status)) { DEBUG(1,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); errno = ENOTSUP; return NULL; } if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, *pp_username, *pp_password, *pp_workgroup))) { /* * context->smb_encryption_level == * 1 means don't fail if encryption can't be * negotiated, == 2 means fail if encryption * can't be negotiated. */ DEBUG(4,(" SMB encrypt failed on IPC$\n")); if (context->internal->smb_encryption_level == 2) { cli_shutdown(ipc_cli); errno = EPERM; return NULL; } } DEBUG(4,(" SMB encrypt ok on IPC$\n")); } ipc_srv = SMB_MALLOC_P(SMBCSRV); if (!ipc_srv) { errno = ENOMEM; cli_shutdown(ipc_cli); return NULL; } ZERO_STRUCTP(ipc_srv); DLIST_ADD(ipc_srv->cli, ipc_cli); nt_status = cli_rpc_pipe_open_noauth( ipc_srv->cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("cli_nt_session_open fail!\n")); errno = ENOTSUP; cli_shutdown(ipc_srv->cli); free(ipc_srv); return NULL; } /* * Some systems don't support * SEC_FLAG_MAXIMUM_ALLOWED, but NT sends 0x2000000 * so we might as well do it too. */ nt_status = rpccli_lsa_open_policy( pipe_hnd, talloc_tos(), True, GENERIC_EXECUTE_ACCESS, &ipc_srv->pol); if (!NT_STATUS_IS_OK(nt_status)) { errno = SMBC_errno(context, ipc_srv->cli); cli_shutdown(ipc_srv->cli); free(ipc_srv); return NULL; } /* now add it to the cache (internal or external) */ errno = 0; /* let cache function set errno if it likes */ if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv, server, "*IPC$", *pp_workgroup, *pp_username)) { DEBUG(3, (" Failed to add server to cache\n")); if (errno == 0) { errno = ENOMEM; } cli_shutdown(ipc_srv->cli); free(ipc_srv); return NULL; } DLIST_ADD(context->internal->servers, ipc_srv); } return ipc_srv; }
static SMBCSRV * SMBC_server_internal(TALLOC_CTX *ctx, SMBCCTX *context, bool connect_if_not_found, const char *server, uint16_t port, const char *share, char **pp_workgroup, char **pp_username, char **pp_password, bool *in_cache) { SMBCSRV *srv=NULL; char *workgroup = NULL; struct cli_state *c = NULL; const char *server_n = server; int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0); uint32_t fs_attrs = 0; const char *username_used; NTSTATUS status; char *newserver, *newshare; int flags = 0; struct smbXcli_tcon *tcon = NULL; int signing_state = SMB_SIGNING_DEFAULT; ZERO_STRUCT(c); *in_cache = false; if (server[0] == 0) { errno = EPERM; return NULL; } /* Look for a cached connection */ srv = SMBC_find_server(ctx, context, server, share, pp_workgroup, pp_username, pp_password); /* * If we found a connection and we're only allowed one share per * server... */ if (srv && share != NULL && *share != '\0' && smbc_getOptionOneSharePerServer(context)) { /* * ... then if there's no current connection to the share, * connect to it. SMBC_find_server(), or rather the function * pointed to by context->get_cached_srv_fn which * was called by SMBC_find_server(), will have issued a tree * disconnect if the requested share is not the same as the * one that was already connected. */ /* * Use srv->cli->desthost and srv->cli->share instead of * server and share below to connect to the actual share, * i.e., a normal share or a referred share from * 'msdfs proxy' share. */ if (!cli_state_has_tcon(srv->cli)) { /* Ensure we have accurate auth info */ SMBC_call_auth_fn(ctx, context, smbXcli_conn_remote_name(srv->cli->conn), srv->cli->share, pp_workgroup, pp_username, pp_password); if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; cli_shutdown(srv->cli); srv->cli = NULL; smbc_getFunctionRemoveCachedServer(context)(context, srv); return NULL; } /* * We don't need to renegotiate encryption * here as the encryption context is not per * tid. */ status = cli_tree_connect(srv->cli, srv->cli->share, "?????", *pp_password, strlen(*pp_password)+1); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); cli_shutdown(srv->cli); srv->cli = NULL; smbc_getFunctionRemoveCachedServer(context)(context, srv); srv = NULL; } /* Determine if this share supports case sensitivity */ if (is_ipc) { DEBUG(4, ("IPC$ so ignore case sensitivity\n")); status = NT_STATUS_OK; } else { status = cli_get_fs_attr_info(c, &fs_attrs); } if (!NT_STATUS_IS_OK(status)) { DEBUG(4, ("Could not retrieve " "case sensitivity flag: %s.\n", nt_errstr(status))); /* * We can't determine the case sensitivity of * the share. We have no choice but to use the * user-specified case sensitivity setting. */ if (smbc_getOptionCaseSensitive(context)) { cli_set_case_sensitive(c, True); } else { cli_set_case_sensitive(c, False); } } else if (!is_ipc) { DEBUG(4, ("Case sensitive: %s\n", (fs_attrs & FILE_CASE_SENSITIVE_SEARCH ? "True" : "False"))); cli_set_case_sensitive( c, (fs_attrs & FILE_CASE_SENSITIVE_SEARCH ? True : False)); } /* * Regenerate the dev value since it's based on both * server and share */ if (srv) { const char *remote_name = smbXcli_conn_remote_name(srv->cli->conn); srv->dev = (dev_t)(str_checksum(remote_name) ^ str_checksum(srv->cli->share)); } } } /* If we have a connection... */ if (srv) { /* ... then we're done here. Give 'em what they came for. */ *in_cache = true; goto done; } /* If we're not asked to connect when a connection doesn't exist... */ if (! connect_if_not_found) { /* ... then we're done here. */ return NULL; } if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; return NULL; } DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); status = NT_STATUS_UNSUCCESSFUL; if (smbc_getOptionUseKerberos(context)) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } if (smbc_getOptionFallbackAfterKerberos(context)) { flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; } if (smbc_getOptionUseCCache(context)) { flags |= CLI_FULL_CONNECTION_USE_CCACHE; } if (smbc_getOptionUseNTHash(context)) { flags |= CLI_FULL_CONNECTION_USE_NT_HASH; } if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) { signing_state = SMB_SIGNING_REQUIRED; } if (port == 0) { if (share == NULL || *share == '\0' || is_ipc) { /* * Try 139 first for IPC$ */ status = cli_connect_nb(server_n, NULL, NBT_SMB_PORT, 0x20, smbc_getNetbiosName(context), signing_state, flags, &c); } } if (!NT_STATUS_IS_OK(status)) { /* * No IPC$ or 139 did not work */ status = cli_connect_nb(server_n, NULL, port, 0x20, smbc_getNetbiosName(context), signing_state, flags, &c); } if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); return NULL; } cli_set_timeout(c, smbc_getTimeout(context)); status = smbXcli_negprot(c->conn, c->timeout, lp_client_min_protocol(), lp_client_max_protocol()); if (!NT_STATUS_IS_OK(status)) { cli_shutdown(c); errno = ETIMEDOUT; return NULL; } if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) { /* Ensure we ask for some initial credits. */ smb2cli_conn_set_max_credits(c->conn, DEFAULT_SMB2_MAX_CREDITS); } username_used = *pp_username; if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, strlen(*pp_password), *pp_password, strlen(*pp_password), *pp_workgroup))) { /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; if (smbc_getOptionNoAutoAnonymousLogin(context) || !NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, 1, *pp_password, 0, *pp_workgroup))) { cli_shutdown(c); errno = EPERM; return NULL; } } DEBUG(4,(" session setup ok\n")); /* here's the fun part....to support 'msdfs proxy' shares (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL here before trying to connect to the original share. cli_check_msdfs_proxy() will fail if it is a normal share. */ if (smbXcli_conn_dfs_supported(c->conn) && cli_check_msdfs_proxy(ctx, c, share, &newserver, &newshare, /* FIXME: cli_check_msdfs_proxy() does not support smbc_smb_encrypt_level type */ context->internal->smb_encryption_level ? true : false, *pp_username, *pp_password, *pp_workgroup)) { cli_shutdown(c); srv = SMBC_server_internal(ctx, context, connect_if_not_found, newserver, port, newshare, pp_workgroup, pp_username, pp_password, in_cache); TALLOC_FREE(newserver); TALLOC_FREE(newshare); return srv; } /* must be a normal share */ status = cli_tree_connect(c, share, "?????", *pp_password, strlen(*pp_password)+1); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); cli_shutdown(c); return NULL; } DEBUG(4,(" tconx ok\n")); if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) { tcon = c->smb2.tcon; } else { tcon = c->smb1.tcon; } /* Determine if this share supports case sensitivity */ if (is_ipc) { DEBUG(4, ("IPC$ so ignore case sensitivity\n")); status = NT_STATUS_OK; } else { status = cli_get_fs_attr_info(c, &fs_attrs); } if (!NT_STATUS_IS_OK(status)) { DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n", nt_errstr(status))); /* * We can't determine the case sensitivity of the share. We * have no choice but to use the user-specified case * sensitivity setting. */ if (smbc_getOptionCaseSensitive(context)) { cli_set_case_sensitive(c, True); } else { cli_set_case_sensitive(c, False); } } else if (!is_ipc) { DEBUG(4, ("Case sensitive: %s\n", (fs_attrs & FILE_CASE_SENSITIVE_SEARCH ? "True" : "False"))); smbXcli_tcon_set_fs_attributes(tcon, fs_attrs); } if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(c, username_used, *pp_password, *pp_workgroup))) { /* * context->smb_encryption_level == 1 * means don't fail if encryption can't be negotiated, * == 2 means fail if encryption can't be negotiated. */ DEBUG(4,(" SMB encrypt failed\n")); if (context->internal->smb_encryption_level == 2) { cli_shutdown(c); errno = EPERM; return NULL; } } DEBUG(4,(" SMB encrypt ok\n")); } /* * Ok, we have got a nice connection * Let's allocate a server structure. */ srv = SMB_MALLOC_P(SMBCSRV); if (!srv) { cli_shutdown(c); errno = ENOMEM; return NULL; } ZERO_STRUCTP(srv); DLIST_ADD(srv->cli, c); srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); srv->no_pathinfo = False; srv->no_pathinfo2 = False; srv->no_pathinfo3 = False; srv->no_nt_session = False; done: if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) { workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context)); } else { workgroup = *pp_workgroup; } if(!workgroup) { if (c != NULL) { cli_shutdown(c); } SAFE_FREE(srv); return NULL; } /* set the credentials to make DFS work */ smbc_set_credentials_with_fallback(context, workgroup, *pp_username, *pp_password); return srv; }
NTSTATUS rpccli_setup_netlogon_creds_locked( struct cli_state *cli, enum dcerpc_transport_t transport, struct netlogon_creds_cli_context *creds_ctx, bool force_reauth, struct cli_credentials *cli_creds, uint32_t *negotiate_flags) { TALLOC_CTX *frame = talloc_stackframe(); struct rpc_pipe_client *netlogon_pipe = NULL; struct netlogon_creds_CredentialState *creds = NULL; uint8_t num_nt_hashes = 0; const struct samr_Password *nt_hashes[2] = { NULL, NULL }; uint8_t idx_nt_hashes = 0; NTSTATUS status; status = netlogon_creds_cli_get(creds_ctx, frame, &creds); if (NT_STATUS_IS_OK(status)) { const char *action = "using"; if (force_reauth) { action = "overwrite"; } DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n", __FUNCTION__, action, creds->account_name, creds->computer_name, smbXcli_conn_remote_name(cli->conn))); if (!force_reauth) { goto done; } TALLOC_FREE(creds); } nt_hashes[0] = cli_credentials_get_nt_hash(cli_creds, talloc_tos()); if (nt_hashes[0] == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } num_nt_hashes = 1; nt_hashes[1] = cli_credentials_get_old_nt_hash(cli_creds, talloc_tos()); if (nt_hashes[1] != NULL) { num_nt_hashes = 2; } status = cli_rpc_pipe_open_noauth_transport(cli, transport, &ndr_table_netlogon, &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n", __FUNCTION__, smbXcli_conn_remote_name(cli->conn), nt_errstr(status))); TALLOC_FREE(frame); return status; } talloc_steal(frame, netlogon_pipe); status = netlogon_creds_cli_auth(creds_ctx, netlogon_pipe->binding_handle, num_nt_hashes, nt_hashes, &idx_nt_hashes); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return status; } status = netlogon_creds_cli_get(creds_ctx, frame, &creds); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return NT_STATUS_INTERNAL_ERROR; } DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n", __FUNCTION__, creds->account_name, creds->computer_name, smbXcli_conn_remote_name(cli->conn))); done: if (negotiate_flags != NULL) { *negotiate_flags = creds->negotiate_flags; } TALLOC_FREE(frame); return NT_STATUS_OK; }
NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, enum dcerpc_transport_t transport, struct netlogon_creds_cli_context *netlogon_creds, bool force_reauth, struct samr_Password current_nt_hash, const struct samr_Password *previous_nt_hash) { TALLOC_CTX *frame = talloc_stackframe(); struct rpc_pipe_client *netlogon_pipe = NULL; struct netlogon_creds_CredentialState *creds = NULL; NTSTATUS status; status = netlogon_creds_cli_get(netlogon_creds, frame, &creds); if (NT_STATUS_IS_OK(status)) { const char *action = "using"; if (force_reauth) { action = "overwrite"; } DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n", __FUNCTION__, action, creds->account_name, creds->computer_name, smbXcli_conn_remote_name(cli->conn))); if (!force_reauth) { TALLOC_FREE(frame); return NT_STATUS_OK; } TALLOC_FREE(creds); } status = cli_rpc_pipe_open_noauth_transport(cli, transport, &ndr_table_netlogon, &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n", __FUNCTION__, smbXcli_conn_remote_name(cli->conn), nt_errstr(status))); TALLOC_FREE(frame); return status; } talloc_steal(frame, netlogon_pipe); status = netlogon_creds_cli_auth(netlogon_creds, netlogon_pipe->binding_handle, current_nt_hash, previous_nt_hash); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return status; } status = netlogon_creds_cli_get(netlogon_creds, frame, &creds); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return NT_STATUS_INTERNAL_ERROR; } DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n", __FUNCTION__, creds->account_name, creds->computer_name, smbXcli_conn_remote_name(cli->conn))); TALLOC_FREE(frame); return NT_STATUS_OK; }