fixed a crash bug in domain auth caused by an uninitialised nt_status
[ira/wip.git] / source / libsmb / cliconnect.c
index 314ac6638ae55038191b01ab208a4d589ca85fe9..1812416426dd4fd28604cfaaae5cbd30fed91fc2 100644 (file)
@@ -255,11 +255,13 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
        }
 
        if (passlen != 24) {
-               /* non encrypted password supplied. */
+               /* non encrypted password supplied. Ignore ntpass. */
                passlen = 24;
                ntpasslen = 24;
-               clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
-               clistr_push(cli, ntpword, ntpass, sizeof(ntpword), STR_TERMINATE);
+               clistr_push(cli, pword, 
+                           pass?pass:"", sizeof(pword), STR_TERMINATE|STR_ASCII);
+               clistr_push(cli, ntpword, 
+                           pass?pass:"", sizeof(ntpword), STR_TERMINATE|STR_ASCII);
                SMBencrypt((uchar *)pword,cli->secblob.data,(uchar *)pword);
                SMBNTencrypt((uchar *)ntpword,cli->secblob.data,(uchar *)ntpword);
        } else {
@@ -323,6 +325,7 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
        uint32 capabilities = cli_session_setup_capabilities(cli);
        char *p;
        DATA_BLOB blob2;
+       uint32 len;
 
        blob2 = data_blob(NULL, 0);
 
@@ -369,14 +372,16 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
 
        p += blob2.length;
        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);
+
+       /* w2k with kerberos doesn't properly null terminate this field */
+       len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
+       p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
 
        return blob2;
 }
 
 
-#if HAVE_KRB5
+#ifdef HAVE_KRB5
 /****************************************************************************
 do a spnego/kerberos encrypted session setup
 ****************************************************************************/
@@ -541,7 +546,7 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user,
 
        fstrcpy(cli->user_name, user);
 
-#if HAVE_KRB5
+#ifdef HAVE_KRB5
        if (got_kerberos_mechanism && cli->use_kerberos) {
                return cli_session_setup_kerberos(cli, principal, workgroup);
        }
