static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen) { size_t len; for(;;) { NTSTATUS status; set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK); status = receive_smb_raw(cli->fd, cli->inbuf, cli->bufsize, cli->timeout, maxlen, &len); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("client_receive_smb failed\n")); show_msg(cli->inbuf); if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { set_smb_read_error(&cli->smb_rw_error, SMB_READ_EOF); return -1; } if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { set_smb_read_error(&cli->smb_rw_error, SMB_READ_TIMEOUT); return -1; } set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR); return -1; } /* * I don't believe len can be < 0 with NT_STATUS_OK * returned above, but this check doesn't hurt. JRA. */ if ((ssize_t)len < 0) { return len; } /* Ignore session keepalive packets. */ if(CVAL(cli->inbuf,0) != SMBkeepalive) { break; } } if (cli_encryption_on(cli)) { NTSTATUS status = cli_decrypt_message(cli); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("SMB decryption failed on incoming packet! Error %s\n", nt_errstr(status))); cli->smb_rw_error = SMB_READ_BAD_DECRYPT; return -1; } } show_msg(cli->inbuf); return len; }
BOOL receive_smb(int fd,char *buffer, unsigned int timeout) { if (!receive_smb_raw(fd, buffer, timeout)) { return False; } /* Check the incoming SMB signature. */ if (!srv_check_sign_mac(buffer, True)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on incoming packet!\n")); if (smb_read_error == 0) smb_read_error = READ_BAD_SIG; return False; }; return(True); }
static void filter_child(int c, struct sockaddr_storage *dest_ss) { NTSTATUS status; int s = -1; char packet[128*1024]; /* we have a connection from a new client, now connect to the server */ status = open_socket_out(dest_ss, TCP_SMB_PORT, LONG_CONNECT_TIMEOUT, &s); if (!NT_STATUS_IS_OK(status)) { char addr[INET6_ADDRSTRLEN]; if (dest_ss) { print_sockaddr(addr, sizeof(addr), dest_ss); } d_printf("Unable to connect to %s (%s)\n", dest_ss?addr:"NULL", nt_errstr(status)); exit(1); } while (c != -1 || s != -1) { struct pollfd fds[2]; int num_fds, ret; memset(fds, 0, sizeof(struct pollfd) * 2); fds[0].fd = -1; fds[1].fd = -1; num_fds = 0; if (s != -1) { fds[num_fds].fd = s; fds[num_fds].events = POLLIN|POLLHUP; num_fds += 1; } if (c != -1) { fds[num_fds].fd = c; fds[num_fds].events = POLLIN|POLLHUP; num_fds += 1; } ret = sys_poll_intr(fds, num_fds, -1); if (ret <= 0) { continue; } /* * find c in fds and see if it's readable */ if ((c != -1) && (((fds[0].fd == c) && (fds[0].revents & (POLLIN|POLLHUP|POLLERR))) || ((fds[1].fd == c) && (fds[1].revents & (POLLIN|POLLHUP|POLLERR))))) { size_t len; if (!NT_STATUS_IS_OK(receive_smb_raw( c, packet, sizeof(packet), 0, 0, &len))) { d_printf("client closed connection\n"); exit(0); } filter_request(packet, len); if (!send_smb(s, packet)) { d_printf("server is dead\n"); exit(1); } } /* * find s in fds and see if it's readable */ if ((s != -1) && (((fds[0].fd == s) && (fds[0].revents & (POLLIN|POLLHUP|POLLERR))) || ((fds[1].fd == s) && (fds[1].revents & (POLLIN|POLLHUP|POLLERR))))) { size_t len; if (!NT_STATUS_IS_OK(receive_smb_raw( s, packet, sizeof(packet), 0, 0, &len))) { d_printf("server closed connection\n"); exit(0); } filter_reply(packet); if (!send_smb(c, packet)) { d_printf("client is dead\n"); exit(1); } } } d_printf("Connection closed\n"); exit(0); }