s3-rpc_server: Convert rpc_connect_spoolss_pipe into a generic interface.
[kamenim/samba.git] / source3 / smbd / reply.c
index a2b6b33af5af7f2dbf649b17c35bf1dabbfc86f8..4ace452ed92a630d5fe52f7919e932805754745d 100644 (file)
@@ -27,6 +27,7 @@
 #include "includes.h"
 #include "printing.h"
 #include "smbd/globals.h"
+#include "fake_file.h"
 #include "../librpc/gen_ndr/cli_spoolss.h"
 #include "rpc_client/cli_spoolss.h"
 #include "rpc_client/init_spoolss.h"
@@ -468,7 +469,7 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn,
        *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
        *(uint16_t *)(outbuf+8) = htons(retarget_port);
 
-       if (!srv_send_smb(sconn->sock, (char *)outbuf, false, 0, false,
+       if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
                          NULL)) {
                exit_server_cleanly("netbios_session_regarget: srv_send_smb "
                                    "failed.");
@@ -527,6 +528,15 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf)
                        exit_server_cleanly("retargeted client");
                }
 
+               /*
+                * Windows NT/2k uses "*SMBSERVER" and XP uses
+                * "*SMBSERV" arrggg!!!
+                */
+               if (strequal(name1, "*SMBSERVER     ")
+                   || strequal(name1, "*SMBSERV       "))  {
+                       fstrcpy(name1, sconn->client_id.addr);
+               }
+
                set_local_machine_name(name1, True);
                set_remote_machine_name(name2, True);
 
@@ -548,7 +558,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf)
                        add_session_user(sconn, get_remote_machine_name());
                }
 
-               reload_services(sconn->msg_ctx, True);
+               reload_services(sconn->msg_ctx, sconn->sock, True);
                reopen_logs();
 
                sconn->nbt.got_session = true;
@@ -574,7 +584,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf)
        DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
                    msg_type, msg_flags));
 
-       srv_send_smb(sconn->sock, outbuf, false, 0, false, NULL);
+       srv_send_smb(sconn, outbuf, false, 0, false, NULL);
        return;
 }
 
@@ -3796,6 +3806,43 @@ void error_to_writebrawerr(struct smb_request *req)
        TALLOC_FREE(old_outbuf);
 }
 
+/****************************************************************************
+ Read 4 bytes of a smb packet and return the smb length of the packet.
+ Store the result in the buffer. This version of the function will
+ never return a session keepalive (length of zero).
+ Timeout is in milliseconds.
+****************************************************************************/
+
+static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
+                               size_t *len)
+{
+       uint8_t msgtype = SMBkeepalive;
+
+       while (msgtype == SMBkeepalive) {
+               NTSTATUS status;
+
+               status = read_smb_length_return_keepalive(fd, inbuf, timeout,
+                                                         len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       char addr[INET6_ADDRSTRLEN];
+                       /* Try and give an error message
+                        * saying what client failed. */
+                       DEBUG(0, ("read_fd_with_timeout failed for "
+                                 "client %s read error = %s.\n",
+                                 get_peer_addr(fd,addr,sizeof(addr)),
+                                 nt_errstr(status)));
+                       return status;
+               }
+
+               msgtype = CVAL(inbuf, 0);
+       }
+
+       DEBUG(10,("read_smb_length: got smb length of %lu\n",
+                 (unsigned long)len));
+
+       return NT_STATUS_OK;
+}
+
 /****************************************************************************
  Reply to a writebraw (core+ or LANMAN1.0 protocol).
 ****************************************************************************/
@@ -3929,7 +3976,7 @@ void reply_writebraw(struct smb_request *req)
        SCVAL(buf,smb_com,SMBwritebraw);
        SSVALS(buf,smb_vwv0,0xFFFF);
        show_msg(buf);
-       if (!srv_send_smb(req->sconn->sock,
+       if (!srv_send_smb(req->sconn,
                          buf,
                          false, 0, /* no signing */
                          IS_CONN_ENCRYPTED(conn),
@@ -3966,9 +4013,14 @@ void reply_writebraw(struct smb_request *req)
                status = read_data(req->sconn->sock, buf+4, numtowrite);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("reply_writebraw: Oversize secondary write "
-                                "raw read failed (%s). Terminating\n",
-                                nt_errstr(status)));
+                       char addr[INET6_ADDRSTRLEN];
+                       /* Try and give an error message
+                        * saying what client failed. */
+                       DEBUG(0, ("reply_writebraw: Oversize secondary write "
+                                 "raw read failed (%s) for client %s. "
+                                 "Terminating\n", nt_errstr(status),
+                                 get_peer_addr(req->sconn->sock, addr,
+                                               sizeof(addr))));
                        exit_server_cleanly("secondary writebraw failed");
                }
 
@@ -5071,7 +5123,7 @@ void reply_echo(struct smb_request *req)
                SSVAL(req->outbuf,smb_vwv0,seq_num);
 
                show_msg((char *)req->outbuf);
-               if (!srv_send_smb(req->sconn->sock,
+               if (!srv_send_smb(req->sconn,
                                (char *)req->outbuf,
                                true, req->seqnum+1,
                                IS_CONN_ENCRYPTED(conn)||req->encrypted,
@@ -5242,7 +5294,12 @@ void reply_printqueue(struct smb_request *req)
 
                ZERO_STRUCT(handle);
 
-               status = rpc_connect_spoolss_pipe(conn, &cli);
+               status = rpc_pipe_open_interface(conn,
+                                                &ndr_table_spoolss.syntax_id,
+                                                conn->server_info,
+                                                &conn->sconn->client_id,
+                                                conn->sconn->msg_ctx,
+                                                &cli);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0, ("reply_printqueue: "
                                  "could not connect to spoolss: %s\n",