📄 cliconnect.c
字号:
/* allow hostnames of the form NAME#xx and do a netbios lookup */ if ((p = strchr(cli->desthost, '#'))) { name_type = strtol(p+1, NULL, 16); *p = 0; } if (!ip || is_zero_ip(*ip)) { if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) { return False; } if (ip) *ip = cli->dest_ip; } else { cli->dest_ip = *ip; } if (getenv("LIBSMB_PROG")) { cli->fd = sock_exec(getenv("LIBSMB_PROG")); } else { /* try 445 first, then 139 */ int port = cli->port?cli->port:445; cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, cli->timeout); if (cli->fd == -1 && cli->port == 0) { port = 139; cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, cli->timeout); } if (cli->fd != -1) cli->port = port; } if (cli->fd == -1) { DEBUG(1,("Error connecting to %s (%s)\n", ip?inet_ntoa(*ip):host,strerror(errno))); return False; } set_socket_options(cli->fd,user_socket_options); return True;}/** establishes a connection to after the negprot. @param output_cli A fully initialised cli structure, non-null only on success @param dest_host The netbios name of the remote host @param dest_ip (optional) The the destination IP, NULL for name based lookup @param port (optional) The destination port (0 for default) @param retry BOOL. Did this connection fail with a retryable error ?*/NTSTATUS cli_start_connection(struct cli_state **output_cli, const char *my_name, const char *dest_host, struct in_addr *dest_ip, int port, int signing_state, int flags, BOOL *retry) { NTSTATUS nt_status; struct nmb_name calling; struct nmb_name called; struct cli_state *cli; struct in_addr ip; if (retry) *retry = False; if (!my_name) my_name = global_myname(); if (!(cli = cli_initialise(NULL))) return NT_STATUS_NO_MEMORY; make_nmb_name(&calling, my_name, 0x0); make_nmb_name(&called , dest_host, 0x20); if (cli_set_port(cli, port) != port) { cli_shutdown(cli); return NT_STATUS_UNSUCCESSFUL; } cli_set_timeout(cli, 10000); /* 10 seconds. */ if (dest_ip) ip = *dest_ip; else ZERO_STRUCT(ip);again: DEBUG(3,("Connecting to host=%s\n", dest_host)); if (!cli_connect(cli, dest_host, &ip)) { DEBUG(1,("cli_start_connection: failed to connect to %s (%s)\n", nmb_namestr(&called), inet_ntoa(ip))); cli_shutdown(cli); return NT_STATUS_UNSUCCESSFUL; } if (retry) *retry = True; if (!cli_session_request(cli, &calling, &called)) { char *p; DEBUG(1,("session request to %s failed (%s)\n", called.name, cli_errstr(cli))); if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) { *p = 0; goto again; } if (strcmp(called.name, "*SMBSERVER")) { make_nmb_name(&called , "*SMBSERVER", 0x20); goto again; } return NT_STATUS_UNSUCCESSFUL; } cli_setup_signing_state(cli, signing_state); if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) cli->use_spnego = False; else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) cli->use_kerberos = True; if (!cli_negprot(cli)) { DEBUG(1,("failed negprot\n")); nt_status = NT_STATUS_UNSUCCESSFUL; cli_shutdown(cli); return nt_status; } *output_cli = cli; return NT_STATUS_OK;}/** establishes a connection right up to doing tconX, password specified. @param output_cli A fully initialised cli structure, non-null only on success @param dest_host The netbios name of the remote host @param dest_ip (optional) The the destination IP, NULL for name based lookup @param port (optional) The destination port (0 for default) @param service (optional) The share to make the connection to. Should be 'unqualified' in any way. @param service_type The 'type' of serivice. @param user Username, unix string @param domain User's domain @param password User's password, unencrypted unix string. @param retry BOOL. Did this connection fail with a retryable error ?*/NTSTATUS cli_full_connection(struct cli_state **output_cli, const char *my_name, const char *dest_host, struct in_addr *dest_ip, int port, const char *service, const char *service_type, const char *user, const char *domain, const char *password, int flags, int signing_state, BOOL *retry) { NTSTATUS nt_status; struct cli_state *cli = NULL; nt_status = cli_start_connection(&cli, my_name, dest_host, dest_ip, port, signing_state, flags, retry); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } if (!cli_session_setup(cli, user, password, strlen(password)+1, password, strlen(password)+1, domain)) { if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK) && cli_session_setup(cli, "", "", 0, "", 0, domain)) { } else { nt_status = cli_nt_error(cli); DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status))); cli_shutdown(cli); if (NT_STATUS_IS_OK(nt_status)) nt_status = NT_STATUS_UNSUCCESSFUL; return nt_status; } } if (service) { if (!cli_send_tconX(cli, service, service_type, password, strlen(password)+1)) { nt_status = cli_nt_error(cli); DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status))); cli_shutdown(cli); if (NT_STATUS_IS_OK(nt_status)) { nt_status = NT_STATUS_UNSUCCESSFUL; } return nt_status; } } cli_init_creds(cli, user, domain, password); *output_cli = cli; return NT_STATUS_OK;}/**************************************************************************** Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.****************************************************************************/BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost, struct in_addr *pdest_ip){ struct nmb_name calling, called; make_nmb_name(&calling, srchost, 0x0); /* * If the called name is an IP address * then use *SMBSERVER immediately. */ if(is_ipaddress(desthost)) make_nmb_name(&called, "*SMBSERVER", 0x20); else make_nmb_name(&called, desthost, 0x20); if (!cli_session_request(cli, &calling, &called)) { struct nmb_name smbservername; make_nmb_name(&smbservername , "*SMBSERVER", 0x20); /* * If the name wasn't *SMBSERVER then * try with *SMBSERVER if the first name fails. */ if (nmb_name_equal(&called, &smbservername)) { /* * The name used was *SMBSERVER, don't bother with another name. */ DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \with error %s.\n", desthost, cli_errstr(cli) )); return False; } /* * We need to close the connection here but can't call cli_shutdown as * will free an allocated cli struct. cli_close_connection was invented * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>. */ cli_close_connection(cli); if (!cli_initialise(cli) || !cli_connect(cli, desthost, pdest_ip) || !cli_session_request(cli, &calling, &smbservername)) { DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) )); return False; } } return True;}/**************************************************************************** Send an old style tcon.****************************************************************************/NTSTATUS cli_raw_tcon(struct cli_state *cli, const char *service, const char *pass, const char *dev, uint16 *max_xmit, uint16 *tid){ char *p; if (!lp_client_plaintext_auth() && (*pass)) { DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" " is disabled\n")); return NT_STATUS_ACCESS_DENIED; } memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf, 0, 0, True); SCVAL(cli->outbuf,smb_com,SMBtcon); cli_setup_packet(cli); p = smb_buf(cli->outbuf); *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN); *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN); *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN); cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { return NT_STATUS_UNEXPECTED_NETWORK_ERROR; } if (cli_is_error(cli)) { return cli_nt_error(cli); } *max_xmit = SVAL(cli->inbuf, smb_vwv0); *tid = SVAL(cli->inbuf, smb_vwv1); return NT_STATUS_OK;}/* Return a cli_state pointing at the IPC$ share for the given server */struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip, struct user_auth_info *user_info){ struct cli_state *cli; pstring myname; NTSTATUS nt_status; get_myname(myname); nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC", user_info->username, lp_workgroup(), user_info->password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL); if (NT_STATUS_IS_OK(nt_status)) { return cli; } else if (is_ipaddress(server)) { /* windows 9* needs a correct NMB name for connections */ fstring remote_name; if (name_status_find("*", 0, 0, *server_ip, remote_name)) { cli = get_ipc_connect(remote_name, server_ip, user_info); if (cli) return cli; } } return NULL;}/* * Given the IP address of a master browser on the network, return its * workgroup and connect to it. * * This function is provided to allow additional processing beyond what * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master * browsers and obtain each master browsers' list of domains (in case the * first master browser is recently on the network and has not yet * synchronized with other master browsers and therefore does not yet have the * entire network browse list) */struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info){ static fstring name; struct cli_state *cli; struct in_addr server_ip; DEBUG(99, ("Looking up name of master browser %s\n", inet_ntoa(mb_ip->ip))); /* * Do a name status query to find out the name of the master browser. * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain * master browser will not respond to a wildcard query (or, at least, * an NT4 server acting as the domain master browser will not). * * We might be able to use ONLY the query on MSBROWSE, but that's not * yet been tested with all Windows versions, so until it is, leave * the original wildcard query as the first choice and fall back to * MSBROWSE if the wildcard query fails. */ if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) && !name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) { DEBUG(99, ("Could not retrieve name status for %s\n", inet_ntoa(mb_ip->ip))); return NULL; } if (!find_master_ip(name, &server_ip)) { DEBUG(99, ("Could not find master ip for %s\n", name)); return NULL; } pstrcpy(workgroup, name); DEBUG(4, ("found master browser %s, %s\n", name, inet_ntoa(mb_ip->ip))); cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info); return cli; }/* * Return the IP address and workgroup of a master browser on the network, and * connect to it. */struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info){ struct ip_service *ip_list; struct cli_state *cli; int i, count; DEBUG(99, ("Do broadcast lookup for workgroups on local network\n")); /* Go looking for workgroups by broadcasting on the local network */ if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) { DEBUG(99, ("No master browsers responded\n")); return False; } for (i = 0; i < count; i++) { DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip))); cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info); if (cli) return(cli); } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -