static struct cli_state *connect_one(const char *share) { struct cli_state *c; struct sockaddr_storage ss; NTSTATUS nt_status; uint32_t flags = 0; zero_sockaddr(&ss); if (get_cmdline_auth_info_use_machine_account() && !set_cmdline_auth_info_machine_account_creds()) { return NULL; } if (get_cmdline_auth_info_use_kerberos()) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS | CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; } if (!get_cmdline_auth_info_got_pass()) { char *pass = getpass("Password: "******"?????", get_cmdline_auth_info_username(), lp_workgroup(), get_cmdline_auth_info_password(), flags, get_cmdline_auth_info_signing_state(), NULL); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); return NULL; } if (get_cmdline_auth_info_smb_encrypt()) { nt_status = cli_cm_force_encryption(c, get_cmdline_auth_info_username(), get_cmdline_auth_info_password(), lp_workgroup(), share); if (!NT_STATUS_IS_OK(nt_status)) { cli_shutdown(c); return NULL; } } return c; }
NTSTATUS connect_to_ipc_krb5(struct net_context *c, struct cli_state **cli_ctx, struct sockaddr_storage *server_ss, const char *server_name) { NTSTATUS nt_status; char *user_and_realm = NULL; /* FIXME: Should get existing kerberos ticket if possible. */ c->opt_password = net_prompt_pass(c, c->opt_user_name); if (!c->opt_password) { return NT_STATUS_NO_MEMORY; } user_and_realm = get_user_and_realm(c->opt_user_name); if (!user_and_realm) { return NT_STATUS_NO_MEMORY; } nt_status = cli_full_connection(cli_ctx, NULL, server_name, server_ss, c->opt_port, "IPC$", "IPC", user_and_realm, c->opt_workgroup, c->opt_password, CLI_FULL_CONNECTION_USE_KERBEROS, Undefined); SAFE_FREE(user_and_realm); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1,("Cannot connect to server using kerberos. Error was %s\n", nt_errstr(nt_status))); return nt_status; } if (c->smb_encrypt) { nt_status = cli_cm_force_encryption(*cli_ctx, user_and_realm, c->opt_password, c->opt_workgroup, "IPC$"); if (!NT_STATUS_IS_OK(nt_status)) { cli_shutdown(*cli_ctx); *cli_ctx = NULL; } } return nt_status; }
static struct cli_state *connect_one(const char *share) { struct cli_state *c; NTSTATUS nt_status; uint32_t flags = 0; if (get_cmdline_auth_info_use_machine_account(smbcquotas_auth_info) && !set_cmdline_auth_info_machine_account_creds(smbcquotas_auth_info)) { return NULL; } if (get_cmdline_auth_info_use_kerberos(smbcquotas_auth_info)) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS | CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; } set_cmdline_auth_info_getpass(smbcquotas_auth_info); nt_status = cli_full_connection(&c, lp_netbios_name(), server, NULL, 0, share, "?????", get_cmdline_auth_info_username(smbcquotas_auth_info), lp_workgroup(), get_cmdline_auth_info_password(smbcquotas_auth_info), flags, get_cmdline_auth_info_signing_state(smbcquotas_auth_info)); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); return NULL; } if (get_cmdline_auth_info_smb_encrypt(smbcquotas_auth_info)) { nt_status = cli_cm_force_encryption(c, get_cmdline_auth_info_username(smbcquotas_auth_info), get_cmdline_auth_info_password(smbcquotas_auth_info), lp_workgroup(), share); if (!NT_STATUS_IS_OK(nt_status)) { cli_shutdown(c); return NULL; } } return c; }
NTSTATUS connect_to_ipc_krb5(struct cli_state **c, struct sockaddr_storage *server_ss, const char *server_name) { NTSTATUS nt_status; char *user_and_realm = NULL; opt_password = net_prompt_pass(opt_user_name); if (!opt_password) { return NT_STATUS_NO_MEMORY; } user_and_realm = get_user_and_realm(opt_user_name); if (!user_and_realm) { return NT_STATUS_NO_MEMORY; } nt_status = cli_full_connection(c, NULL, server_name, server_ss, opt_port, "IPC$", "IPC", user_and_realm, opt_workgroup, opt_password, CLI_FULL_CONNECTION_USE_KERBEROS, Undefined, NULL); SAFE_FREE(user_and_realm); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1,("Cannot connect to server using kerberos. Error was %s\n", nt_errstr(nt_status))); return nt_status; } if (smb_encrypt) { nt_status = cli_cm_force_encryption(*c, user_and_realm, opt_password, opt_workgroup, "IPC$"); if (!NT_STATUS_IS_OK(nt_status)) { cli_shutdown(*c); *c = NULL; } } return nt_status; }
static struct cli_state * smb_complete_connection(const char *myname, const char *server, int port, const char *username, const char *password, const char *workgroup, const char *share, int flags, bool *need_auth) { struct cli_state *cli; /* New connection */ NTSTATUS nt_status; /* Start the SMB connection */ *need_auth = false; nt_status = cli_start_connection(&cli, myname, server, NULL, port, Undefined, flags); if (!NT_STATUS_IS_OK(nt_status)) { fprintf(stderr, "ERROR: Connection failed: %s\n", nt_errstr(nt_status)); return NULL; } /* * We pretty much guarantee password must be valid or a pointer to a * 0 char. */ if (!password) { *need_auth = true; return NULL; } nt_status = cli_session_setup(cli, username, password, strlen(password) + 1, password, strlen(password) + 1, workgroup); if (!NT_STATUS_IS_OK(nt_status)) { fprintf(stderr, "ERROR: Session setup failed: %s\n", nt_errstr(nt_status)); if (get_exit_code(cli, nt_status) == 2) { *need_auth = true; } cli_shutdown(cli); return NULL; } nt_status = cli_tcon_andx(cli, share, "?????", password, strlen(password) + 1); if (!NT_STATUS_IS_OK(nt_status)) { fprintf(stderr, "ERROR: Tree connect failed (%s)\n", nt_errstr(nt_status)); if (get_exit_code(cli, nt_status) == 2) { *need_auth = true; } cli_shutdown(cli); return NULL; } #if 0 /* Need to work out how to specify this on the URL. */ if (smb_encrypt) { if (!cli_cm_force_encryption(cli, username, password, workgroup, share)) { fprintf(stderr, "ERROR: encryption setup failed\n"); cli_shutdown(cli); return NULL; } } #endif return cli; }
static NTSTATUS do_connect(TALLOC_CTX *ctx, const char *server, const char *share, const struct user_auth_info *auth_info, bool show_sessetup, bool force_encrypt, int max_protocol, int port, int name_type, struct cli_state **pcli) { struct cli_state *c = NULL; char *servicename; char *sharename; char *newserver, *newshare; const char *username; const char *password; NTSTATUS status; int flags = 0; /* make a copy so we don't modify the global string 'service' */ servicename = talloc_strdup(ctx,share); if (!servicename) { return NT_STATUS_NO_MEMORY; } sharename = servicename; if (*sharename == '\\') { sharename += 2; if (server == NULL) { server = sharename; } sharename = strchr_m(sharename,'\\'); if (!sharename) { return NT_STATUS_NO_MEMORY; } *sharename = 0; sharename++; } if (server == NULL) { return NT_STATUS_INVALID_PARAMETER; } if (get_cmdline_auth_info_use_kerberos(auth_info)) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } if (get_cmdline_auth_info_fallback_after_kerberos(auth_info)) { flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; } if (get_cmdline_auth_info_use_ccache(auth_info)) { flags |= CLI_FULL_CONNECTION_USE_CCACHE; } status = cli_connect_nb( server, NULL, port, name_type, NULL, get_cmdline_auth_info_signing_state(auth_info), flags, &c); if (!NT_STATUS_IS_OK(status)) { d_printf("Connection to %s failed (Error %s)\n", server, nt_errstr(status)); return status; } if (max_protocol == 0) { max_protocol = PROTOCOL_NT1; } DEBUG(4,(" session request ok\n")); status = cli_negprot(c, max_protocol); if (!NT_STATUS_IS_OK(status)) { d_printf("protocol negotiation failed: %s\n", nt_errstr(status)); cli_shutdown(c); return status; } username = get_cmdline_auth_info_username(auth_info); password = get_cmdline_auth_info_password(auth_info); status = cli_session_setup(c, username, password, strlen(password), password, strlen(password), lp_workgroup()); if (!NT_STATUS_IS_OK(status)) { /* If a password was not supplied then * try again with a null username. */ if (password[0] || !username[0] || get_cmdline_auth_info_use_kerberos(auth_info) || !NT_STATUS_IS_OK(status = cli_session_setup(c, "", "", 0, "", 0, lp_workgroup()))) { d_printf("session setup failed: %s\n", nt_errstr(status)); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) d_printf("did you forget to run kinit?\n"); cli_shutdown(c); return status; } d_printf("Anonymous login successful\n"); status = cli_init_creds(c, "", lp_workgroup(), ""); } else { status = cli_init_creds(c, username, lp_workgroup(), password); } if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("cli_init_creds() failed: %s\n", nt_errstr(status))); cli_shutdown(c); return status; } if ( show_sessetup ) { if (*c->server_domain) { DEBUG(0,("Domain=[%s] OS=[%s] Server=[%s]\n", c->server_domain,c->server_os,c->server_type)); } else if (*c->server_os || *c->server_type) { DEBUG(0,("OS=[%s] Server=[%s]\n", c->server_os,c->server_type)); } } 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 ((cli_state_capabilities(c) & CAP_DFS) && cli_check_msdfs_proxy(ctx, c, sharename, &newserver, &newshare, force_encrypt, username, password, lp_workgroup())) { cli_shutdown(c); return do_connect(ctx, newserver, newshare, auth_info, false, force_encrypt, max_protocol, port, name_type, pcli); } /* must be a normal share */ status = cli_tree_connect(c, sharename, "?????", password, strlen(password)+1); if (!NT_STATUS_IS_OK(status)) { d_printf("tree connect failed: %s\n", nt_errstr(status)); cli_shutdown(c); return status; } if (force_encrypt) { status = cli_cm_force_encryption(c, username, password, lp_workgroup(), sharename); if (!NT_STATUS_IS_OK(status)) { cli_shutdown(c); return status; } } DEBUG(4,(" tconx ok\n")); *pcli = c; return NT_STATUS_OK; }
bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, struct cli_state *cli, const char *sharename, char **pp_newserver, char **pp_newshare, bool force_encrypt, const char *username, const char *password, const char *domain) { struct client_dfs_referral *refs = NULL; size_t num_refs = 0; size_t consumed = 0; char *fullpath = NULL; bool res; uint16 cnum; char *newextrapath = NULL; NTSTATUS status; const char *remote_name; if (!cli || !sharename) { return false; } remote_name = cli_state_remote_name(cli); cnum = cli_state_get_tid(cli); /* special case. never check for a referral on the IPC$ share */ if (strequal(sharename, "IPC$")) { return false; } /* send a trans2_query_path_info to check for a referral */ fullpath = talloc_asprintf(ctx, "\\%s\\%s", remote_name, sharename); if (!fullpath) { return false; } /* check for the referral */ if (!NT_STATUS_IS_OK(cli_tree_connect(cli, "IPC$", "IPC", NULL, 0))) { return false; } if (force_encrypt) { status = cli_cm_force_encryption(cli, username, password, lp_workgroup(), "IPC$"); if (!NT_STATUS_IS_OK(status)) { return false; } } status = cli_dfs_get_referral(ctx, cli, fullpath, &refs, &num_refs, &consumed); res = NT_STATUS_IS_OK(status); status = cli_tdis(cli); if (!NT_STATUS_IS_OK(status)) { return false; } cli_state_set_tid(cli, cnum); if (!res || !num_refs) { return false; } if (!refs[0].dfspath) { return false; } if (!split_dfs_path(ctx, refs[0].dfspath, pp_newserver, pp_newshare, &newextrapath)) { return false; } /* check that this is not a self-referral */ if (strequal(remote_name, *pp_newserver) && strequal(sharename, *pp_newshare)) { return false; } return true; }
/* * 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 encryption. */ nt_status = cli_cm_force_encryption(ipc_cli, *pp_username, *pp_password, *pp_workgroup, "IPC$"); if (!NT_STATUS_IS_OK(nt_status)) { /* * 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; }