Break up 'cli_full_connection' to allow for the session setups to be done
authorAndrew Bartlett <abartlet@samba.org>
Tue, 19 Aug 2003 17:47:44 +0000 (17:47 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 19 Aug 2003 17:47:44 +0000 (17:47 +0000)
elsewhere in the code.  This will allow us to try kerberos, then another user
then guest in the winbindd code.

Also, re-introduce the seperate, NT1 'guest' session setup code, as I found
some problems with doing guest under NTLMSSP.

Andrew Bartlett

source/libsmb/cliconnect.c

index 010aa4d1bb4930c4e9c9e4b6ef7b2152aef52083..ca492e0a1c6eda4dc042659fea78c2b9b7c42396 100644 (file)
@@ -130,6 +130,55 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli)
        return capabilities;
 }
 
+/****************************************************************************
+ Do a NT1 guest session setup.
+****************************************************************************/
+
+static BOOL cli_session_setup_guest(struct cli_state *cli)
+{
+       char *p;
+       uint32 capabilities = cli_session_setup_capabilities(cli);
+
+       set_message(cli->outbuf,13,0,True);
+       SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
+       cli_setup_packet(cli);
+                       
+       SCVAL(cli->outbuf,smb_vwv0,0xFF);
+       SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
+       SSVAL(cli->outbuf,smb_vwv3,2);
+       SSVAL(cli->outbuf,smb_vwv4,cli->pid);
+       SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
+       SSVAL(cli->outbuf,smb_vwv7,0);
+       SSVAL(cli->outbuf,smb_vwv8,0);
+       SIVAL(cli->outbuf,smb_vwv11,capabilities); 
+       p = smb_buf(cli->outbuf);
+       p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
+       p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
+       p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
+       p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
+       cli_setup_bcc(cli, p);
+
+       cli_send_smb(cli);
+       if (!cli_receive_smb(cli))
+             return False;
+       
+       show_msg(cli->inbuf);
+       
+       if (cli_is_error(cli))
+               return False;
+
+       cli->vuid = SVAL(cli->inbuf,smb_uid);
+
+       p = smb_buf(cli->inbuf);
+       p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
+       p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
+       p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
+
+       fstrcpy(cli->user_name, "");
+
+       return True;
+}
+
 /****************************************************************************
  Do a NT1 plaintext session setup.
 ****************************************************************************/
@@ -198,7 +247,8 @@ static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key)
 }
 
 /****************************************************************************
-   do a NT1 NTLM/LM encrypted session setup
+   do a NT1 NTLM/LM encrypted session setup - for when extended security
+   is not negotiated.
    @param cli client state to create do session setup on
    @param user username
    @param pass *either* cleartext password (passlen !=24) or LM response.
@@ -221,7 +271,10 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
        if (passlen == 0) {
                /* do nothing - guest login */
        } else if (passlen != 24) {
-               if ((cli->capabilities & CAP_EXTENDED_SECURITY) && lp_client_ntlmv2_auth()) {
+               /* if client ntlmv2 auth is set, then don't use it on a
+                  connection without extended security.  This isn't a very
+                  good check, but it is a start */
+               if (lp_client_ntlmv2_auth()) {
                        DATA_BLOB server_chal;
                        DATA_BLOB names_blob;
                        server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); 
@@ -573,7 +626,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
        if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) {
                return False;
        }
-
+       
        return (NT_STATUS_IS_OK(nt_status));
 }
 
@@ -581,8 +634,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
  Do a spnego encrypted session setup.
 ****************************************************************************/
 
