uint8_t *p;
NTSTATUS status;
ssize_t ret;
+ uint8_t wct;
+ uint16_t *vwv;
- status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
+ status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
&num_bytes, &bytes);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
p = bytes;
cli->vuid = SVAL(inbuf, smb_uid);
+ cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
status = smb_bytes_talloc_string(cli,
inbuf,
uint8_t *p;
NTSTATUS status;
ssize_t ret;
+ uint8_t wct;
+ uint16_t *vwv;
- status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
+ status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
&num_bytes, &bytes);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
p = bytes;
cli->vuid = SVAL(inbuf, smb_uid);
+ cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
status = smb_bytes_talloc_string(cli,
inbuf,
uint8_t *p;
NTSTATUS status;
ssize_t ret;
+ uint8_t wct;
+ uint16_t *vwv;
- status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
+ status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
&num_bytes, &bytes);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
p = bytes;
cli->vuid = SVAL(inbuf, smb_uid);
+ cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
status = smb_bytes_talloc_string(cli,
inbuf,
uint8_t *p;
NTSTATUS status;
ssize_t ret;
+ uint8_t wct;
+ uint16_t *vwv;
- status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
+ status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
&num_bytes, &bytes);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
p = bytes;
cli->vuid = SVAL(inbuf, smb_uid);
+ cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
status = smb_bytes_talloc_string(cli,
inbuf,
uint8_t *inbuf;
ssize_t ret;
- status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
+ status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
&num_bytes, &bytes);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)
state->inbuf = (char *)inbuf;
cli->vuid = SVAL(state->inbuf, smb_uid);
+ cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
blob_length = SVAL(vwv+3, 0);
if (blob_length > num_bytes) {
* More to send
*/
if (!cli_sesssetup_blob_next(state, &subreq)) {
- tevent_req_nomem(NULL, req);
+ tevent_req_oom(req);
return;
}
tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
cli_temp_set_signing(cli);
status = ntlmssp_client_start(state,
- global_myname(),
+ lp_netbios_name(),
lp_workgroup(),
lp_client_ntlmv2_auth(),
&state->ntlmssp_state);
return status;
}
-/****************************************************************************
- Send a session request. See rfc1002.txt 4.3 and 4.3.2.
-****************************************************************************/
-
-bool cli_session_request(struct cli_state *cli,
- struct nmb_name *calling, struct nmb_name *called)
+static NTSTATUS cli_connect_sock(const char *host, int name_type,
+ const struct sockaddr_storage *pss,
+ const char *myname, uint16_t port,
+ int sec_timeout, int *pfd, uint16_t *pport)
{
- TALLOC_CTX *frame;
- uint8_t len_buf[4];
- struct iovec iov[3];
- ssize_t len;
- uint8_t *inbuf;
- int err;
- bool ret = false;
-
- /* 445 doesn't have session request */
- if (cli->port == 445)
- return True;
-
- memcpy(&(cli->calling), calling, sizeof(*calling));
- memcpy(&(cli->called ), called , sizeof(*called ));
-
- /* put in the destination name */
-
- frame = talloc_stackframe();
-
- iov[0].iov_base = len_buf;
- iov[0].iov_len = sizeof(len_buf);
-
- /* put in the destination name */
+ TALLOC_CTX *frame = talloc_stackframe();
+ const char *prog;
+ unsigned int i, num_addrs;
+ const char **called_names;
+ const char **calling_names;
+ int *called_types;
+ NTSTATUS status;
+ int fd;
- iov[1].iov_base = name_mangle(talloc_tos(), called->name,
- called->name_type);
- if (iov[1].iov_base == NULL) {
- goto fail;
+ prog = getenv("LIBSMB_PROG");
+ if (prog != NULL) {
+ fd = sock_exec(prog);
+ if (fd == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ port = 0;
+ goto done;
}
- iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
- talloc_get_size(iov[1].iov_base));
- /* and my name */
+ if ((pss == NULL) || is_zero_addr(pss)) {
+ struct sockaddr_storage *addrs;
+ status = resolve_name_list(talloc_tos(), host, name_type,
+ &addrs, &num_addrs);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ pss = addrs;
+ } else {
+ num_addrs = 1;
+ }
- iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
- calling->name_type);
- if (iov[2].iov_base == NULL) {
+ called_names = talloc_array(talloc_tos(), const char *, num_addrs);
+ if (called_names == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
- talloc_get_size(iov[2].iov_base));
-
- /* send a session request (RFC 1002) */
- /* setup the packet length
- * Remove four bytes from the length count, since the length
- * field in the NBT Session Service header counts the number
- * of bytes which follow. The cli_send_smb() function knows
- * about this and accounts for those four bytes.
- * CRH.
- */
-
- _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
- SCVAL(len_buf,0,0x81);
-
- len = write_data_iov(cli->fd, iov, 3);
- if (len == -1) {
+ called_types = talloc_array(talloc_tos(), int, num_addrs);
+ if (called_types == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- len = read_smb(cli->fd, talloc_tos(), &inbuf, &err);
- if (len == -1) {
- errno = err;
+ calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
+ if (calling_names == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
-
- if (CVAL(inbuf,0) == 0x84) {
- /* C. Hoch 9/14/95 Start */
- /* For information, here is the response structure.
- * We do the byte-twiddling to for portability.
- struct RetargetResponse{
- unsigned char type;
- unsigned char flags;
- int16 length;
- int32 ip_addr;
- int16 port;
- };
- */
- uint16_t port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
- struct in_addr dest_ip;
- NTSTATUS status;
-
- /* SESSION RETARGET */
- putip((char *)&dest_ip,inbuf+4);
- in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
-
- status = open_socket_out(&cli->dest_ss, port,
- LONG_CONNECT_TIMEOUT, &cli->fd);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- DEBUG(3,("Retargeted\n"));
-
- set_socket_options(cli->fd, lp_socket_options());
-
- /* Try again */
- {
- static int depth;
- if (depth > 4) {
- DEBUG(0,("Retarget recursion - failing\n"));
- goto fail;
- }
- depth++;
- ret = cli_session_request(cli, calling, called);
- depth--;
- goto done;
- }
- } /* C. Hoch 9/14/95 End */
-
- if (CVAL(inbuf,0) != 0x82) {
- /* This is the wrong place to put the error... JRA. */
- cli->rap_error = CVAL(inbuf,4);
+ for (i=0; i<num_addrs; i++) {
+ called_names[i] = host;
+ called_types[i] = name_type;
+ calling_names[i] = myname;
+ }
+ status = smbsock_any_connect(pss, called_names, called_types,
+ calling_names, NULL, num_addrs, port,
+ sec_timeout, &fd, NULL, &port);
+ if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+ set_socket_options(fd, lp_socket_options());
done:
- ret = true;
+ *pfd = fd;
+ *pport = port;
+ status = NT_STATUS_OK;
fail:
- err = errno;
TALLOC_FREE(frame);
- errno = err;
- return ret;
-}
-
-struct fd_struct {
- int fd;
-};
-
-static void smb_sock_connected(struct tevent_req *req)
-{
- struct fd_struct *pfd = tevent_req_callback_data(
- req, struct fd_struct);
- int fd;
- NTSTATUS status;
-
- status = open_socket_out_defer_recv(req, &fd);
- if (NT_STATUS_IS_OK(status)) {
- pfd->fd = fd;
- }
-}
-
-static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
- uint16_t *port, int timeout, int *pfd)
-{
- struct event_context *ev;
- struct tevent_req *r139, *r445;
- struct fd_struct *fd139, *fd445;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
-
- if (*port != 0) {
- return open_socket_out(pss, *port, timeout, pfd);
- }
-
- ev = event_context_init(talloc_tos());
- if (ev == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- fd139 = talloc(ev, struct fd_struct);
- if (fd139 == NULL) {
- goto done;
- }
- fd139->fd = -1;
-
- fd445 = talloc(ev, struct fd_struct);
- if (fd445 == NULL) {
- goto done;
- }
- fd445->fd = -1;
-
- r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
- pss, 445, timeout);
- r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
- pss, 139, timeout);
- if ((r445 == NULL) || (r139 == NULL)) {
- goto done;
- }
- tevent_req_set_callback(r445, smb_sock_connected, fd445);
- tevent_req_set_callback(r139, smb_sock_connected, fd139);
-
- while ((fd445->fd == -1) && (fd139->fd == -1)
- && (tevent_req_is_in_progress(r139)
- || tevent_req_is_in_progress(r445))) {
- event_loop_once(ev);
- }
-
- if ((fd139->fd != -1) && (fd445->fd != -1)) {
- close(fd139->fd);
- fd139->fd = -1;
- }
-
- if (fd445->fd != -1) {
- *port = 445;
- *pfd = fd445->fd;
- status = NT_STATUS_OK;
- goto done;
- }
- if (fd139->fd != -1) {
- *port = 139;
- *pfd = fd139->fd;
- status = NT_STATUS_OK;
- goto done;
- }
-
- status = open_socket_out_defer_recv(r445, &fd445->fd);
- done:
- TALLOC_FREE(ev);
return status;
}
-/****************************************************************************
- Open the client sockets.
-****************************************************************************/
-
-NTSTATUS cli_connect(struct cli_state *cli,
- const char *host,
- struct sockaddr_storage *dest_ss)
-
+NTSTATUS cli_connect_nb(const char *host, struct sockaddr_storage *pss,
+ uint16_t port, int name_type, const char *myname,
+ int signing_state, struct cli_state **pcli)
{
- int name_type = 0x20;
TALLOC_CTX *frame = talloc_stackframe();
- unsigned int num_addrs = 0;
- unsigned int i = 0;
- struct sockaddr_storage *ss_arr = NULL;
- char *p = NULL;
-
- /* reasonable default hostname */
- if (!host) {
- host = STAR_SMBSERVER;
- }
+ struct cli_state *cli;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+ int fd = -1;
+ char *desthost;
+ char *p;
+ socklen_t length;
+ int ret;
- cli->desthost = talloc_strdup(cli, host);
- if (cli->desthost == NULL) {
- return NT_STATUS_NO_MEMORY;
+ desthost = talloc_strdup(talloc_tos(), host);
+ if (desthost == NULL) {
+ goto fail;
}
- /* allow hostnames of the form NAME#xx and do a netbios lookup */
- if ((p = strchr(cli->desthost, '#'))) {
+ p = strchr(host, '#');
+ if (p != NULL) {
name_type = strtol(p+1, NULL, 16);
- *p = 0;
- }
-
- if (!dest_ss || is_zero_addr(dest_ss)) {
- NTSTATUS status =resolve_name_list(frame,
- cli->desthost,
- name_type,
- &ss_arr,
- &num_addrs);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(frame);
- return NT_STATUS_BAD_NETWORK_NAME;
- }
- } else {
- num_addrs = 1;
- ss_arr = TALLOC_P(frame, struct sockaddr_storage);
- if (!ss_arr) {
- TALLOC_FREE(frame);
- return NT_STATUS_NO_MEMORY;
+ host = talloc_strndup(talloc_tos(), host, p - host);
+ if (host == NULL) {
+ goto fail;
}
- *ss_arr = *dest_ss;
}
- for (i = 0; i < num_addrs; i++) {
- cli->dest_ss = ss_arr[i];
- if (getenv("LIBSMB_PROG")) {
- cli->fd = sock_exec(getenv("LIBSMB_PROG"));
- } else {
- uint16_t port = cli->port;
- NTSTATUS status;
- status = open_smb_socket(&cli->dest_ss, &port,
- cli->timeout, &cli->fd);
- if (NT_STATUS_IS_OK(status)) {
- cli->port = port;
- }
- }
- if (cli->fd == -1) {
- char addr[INET6_ADDRSTRLEN];
- print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
- DEBUG(2,("Error connecting to %s (%s)\n",
- dest_ss?addr:host,strerror(errno)));
- } else {
- /* Exit from loop on first connection. */
- break;
- }
+ cli = cli_initialise_ex(signing_state);
+ if (cli == NULL) {
+ goto fail;
}
+ cli->desthost = talloc_move(cli, &desthost);
- if (cli->fd == -1) {
- TALLOC_FREE(frame);
- return map_nt_error_from_unix(errno);
+ status = cli_connect_sock(host, name_type, pss, myname, port, 20, &fd,
+ &port);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_shutdown(cli);
+ goto fail;
}
+ cli->fd = fd;
+ cli->port = port;
- if (dest_ss) {
- *dest_ss = cli->dest_ss;
+ length = sizeof(cli->dest_ss);
+ ret = getpeername(fd, (struct sockaddr *)(void *)&cli->dest_ss,
+ &length);
+ if (ret == -1) {
+ status = map_nt_error_from_unix(errno);
+ cli_shutdown(cli);
+ goto fail;
}
- set_socket_options(cli->fd, lp_socket_options());
+ if (pss != NULL) {
+ *pss = cli->dest_ss;
+ }
+ *pcli = cli;
+ status = NT_STATUS_OK;
+fail:
TALLOC_FREE(frame);
- return NT_STATUS_OK;
+ return status;
}
/**
int signing_state, int flags)
{
NTSTATUS nt_status;
- struct nmb_name calling;
- struct nmb_name called;
struct cli_state *cli;
- struct sockaddr_storage ss;
-
- if (!my_name)
- my_name = global_myname();
-
- if (!(cli = cli_initialise_ex(signing_state))) {
- return NT_STATUS_NO_MEMORY;
- }
- make_nmb_name(&calling, my_name, 0x0);
- make_nmb_name(&called , dest_host, 0x20);
-
- cli_set_port(cli, port);
- cli_set_timeout(cli, 10000); /* 10 seconds. */
-
- if (dest_ss) {
- ss = *dest_ss;
- } else {
- zero_sockaddr(&ss);
- }
-
-again:
-
- DEBUG(3,("Connecting to host=%s\n", dest_host));
-
- nt_status = cli_connect(cli, dest_host, &ss);
+ nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
+ signing_state, &cli);
if (!NT_STATUS_IS_OK(nt_status)) {
- char addr[INET6_ADDRSTRLEN];
- print_sockaddr(addr, sizeof(addr), &ss);
- DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
- nmb_namestr(&called), addr, nt_errstr(nt_status) ));
- cli_shutdown(cli);
+ DEBUG(10, ("cli_connect_nb failed: %s\n",
+ nt_errstr(nt_status)));
return nt_status;
}
- 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, STAR_SMBSERVER)) {
- make_nmb_name(&called , STAR_SMBSERVER, 0x20);
- goto again;
- }
- return NT_STATUS_BAD_NETWORK_NAME;
- }
-
if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
cli->use_spnego = False;
else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
return NT_STATUS_OK;
}
-/****************************************************************************
- Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
-****************************************************************************/
-
-bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
- struct sockaddr_storage *pdest_ss)
-{
- 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, STAR_SMBSERVER, 0x20);
- } else {
- make_nmb_name(&called, desthost, 0x20);
- }
-
- if (!cli_session_request(*ppcli, &calling, &called)) {
- NTSTATUS status;
- struct nmb_name smbservername;
-
- make_nmb_name(&smbservername, STAR_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(*ppcli) ));
- return False;
- }
-
- /* Try again... */
- cli_shutdown(*ppcli);
-
- *ppcli = cli_initialise();
- if (!*ppcli) {
- /* Out of memory... */
- return False;
- }
-
- status = cli_connect(*ppcli, desthost, pdest_ss);
- if (!NT_STATUS_IS_OK(status) ||
- !cli_session_request(*ppcli, &calling, &smbservername)) {
- DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
-name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
- return False;
- }
- }
-
- return True;
-}
-
/****************************************************************************
Send an old style tcon.
****************************************************************************/