@@ -571,7 +576,8 @@ BOOL cli_session_setup(struct cli_state *cli,
 
        /* allow for workgroups as part of the username */
        fstrcpy(user2, user);
-       if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/'))) {
+       if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
+           (p=strchr_m(user2,*lp_winbind_separator()))) {
                *p = 0;
                user = p+1;
                workgroup = user2;
@@ -973,11 +979,22 @@ open the client sockets
 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
 {
        extern pstring user_socket_options;
+       int name_type = 0x20;
+       char *p;
+
+       /* reasonable default hostname */
+       if (!host) host = "*SMBSERVER";
 
        fstrcpy(cli->desthost, host);
+
+       /* allow hostnames of the form NAME#xx and do a netbios lookup */
+       if ((p = strchr(cli->desthost, '#'))) {
+               name_type = strtol(p+1, NULL, 16);              
+               *p = 0;
+       }
        
        if (!ip || is_zero_ip(*ip)) {
-                if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
+                if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
                         return False;
                 }
                if (ip) *ip = cli->dest_ip;
@@ -1011,7 +1028,7 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
 }
 
 /****************************************************************************
-establishes a connection right up to doing tconX, reading in a password.
+establishes a connection right up to doing tconX, password in cache.
 ****************************************************************************/
 BOOL cli_establish_connection(struct cli_state *cli, 
                                char *dest_host, struct in_addr *dest_ip,
@@ -1144,7 +1161,7 @@ BOOL cli_establish_connection(struct cli_state *cli,
                        {
                                DEBUG(1,("failed tcon_X\n"));
                                if (do_shutdown)
-                  cli_shutdown(cli);
+                                       cli_shutdown(cli);
                                return False;
                        }
                }
@@ -1156,6 +1173,126 @@ BOOL cli_establish_connection(struct cli_state *cli,
        return True;
 }
 
+/* Initialise client credentials for authenticated pipe access */
+
+static void init_creds(struct ntuser_creds *creds, char* username,
+                      char* domain, char* password, int pass_len)
+{
+       ZERO_STRUCTP(creds);
+
+       pwd_set_cleartext(&creds->pwd, password);
+
+       fstrcpy(creds->user_name, username);
+       fstrcpy(creds->domain, domain);
+
+       if (!*username) {
+               creds->pwd.null_pwd = True;
+       }
+}
+
+/****************************************************************************
+establishes a connection right up to doing tconX, password specified.
+****************************************************************************/
+NTSTATUS cli_full_connection(struct cli_state **output_cli, 
+                            const char *my_name, const char *dest_host, 
+                            struct in_addr *dest_ip, int port,
+                            char *service, char *service_type,
+                            char *user, char *domain, 
+                            char *password, int pass_len) 
+{
+       struct ntuser_creds creds;
+       NTSTATUS nt_status;
+       struct nmb_name calling;
+       struct nmb_name called;
+       struct cli_state *cli;
+       struct in_addr ip;
+       
+       if (!output_cli) {
+               DEBUG(0, ("output_cli is NULL!?!"));
+       }
+
+       *output_cli = NULL;
+       
+       make_nmb_name(&calling, my_name, 0x0);
+       make_nmb_name(&called , dest_host, 0x20);
+
+again:
+
+       if (!(cli = cli_initialise(NULL))) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       if (cli_set_port(cli, port) != port) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       ip = *dest_ip;
+       
+       DEBUG(3,("Connecting to host=%s share=%s\n\n", 
+                dest_host, service));
+       
+       if (!cli_connect(cli, dest_host, &ip))
+       {
+               DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
+                        nmb_namestr(&called), inet_ntoa(*dest_ip)));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       if (!cli_session_request(cli, &calling, &called)) {
+               char *p;
+               DEBUG(1,("session request to %s failed (%s)\n", 
+                        called.name, cli_errstr(cli)));
+               cli_shutdown(cli);
+               if ((p=strchr(called.name, '.'))) {
+                       *p = 0;
+                       goto again;
+               }
+               if (strcmp(called.name, "*SMBSERVER")) {
+                       make_nmb_name(&called , "*SMBSERVER", 0x20);
+                       goto again;
+               }
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       if (!cli_negprot(cli))
+       {
+               DEBUG(1,("failed negprot\n"));
+               nt_status = NT_STATUS_UNSUCCESSFUL;
+               cli_shutdown(cli);
+               return nt_status;
+       }
+
+       if (!cli_session_setup(cli, user,
+                              password, pass_len,
+                              NULL, 0,
+                              domain))
+       {
+               DEBUG(1,("failed session setup\n"));
+               nt_status = cli_nt_error(cli);
+               cli_shutdown(cli);
+               if (NT_STATUS_IS_OK(nt_status)) nt_status = NT_STATUS_UNSUCCESSFUL;
+               return nt_status;
+       } 
+
+       if (service)
+       {
+               if (!cli_send_tconX(cli, service, service_type,
+                                   (char*)password, pass_len))
+               {
+                       DEBUG(1,("failed tcon_X\n"));
+                       nt_status = cli_nt_error(cli);
+                       cli_shutdown(cli);
+                       if (NT_STATUS_IS_OK(nt_status)) nt_status = NT_STATUS_UNSUCCESSFUL;
+                       return nt_status;
+               }
+       }
+
+       init_creds(&creds, user, domain, password, pass_len);
+       cli_init_creds(cli, &creds);
+
+       *output_cli = cli;
+       return NT_STATUS_OK;
+}
 
 /****************************************************************************
  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
@@ -1196,9 +1333,9 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char
 
         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
 with error %s.\n", desthost, cli_errstr(cli) ));
-           cli_shutdown(cli);
-               return False;
-       }
+       cli_shutdown(cli);
+       return False;
+    }
 
     cli_shutdown(cli);
 
@@ -1214,3 +1351,5 @@ name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
 
   return True;
 }
+
+