Fix a segv in winbindd caused by trying to free an fstring.
[samba.git] / source3 / winbindd / winbindd_cm.c
index 00d9092dc3d01256c43922a67f75a05d413a2f97..6c5633c2b2c90caee983192e7dc55e3f0e133129 100644 (file)
@@ -635,6 +635,40 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
        return True;
 }
 
+/**
+ * Helper function to assemble trust password and account name
+ */
+static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
+                               char **machine_password,
+                               char **machine_account,
+                               char **machine_krb5_principal)
+{
+       const char *account_name;
+
+       if (!get_trust_pw_clear(domain->name, machine_password,
+                               &account_name, NULL))
+       {
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+
+       if ((machine_account != NULL) &&
+           (asprintf(machine_account, "%s$", account_name) == -1))
+       {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* this is at least correct when domain is our domain,
+        * which is the only case, when this is currently used: */
+       if ((machine_krb5_principal != NULL) &&
+           (asprintf(machine_krb5_principal, "%s$@%s", account_name,
+                     domain->alt_name) == -1))
+       {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return NT_STATUS_OK;
+}
+
 /************************************************************************
  Given a fd with a just-connected TCP connection to a DC, open a connection
  to the pipe.
@@ -649,7 +683,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
        char *machine_password = NULL;
        char *machine_krb5_principal = NULL;
        char *machine_account = NULL;
-       const char *account_name = NULL;
        char *ipc_username = NULL;
        char *ipc_domain = NULL;
        char *ipc_password = NULL;
@@ -729,22 +762,10 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
        {
                ADS_STATUS ads_status;
 
-               if (!get_trust_pw_clear(domain->name, &machine_password,
-                                       &account_name, NULL))
-               {
-                       result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-                       goto done;
-               }
-
-               if (asprintf(&machine_account, "%s$", account_name) == -1) {
-                       result = NT_STATUS_NO_MEMORY;
-                       goto done;
-               }
-
-               if (asprintf(&machine_krb5_principal, "%s$@%s", account_name,
-                            lp_realm()) == -1)
-               {
-                       result = NT_STATUS_NO_MEMORY;
+               result = get_trust_creds(domain, &machine_password,
+                                        &machine_account,
+                                        &machine_krb5_principal);
+               if (!NT_STATUS_IS_OK(result)) {
                        goto done;
                }
 
@@ -1947,6 +1968,9 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        fstring conn_pwd;
        struct dcinfo *p_dcinfo;
+       char *machine_password = NULL;
+       char *machine_account = NULL;
+       char *domain_name = NULL;
 
        result = init_dc_connection(domain);
        if (!NT_STATUS_IS_OK(result)) {
@@ -1969,10 +1993,26 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
        if ((conn->cli->user_name[0] == '\0') ||
            (conn->cli->domain[0] == '\0') || 
-           (conn_pwd[0] == '\0')) {
-               DEBUG(10, ("cm_connect_sam: No no user available for "
-                          "domain %s, trying schannel\n", conn->cli->domain));
+           (conn_pwd[0] == '\0'))
+       {
+               result = get_trust_creds(domain, &machine_password,
+                                        &machine_account, NULL);
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(10, ("cm_connect_sam: No no user available for "
+                                  "domain %s, trying schannel\n", conn->cli->domain));
+                       goto schannel;
+               }
+               domain_name = domain->name;
                goto schannel;
+       } else {
+               machine_password = SMB_STRDUP(conn_pwd);                
+               machine_account = SMB_STRDUP(conn->cli->user_name);
+               domain_name = conn->cli->domain;
+       }
+
+       if (!machine_password || !machine_account) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
        }
 
        /* We have an authenticated connection. Use a NTLMSSP SPNEGO
@@ -1980,23 +2020,23 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        conn->samr_pipe =
                cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
                                                 PIPE_AUTH_LEVEL_PRIVACY,
-                                                conn->cli->domain,
-                                                conn->cli->user_name,
-                                                conn_pwd, &result);
+                                                domain_name,
+                                                machine_account,
+                                                machine_password, &result);
 
        if (conn->samr_pipe == NULL) {
                DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
                          "pipe for domain %s using NTLMSSP "
                          "authenticated pipe: user %s\\%s. Error was "
-                         "%s\n", domain->name, conn->cli->domain,
-                         conn->cli->user_name, nt_errstr(result)));
+                         "%s\n", domain->name, domain_name,
+                         machine_account, nt_errstr(result)));
                goto schannel;
        }
 
        DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
                  "domain %s using NTLMSSP authenticated "
                  "pipe: user %s\\%s\n", domain->name,
-                 conn->cli->domain, conn->cli->user_name ));
+                 domain_name, machine_account));
 
        result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
@@ -2081,6 +2121,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 
        *cli = conn->samr_pipe;
        *sam_handle = conn->sam_domain_handle;
+       SAFE_FREE(machine_password);
+       SAFE_FREE(machine_account);
        return result;
 }