ERRmoredata is informational and should not be treated as a hard error
[samba.git] / source3 / libsmb / clientgen.c
index 99d868e216a8b6fc45a7e42b5a54c29083c6cb42..bd5d58e4de27513b2848de7d53406b68fa8169d4 100644 (file)
 
 extern int DEBUGLEVEL;
 
+/* 
+ * set the port that will be used for connections by the client
+ */
+
+int cli_set_port(struct cli_state *cli, int port)
+{
+
+       if (port != 0)
+         cli -> port = port;
+
+       return cli -> port;   /* return it incase caller wants it */
+
+}
 
 /****************************************************************************
 recv an smb
@@ -213,7 +226,7 @@ static char *fix_char_ptr(unsigned int datap, unsigned int converter,
 /****************************************************************************
   send a SMB trans or trans2 request
   ****************************************************************************/
-static BOOL cli_send_trans(struct cli_state *cli, int trans, 
+BOOL cli_send_trans(struct cli_state *cli, int trans, 
                            char *name, int pipe_name_len, 
                            int fid, int flags,
                            uint16 *setup, int lsetup, int msetup,
@@ -328,8 +341,6 @@ static BOOL cli_receive_trans(struct cli_state *cli,int trans,
        int total_data=0;
        int total_param=0;
        int this_data,this_param;
-       uint8 eclass;
-       uint32 num;
        
        *data_len = *param_len = 0;
 
@@ -344,8 +355,7 @@ static BOOL cli_receive_trans(struct cli_state *cli,int trans,
                return(False);
        }
 
-       /* DOS error "more data" is an acceptable error code */
-       if (cli_error(cli, &eclass, &num) && eclass != ERRDOS && num != ERRmoredata)
+       if (cli_error(cli, NULL, NULL))
        {
                return(False);
        }
@@ -396,8 +406,8 @@ static BOOL cli_receive_trans(struct cli_state *cli,int trans,
                                 CVAL(cli->inbuf,smb_com)));
                        return(False);
                }
-               /* DOS error "more data" is an acceptable error code */
-               if (cli_error(cli, &eclass, &num) && eclass != ERRDOS && num != ERRmoredata)
+
+               if (cli_error(cli, NULL, NULL))
                {
                        return(False);
                }
@@ -666,6 +676,8 @@ prots[] =
       {PROTOCOL_LANMAN2,"Samba"},
       {PROTOCOL_NT1,"NT LANMAN 1.0"},
       {PROTOCOL_NT1,"NT LM 0.12"},
+#if 0
+#endif
       {-1,NULL}
     };
 
@@ -683,36 +695,59 @@ BOOL cli_session_setup(struct cli_state *cli,
        fstring pword, ntpword;
 
        if (cli->protocol < PROTOCOL_LANMAN1)
+       {
                return True;
+       }
 
-       if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
+       if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1)
+       {
                return False;
        }
 