-static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, 
-                                    const char *pass, const char *workgroup)
+BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, 
+                             const char *pass, const char *workgroup)
 {
        char *principal;
        char *OIDs[ASN1_MAX_OIDS];
@@ -704,6 +757,12 @@ BOOL cli_session_setup(struct cli_state *cli,
                return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
        }
 
+       /* if no user is supplied then we have to do an anonymous connection.
+          passwords are ignored */
+
+       if (!user || !*user)
+               return cli_session_setup_guest(cli);
+
        /* if the server is share level then send a plaintext null
            password at this point. The password is sent in the tree
            connect */
@@ -711,17 +770,6 @@ BOOL cli_session_setup(struct cli_state *cli,
        if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
                return cli_session_setup_plaintext(cli, user, "", workgroup);
 
-       /* if no user is supplied then we have to do an anonymous connection.
-          passwords are ignored */
-
-       if (!user || !*user) {
-               user = "";
-               pass = NULL;
-               ntpass = NULL;
-               passlen = 0;
-               ntpasslen = 0;
-       }
-
        /* if the server doesn't support encryption then we have to use 
           plaintext. The second password is ignored */
 
@@ -1187,7 +1235,7 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
  Initialise client credentials for authenticated pipe access.
 ****************************************************************************/
 
-static void init_creds(struct ntuser_creds *creds, const char* username,
+void init_creds(struct ntuser_creds *creds, const char* username,
                       const char* domain, const char* password)
 {
        ZERO_STRUCTP(creds);
@@ -1203,30 +1251,21 @@ static void init_creds(struct ntuser_creds *creds, const char* username,
 }
 
 /**
-   establishes a connection right up to doing tconX, password specified.
+   establishes a connection to after the negprot. 
    @param output_cli A fully initialised cli structure, non-null only on success
    @param dest_host The netbios name of the remote host
    @param dest_ip (optional) The the destination IP, NULL for name based lookup
    @param port (optional) The destination port (0 for default)
-   @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
-   @param service_type The 'type' of serivice. 
-   @param user Username, unix string
-   @param domain User's domain
-   @param password User's password, unencrypted unix string.
    @param retry BOOL. Did this connection fail with a retryable error ?
-*/
 
-NTSTATUS cli_full_connection(struct cli_state **output_cli, 
-                            const char *my_name, 
-                            const char *dest_host, 
-                            struct in_addr *dest_ip, int port,
-                            const char *service, const char *service_type,
-                            const char *user, const char *domain, 
-                            const char *password, int flags,
-                            int signing_state,
-                            BOOL *retry) 
+*/
+NTSTATUS cli_start_connection(struct cli_state **output_cli, 
+                             const char *my_name, 
+                             const char *dest_host, 
+                             struct in_addr *dest_ip, int port,
+                             int signing_state, int flags,
+                             BOOL *retry) 
 {
-       struct ntuser_creds creds;
        NTSTATUS nt_status;
        struct nmb_name calling;
        struct nmb_name called;
@@ -1259,7 +1298,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
 
 again:
 
-       DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service));
+       DEBUG(3,("Connecting to host=%s\n", dest_host));
        
        if (!cli_connect(cli, dest_host, &ip)) {
                DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
@@ -1300,6 +1339,46 @@ again:
                return nt_status;
        }
 
+       *output_cli = cli;
+       return NT_STATUS_OK;
+}
+
+
+/**
+   establishes a connection right up to doing tconX, password specified.
+   @param output_cli A fully initialised cli structure, non-null only on success
+   @param dest_host The netbios name of the remote host
+   @param dest_ip (optional) The the destination IP, NULL for name based lookup
+   @param port (optional) The destination port (0 for default)
+   @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
+   @param service_type The 'type' of serivice. 
+   @param user Username, unix string
+   @param domain User's domain
+   @param password User's password, unencrypted unix string.
+   @param retry BOOL. Did this connection fail with a retryable error ?
+*/
+
+NTSTATUS cli_full_connection(struct cli_state **output_cli, 
+                            const char *my_name, 
+                            const char *dest_host, 
+                            struct in_addr *dest_ip, int port,
+                            const char *service, const char *service_type,
+                            const char *user, const char *domain, 
+                            const char *password, int flags,
+                            int signing_state,
+                            BOOL *retry) 
+{
+       struct ntuser_creds creds;
+       NTSTATUS nt_status;
+       struct cli_state *cli = NULL;
+
+       nt_status = cli_start_connection(&cli, my_name, dest_host, 
+                                        dest_ip, port, signing_state, flags, retry);
+       
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
+
        if (!cli_session_setup(cli, user, password, strlen(password)+1, 
                               password, strlen(password)+1, 
                               domain)) {