From 36441da4240f3e3a296eed65f0796b25b7b05a3a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Nov 2007 11:12:56 -0800 Subject: Remove the horror that was the global smb_rw_error. Each cli struct has it's own local copy of this variable, so use that in client code. In the smbd server, add one static to smbd/proccess.c and use that inside smbd. Fix a bunch of places where smb_rw_error could be set by calling read_data() in places where we weren't reading from the SMB client socket (ie. winbindd). Jeremy. (This used to be commit 255c2adf7b6ef30932b5bb9f142ccef4a5d3d0db) --- source3/client/client.c | 2 +- source3/include/client.h | 2 +- source3/lib/util_sock.c | 87 ++++++++++++++++++++-------------------- source3/libsmb/clientgen.c | 23 ++++++----- source3/nmbd/asyncdns.c | 4 +- source3/smbd/chgpasswd.c | 2 +- source3/smbd/process.c | 59 +++++++++++++++++---------- source3/smbd/reply.c | 5 ++- source3/winbindd/winbindd_dual.c | 4 +- 9 files changed, 104 insertions(+), 84 deletions(-) (limited to 'source3') diff --git a/source3/client/client.c b/source3/client/client.c index 27f120ce9a..94dc52d9d5 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -3711,7 +3711,7 @@ static void readline_callback(void) session keepalives and then drop them here. */ if (FD_ISSET(cli->fd,&fds)) { - if (!receive_smb(cli->fd,cli->inbuf,0)) { + if (!receive_smb(cli->fd,cli->inbuf,0,&cli->smb_rw_error)) { DEBUG(0, ("Read from server failed, maybe it closed the " "connection\n")); return; diff --git a/source3/include/client.h b/source3/include/client.h index d8c35780a4..dd8bb0dba9 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -82,7 +82,7 @@ struct rpc_pipe_client { struct cli_state { int port; int fd; - /* Copy of last read or write error. */ + /* Last read or write error. */ enum smb_read_errors smb_rw_error; uint16 cnum; uint16 pid; diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 02097239cf..4a870b71b3 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -654,22 +654,19 @@ int client_socket_port(int fd) Accessor functions to make thread-safe code easier later... ****************************************************************************/ -static enum smb_read_errors smb_read_error = SMB_READ_OK; - -enum smb_read_errors get_smb_read_error(void) -{ - return smb_read_error; -} - -void set_smb_read_error(enum smb_read_errors newerr) +void set_smb_read_error(enum smb_read_errors *pre, + enum smb_read_errors newerr) { - smb_read_error = newerr; + if (pre) { + *pre = newerr; + } } -void cond_set_smb_read_error(enum smb_read_errors newerr) +void cond_set_smb_read_error(enum smb_read_errors *pre, + enum smb_read_errors newerr) { - if (smb_read_error == SMB_READ_OK) { - smb_read_error = newerr; + if (pre && *pre == SMB_READ_OK) { + *pre = newerr; } } @@ -883,7 +880,8 @@ ssize_t read_socket_with_timeout(int fd, char *buf, size_t mincnt, size_t maxcnt, - unsigned int time_out) + unsigned int time_out, + enum smb_read_errors *pre) { fd_set fds; int selrtn; @@ -896,7 +894,7 @@ ssize_t read_socket_with_timeout(int fd, if (maxcnt <= 0) return(0); - set_smb_read_error(SMB_READ_OK); + set_smb_read_error(pre,SMB_READ_OK); /* Blocking read */ if (time_out == 0) { @@ -910,7 +908,7 @@ ssize_t read_socket_with_timeout(int fd, if (readret == 0) { DEBUG(5,("read_socket_with_timeout: " "blocking read. EOF from client.\n")); - set_smb_read_error(SMB_READ_EOF); + set_smb_read_error(pre,SMB_READ_EOF); return -1; } @@ -927,7 +925,7 @@ ssize_t read_socket_with_timeout(int fd, "read error = %s.\n", strerror(errno) )); } - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(pre,SMB_READ_ERROR); return -1; } nread += readret; @@ -966,7 +964,7 @@ ssize_t read_socket_with_timeout(int fd, "read. select error = %s.\n", strerror(errno) )); } - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(pre,SMB_READ_ERROR); return -1; } @@ -974,7 +972,7 @@ ssize_t read_socket_with_timeout(int fd, if (selrtn == 0) { DEBUG(10,("read_socket_with_timeout: timeout read. " "select timed out.\n")); - set_smb_read_error(SMB_READ_TIMEOUT); + set_smb_read_error(pre,SMB_READ_TIMEOUT); return -1; } @@ -984,7 +982,7 @@ ssize_t read_socket_with_timeout(int fd, /* we got EOF on the file descriptor */ DEBUG(5,("read_socket_with_timeout: timeout read. " "EOF from client.\n")); - set_smb_read_error(SMB_READ_EOF); + set_smb_read_error(pre,SMB_READ_EOF); return -1; } @@ -1002,7 +1000,7 @@ ssize_t read_socket_with_timeout(int fd, "read. read error = %s.\n", strerror(errno) )); } - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(pre,SMB_READ_ERROR); return -1; } @@ -1017,13 +1015,13 @@ ssize_t read_socket_with_timeout(int fd, Read data from the client, reading exactly N bytes. ****************************************************************************/ -ssize_t read_data(int fd,char *buffer,size_t N) +ssize_t read_data(int fd,char *buffer,size_t N, enum smb_read_errors *pre) { ssize_t ret; size_t total=0; char addr[INET6_ADDRSTRLEN]; - set_smb_read_error(SMB_READ_OK); + set_smb_read_error(pre,SMB_READ_OK); while (total < N) { ret = sys_read(fd,buffer + total,N - total); @@ -1032,7 +1030,7 @@ ssize_t read_data(int fd,char *buffer,size_t N) DEBUG(10,("read_data: read of %d returned 0. " "Error = %s\n", (int)(N - total), strerror(errno) )); - set_smb_read_error(SMB_READ_EOF); + set_smb_read_error(pre,SMB_READ_EOF); return 0; } @@ -1051,7 +1049,7 @@ ssize_t read_data(int fd,char *buffer,size_t N) (int)(N - total), strerror(errno) )); } - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(pre,SMB_READ_ERROR); return -1; } total += ret; @@ -1119,8 +1117,9 @@ bool send_keepalive(int client) ****************************************************************************/ ssize_t read_smb_length_return_keepalive(int fd, - char *inbuf, - unsigned int timeout) + char *inbuf, + unsigned int timeout, + enum smb_read_errors *pre) { ssize_t len=0; int msg_type; @@ -1128,10 +1127,10 @@ ssize_t read_smb_length_return_keepalive(int fd, while (!ok) { if (timeout > 0) { - ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout) - == 4); + ok = (read_socket_with_timeout(fd,inbuf,4,4, + timeout,pre) == 4); } else { - ok = (read_data(fd,inbuf,4) == 4); + ok = (read_data(fd,inbuf,4,pre) == 4); } if (!ok) { return -1; @@ -1147,7 +1146,7 @@ ssize_t read_smb_length_return_keepalive(int fd, DEBUG(10,("got smb length of %lu\n",(unsigned long)len)); - return(len); + return len; } /**************************************************************************** @@ -1157,12 +1156,12 @@ ssize_t read_smb_length_return_keepalive(int fd, Timeout is in milliseconds. ****************************************************************************/ -ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout) +ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout, enum smb_read_errors *pre) { ssize_t len; for(;;) { - len = read_smb_length_return_keepalive(fd, inbuf, timeout); + len = read_smb_length_return_keepalive(fd, inbuf, timeout, pre); if(len < 0) return len; @@ -1191,13 +1190,14 @@ ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout) ssize_t receive_smb_raw(int fd, char *buffer, unsigned int timeout, - size_t maxlen) + size_t maxlen, + enum smb_read_errors *pre) { ssize_t len,ret; - set_smb_read_error(SMB_READ_OK); + set_smb_read_error(pre,SMB_READ_OK); - len = read_smb_length_return_keepalive(fd,buffer,timeout); + len = read_smb_length_return_keepalive(fd,buffer,timeout,pre); if (len < 0) { DEBUG(10,("receive_smb_raw: length < 0!\n")); @@ -1207,7 +1207,7 @@ ssize_t receive_smb_raw(int fd, * variables still suck :-). JRA. */ - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(pre,SMB_READ_ERROR); return -1; } @@ -1227,7 +1227,7 @@ ssize_t receive_smb_raw(int fd, * variables still suck :-). JRA. */ - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(pre,SMB_READ_ERROR); return -1; } } @@ -1242,13 +1242,14 @@ ssize_t receive_smb_raw(int fd, buffer+4, len, len, - timeout); + timeout, + pre); } else { - ret = read_data(fd,buffer+4,len); + ret = read_data(fd,buffer+4,len,pre); } if (ret != len) { - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(pre,SMB_READ_ERROR); return -1; } @@ -1266,9 +1267,9 @@ ssize_t receive_smb_raw(int fd, Checks the MAC on signed packets. ****************************************************************************/ -bool receive_smb(int fd, char *buffer, unsigned int timeout) +bool receive_smb(int fd, char *buffer, unsigned int timeout, enum smb_read_errors *pre) { - if (receive_smb_raw(fd, buffer, timeout, 0) < 0) { + if (receive_smb_raw(fd, buffer, timeout, 0, pre) < 0) { return false; } @@ -1276,7 +1277,7 @@ bool receive_smb(int fd, char *buffer, unsigned int timeout) if (!srv_check_sign_mac(buffer, true)) { DEBUG(0, ("receive_smb: SMB Signature verification " "failed on incoming packet!\n")); - cond_set_smb_read_error(SMB_READ_BAD_SIG); + cond_set_smb_read_error(pre,SMB_READ_BAD_SIG); return false; } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 0a8ff4e552..ee1a0fe3db 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -52,24 +52,26 @@ int cli_set_port(struct cli_state *cli, int port) should never go into a blocking read. ****************************************************************************/ -static ssize_t client_receive_smb(int fd,char *buffer, unsigned int timeout, size_t maxlen) +static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen) { ssize_t len; for(;;) { - len = receive_smb_raw(fd, buffer, timeout, maxlen); + len = receive_smb_raw(cli->fd, cli->inbuf, cli->timeout, + maxlen, &cli->smb_rw_error); if (len < 0) { DEBUG(10,("client_receive_smb failed\n")); - show_msg(buffer); + show_msg(cli->inbuf); return len; } /* Ignore session keepalive packets. */ - if(CVAL(buffer,0) != SMBkeepalive) + if(CVAL(cli->inbuf,0) != SMBkeepalive) { break; + } } - show_msg(buffer); + show_msg(cli->inbuf); return len; } @@ -86,7 +88,7 @@ bool cli_receive_smb(struct cli_state *cli) return False; again: - len = client_receive_smb(cli->fd,cli->inbuf,cli->timeout, 0); + len = client_receive_smb(cli, 0); if (len > 0) { /* it might be an oplock break request */ @@ -110,7 +112,6 @@ bool cli_receive_smb(struct cli_state *cli) /* If the server is not responding, note that now */ if (len < 0) { DEBUG(0, ("Receiving SMB: Server stopped responding\n")); - cli->smb_rw_error = get_smb_read_error(); close(cli->fd); cli->fd = -1; return False; @@ -154,9 +155,10 @@ bool cli_receive_smb(struct cli_state *cli) ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len) { if (cli->timeout > 0) { - return read_socket_with_timeout(cli->fd, buffer, len, len, cli->timeout); + return read_socket_with_timeout(cli->fd, buffer, len, + len, cli->timeout, &cli->smb_rw_error); } else { - return read_data(cli->fd, buffer, len); + return read_data(cli->fd, buffer, len, &cli->smb_rw_error); } } @@ -174,7 +176,7 @@ bool cli_receive_smb_readX_header(struct cli_state *cli) again: /* Read up to the size of a readX header reply. */ - len = client_receive_smb(cli->fd, cli->inbuf, cli->timeout, (smb_size - 4) + 24); + len = client_receive_smb(cli, (smb_size - 4) + 24); if (len > 0) { /* it might be an oplock break request */ @@ -240,7 +242,6 @@ bool cli_receive_smb_readX_header(struct cli_state *cli) read_err: - set_smb_read_error(SMB_READ_ERROR); cli->smb_rw_error = SMB_READ_ERROR; close(cli->fd); cli->fd = -1; diff --git a/source3/nmbd/asyncdns.c b/source3/nmbd/asyncdns.c index b9c9ffb1c6..33c1cb6cb1 100644 --- a/source3/nmbd/asyncdns.c +++ b/source3/nmbd/asyncdns.c @@ -87,7 +87,7 @@ static void asyncdns_process(void) DEBUGLEVEL = -1; while (1) { - if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r)) + if (read_data(fd_in, (char *)&r, sizeof(r), NULL) != sizeof(r)) break; pull_ascii_nstring( qname, sizeof(qname), r.name.name); @@ -208,7 +208,7 @@ void run_dns_queue(void) start_async_dns(); } - if ((size=read_data(fd_in, (char *)&r, sizeof(r))) != sizeof(r)) { + if ((size=read_data(fd_in, (char *)&r, sizeof(r), NULL)) != sizeof(r)) { if (size) { DEBUG(0,("Incomplete DNS answer from child!\n")); fd_in = -1; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fb6e6c0f09..d89442150f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -256,7 +256,7 @@ static int expect(int master, char *issue, char *expected) while ((len = read_socket_with_timeout(master, buffer + nread, 1, sizeof(buffer) - nread - 1, - timeout)) > 0) { + timeout, NULL)) > 0) { nread += len; buffer[nread] = 0; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7d6455621f..24497de69a 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -24,6 +24,7 @@ extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); +static enum smb_read_errors smb_read_error = SMB_READ_OK; /* * Size of data we can send to client. Set @@ -43,6 +44,13 @@ SIG_ATOMIC_T got_sig_term = 0; extern bool global_machine_password_needs_changing; extern int max_send; +/* Accessor function for smb_read_error for smbd functions. */ + +enum smb_read_errors *get_srv_read_error(void) +{ + return &smb_read_error; +} + /* Socket functions for smbd packet processing. */ static bool valid_packet_size(size_t len) @@ -63,7 +71,8 @@ static bool valid_packet_size(size_t len) * variables still suck :-). JRA. */ - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return false; } } @@ -86,13 +95,15 @@ static ssize_t read_packet_remainder(int fd, buffer, len, len, - timeout); + timeout, + get_srv_read_error()); } else { - ret = read_data(fd, buffer, len); + ret = read_data(fd, buffer, len, get_srv_read_error()); } if (ret != len) { - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } @@ -135,15 +146,18 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, writeX_header + 4, STANDARD_WRITE_AND_X_HEADER_SIZE, STANDARD_WRITE_AND_X_HEADER_SIZE, - timeout); + timeout, + get_srv_read_error()); } else { ret = read_data(fd, writeX_header+4, - STANDARD_WRITE_AND_X_HEADER_SIZE); + STANDARD_WRITE_AND_X_HEADER_SIZE, + get_srv_read_error()); } if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } @@ -183,7 +197,8 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)sizeof(writeX_header))); - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } @@ -207,7 +222,8 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)len+4)); - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_ERROR); return -1; } @@ -240,10 +256,11 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, ssize_t len,ret; int min_recv_size = lp_min_receive_file_size(); - set_smb_read_error(SMB_READ_OK); + set_smb_read_error(get_srv_read_error(),SMB_READ_OK); *p_unread = 0; - len = read_smb_length_return_keepalive(fd, lenbuf, timeout); + len = read_smb_length_return_keepalive(fd, lenbuf, + timeout, get_srv_read_error()); if (len < 0) { DEBUG(10,("receive_smb_raw: length < 0!\n")); @@ -253,7 +270,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, * variables still suck :-). JRA. */ - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return -1; } @@ -283,7 +300,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, if (*buffer == NULL) { DEBUG(0, ("Could not allocate inbuf of length %d\n", (int)len+4)); - cond_set_smb_read_error(SMB_READ_ERROR); + cond_set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return -1; } @@ -312,7 +329,7 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, if (!srv_check_sign_mac(*buffer, true)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on " "incoming packet!\n")); - cond_set_smb_read_error(SMB_READ_BAD_SIG); + cond_set_smb_read_error(get_srv_read_error(),SMB_READ_BAD_SIG); return -1; } @@ -682,7 +699,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, ssize_t len; *p_unread = 0; - set_smb_read_error(SMB_READ_OK); + set_smb_read_error(get_srv_read_error(),SMB_READ_OK); again: @@ -736,7 +753,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, msg->buf.length); if (*buffer == NULL) { DEBUG(0, ("talloc failed\n")); - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return False; } *buffer_len = msg->buf.length; @@ -830,13 +847,13 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, /* Check if error */ if (selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ - set_smb_read_error(SMB_READ_ERROR); + set_smb_read_error(get_srv_read_error(),SMB_READ_ERROR); return False; } /* Did we timeout ? */ if (selrtn == 0) { - set_smb_read_error(SMB_READ_TIMEOUT); + set_smb_read_error(get_srv_read_error(),SMB_READ_TIMEOUT); return False; } @@ -1826,18 +1843,18 @@ static bool timeout_processing(int *select_timeout, { time_t t; - if (get_smb_read_error() == SMB_READ_EOF) { + if (*get_srv_read_error() == SMB_READ_EOF) { DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); return false; } - if (get_smb_read_error() == SMB_READ_ERROR) { + if (*get_srv_read_error() == SMB_READ_ERROR) { DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n", strerror(errno))); return false; } - if (get_smb_read_error() == SMB_READ_BAD_SIG) { + if (*get_srv_read_error() == SMB_READ_BAD_SIG) { DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n")); return false; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a7fa67df22..1b36fb1e44 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3535,7 +3535,8 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) } /* Now read the raw data into the buffer and write it */ - if (read_smb_length(smbd_server_fd(),buf,SMB_SECONDARY_WAIT) == -1) { + if (read_smb_length(smbd_server_fd(),buf, + SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) { exit_server_cleanly("secondary writebraw failed"); } @@ -3564,7 +3565,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req) (int)tcount,(int)nwritten,(int)numtowrite)); } - if (read_data(smbd_server_fd(), buf+4, numtowrite) + if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error()) != numtowrite ) { DEBUG(0,("reply_writebraw: Oversize secondary write " "raw read failed (%s). Terminating\n", diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index c96941531a..c15af710f4 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -44,7 +44,7 @@ static void child_read_request(struct winbindd_cli_state *state) /* Read data */ len = read_data(state->sock, (char *)&state->request, - sizeof(state->request)); + sizeof(state->request), NULL); if (len != sizeof(state->request)) { DEBUG(len > 0 ? 0 : 3, ("Got invalid request length: %d\n", (int)len)); @@ -72,7 +72,7 @@ static void child_read_request(struct winbindd_cli_state *state) state->request.extra_data.data[state->request.extra_len] = '\0'; len = read_data(state->sock, state->request.extra_data.data, - state->request.extra_len); + state->request.extra_len, NULL); if (len != state->request.extra_len) { DEBUG(0, ("Could not read extra data\n")); -- cgit