-        if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
-          /* Null session connect. */
-          pword[0] = '\0';
-          ntpword[0] = '\0';
-        } else {
-          if ((cli->sec_mode & 2) && passlen != 24) {
-            passlen = 24;
-            ntpasslen = 24;
-            SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
-            SMBNTencrypt((uchar *)ntpass,(uchar *)cli->cryptkey,(uchar *)ntpword);
-          } else {
-                 fstrcpy(pword, pass);
-                 fstrcpy(ntpword, "");
-                 ntpasslen = 0;
-          }
-        }
-
-       /* if in share level security then don't send a password now */
-       if (!(cli->sec_mode & 1)) {
+       if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
+       {
+               /* if in share level security then don't send a password now */
                fstrcpy(pword, "");
                passlen=1;
                fstrcpy(ntpword, "");
                ntpasslen=1;
        } 
+       else if ((passlen == 0 || passlen == 1) && (pass[0] == '\0'))
+       {
+               /* Null session connect. */
+               pword  [0] = '\0';
+               ntpword[0] = '\0';
+       }
+       else if (passlen == 24 && ntpasslen == 24)
+       {
+               if (IS_BITS_SET_ALL(cli->sec_mode, 2))
+               {
+                       /* encrypted password, implicit from 24-byte lengths */
+                       memcpy(pword  , pass  , 24);
+                       memcpy(ntpword, ntpass, 24);
+               }
+               else
+               {
+                       DEBUG(0,("cli_session_setup: encrypted passwords not supported by server\n"));
+                       return False;
+               }
+       }
+       else if (ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2))
+       {
+               /* plain-text password: server doesn't support encrypted. */
+               fstrcpy(pword, pass);
+               fstrcpy(ntpword, "");
+               ntpasslen = 0;
+       }
+       else /* passlen != 0 && ntpasslen != 0 && server supports encryption */
+       {
+               /* plain-text password requesting to be encrypted */
+               uchar *key = (uchar *)cli->cryptkey;
+               SMBencrypt  ((uchar *)pass  , key,(uchar *)pword  );
+               SMBNTencrypt((uchar *)ntpass, key,(uchar *)ntpword);
+               passlen = 24;
+               ntpasslen = 24;
+       }
 
        /* send a session setup command */
        bzero(cli->outbuf,smb_size);
@@ -1343,7 +1378,8 @@ size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t
                mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
                size2 = SVAL(cli->inbuf, smb_vwv5);
 
-               if (CVAL(cli->inbuf,smb_rcls) != 0) {
+               if (cli_error(cli, NULL, NULL))
+               {
                        blocks = MIN(blocks, mid-1);
                        continue;
                }
@@ -2355,8 +2391,10 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
        }
 
 
+       if (cli -> port == 0) cli -> port = 139;
+
        cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
-                                 139, cli->timeout);
+                                 cli -> port, cli->timeout);
        if (cli->fd == -1)
                return False;
 
@@ -2382,6 +2420,7 @@ struct cli_state *cli_initialise(struct cli_state *cli)
 
        ZERO_STRUCTP(cli);
 
+       cli -> port = 0;
        cli->fd = -1;
        cli->cnum = -1;
        cli->pid = (uint16)getpid();
@@ -2494,6 +2533,7 @@ int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
                case ERRrename: return EEXIST;
                case ERRbadshare: return EBUSY;
                case ERRlock: return EBUSY;
+               case ERRmoredata: return 0; /* Informational only */
                }
        }
        if (rcls == ERRSRV) {
@@ -2728,7 +2768,7 @@ BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
        extern pstring scope;
        fstring remote_machine;
        struct in_addr dest_ip;
-       struct nmb_name calling, called;
+       struct nmb_name calling, called, stupid_smbserver_called;
        BOOL connected_ok = False;
 
        /*
@@ -2755,7 +2795,7 @@ BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
                        continue;
                }   
 
-               if (ismyip(dest_ip))
+               if ((lp_security() != SEC_USER) && (ismyip(dest_ip)))
                {
                        DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
                        continue;
@@ -2763,19 +2803,28 @@ BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
 
                make_nmb_name(&calling, global_myname , 0x0 , scope);
                make_nmb_name(&called , remote_machine, 0x20, scope);
+               /* stupid microsoft destruction of the ability of netbios
+                * to provide multiple netbios servers on one host.
+                */
+               make_nmb_name(&stupid_smbserver_called , "*SMBSERVER", 0x20, scope);
 
                pwd_set_nullpwd(&cli->pwd);
 
                if (!cli_establish_connection(cli, remote_machine, &dest_ip,
                                              &calling, &called,
                                              "IPC$", "IPC", 
+                                             False, True) &&
+                   !cli_establish_connection(cli, remote_machine, &dest_ip,
+                                             &calling, &stupid_smbserver_called,
+                                             "IPC$", "IPC", 
                                              False, True))
                {
                        cli_shutdown(cli);
                        continue;
                }      
 
-               if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
+               if (cli->protocol < PROTOCOL_LANMAN2 ||
+                   !IS_BITS_SET_ALL(cli->sec_mode, 1))
                {
                        DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
                                  remote_machine));