LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_pam.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 250 1582 15.8 %
Date: 2024-05-31 13:13:24 Functions: 8 30 26.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Winbind daemon - pam auth functions
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2000
       7             :    Copyright (C) Tim Potter 2001
       8             :    Copyright (C) Andrew Bartlett 2001-2002
       9             :    Copyright (C) Guenther Deschner 2005
      10             : 
      11             :    This program is free software; you can redistribute it and/or modify
      12             :    it under the terms of the GNU General Public License as published by
      13             :    the Free Software Foundation; either version 3 of the License, or
      14             :    (at your option) any later version.
      15             : 
      16             :    This program is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :    GNU General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU General Public License
      22             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "includes.h"
      26             : #include "ntdomain.h"
      27             : #include "winbindd.h"
      28             : #include "libsmb/namequery.h"
      29             : #include "../libcli/auth/libcli_auth.h"
      30             : #include "libcli/auth/pam_errors.h"
      31             : #include "../librpc/gen_ndr/ndr_samr_c.h"
      32             : #include "librpc/rpc/dcesrv_core.h"
      33             : #include "librpc/gen_ndr/ndr_winbind.h"
      34             : #include "rpc_client/cli_pipe.h"
      35             : #include "rpc_client/cli_samr.h"
      36             : #include "../librpc/gen_ndr/ndr_netlogon.h"
      37             : #include "rpc_client/cli_netlogon.h"
      38             : #include "smb_krb5.h"
      39             : #include "../libcli/security/security.h"
      40             : #include "ads.h"
      41             : #include "../librpc/gen_ndr/krb5pac.h"
      42             : #include "passdb/machine_sid.h"
      43             : #include "auth.h"
      44             : #include "../lib/tsocket/tsocket.h"
      45             : #include "auth/kerberos/pac_utils.h"
      46             : #include "auth/gensec/gensec.h"
      47             : #include "librpc/crypto/gse_krb5.h"
      48             : #include "lib/afs/afs_funcs.h"
      49             : #include "libsmb/samlogon_cache.h"
      50             : #include "rpc_client/util_netlogon.h"
      51             : #include "param/param.h"
      52             : #include "messaging/messaging.h"
      53             : #include "lib/util/string_wrappers.h"
      54             : #include "lib/crypto/gnutls_helpers.h"
      55             : 
      56             : #include "lib/crypto/gnutls_helpers.h"
      57             : #include <gnutls/crypto.h>
      58             : #include "lib/global_contexts.h"
      59             : 
      60             : #undef DBGC_CLASS
      61             : #define DBGC_CLASS DBGC_WINBIND
      62             : 
      63             : #define LOGON_KRB5_FAIL_CLOCK_SKEW      0x02000000
      64             : 
      65        1436 : static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
      66             :                                     struct winbindd_response *resp,
      67             :                                     uint16_t validation_level,
      68             :                                     union netr_Validation *validation)
      69             : {
      70        1436 :         struct netr_SamInfo3 *info3 = NULL;
      71        1436 :         char *ex = NULL;
      72           0 :         uint32_t i;
      73        1436 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
      74        1436 :         TALLOC_CTX *frame = talloc_stackframe();
      75             : 
      76        1436 :         status = map_validation_to_info3(frame,
      77             :                                          validation_level,
      78             :                                          validation,
      79             :                                          &info3);
      80        1436 :         if (!NT_STATUS_IS_OK(status)) {
      81           0 :                 goto out;
      82             :         }
      83             : 
      84        1436 :         resp->data.auth.info3.logon_time =
      85        1436 :                 nt_time_to_unix(info3->base.logon_time);
      86        1436 :         resp->data.auth.info3.logoff_time =
      87        1436 :                 nt_time_to_unix(info3->base.logoff_time);
      88        1436 :         resp->data.auth.info3.kickoff_time =
      89        1436 :                 nt_time_to_unix(info3->base.kickoff_time);
      90        1436 :         resp->data.auth.info3.pass_last_set_time =
      91        1436 :                 nt_time_to_unix(info3->base.last_password_change);
      92        1436 :         resp->data.auth.info3.pass_can_change_time =
      93        1436 :                 nt_time_to_unix(info3->base.allow_password_change);
      94        1436 :         resp->data.auth.info3.pass_must_change_time =
      95        1436 :                 nt_time_to_unix(info3->base.force_password_change);
      96             : 
      97        1436 :         resp->data.auth.info3.logon_count = info3->base.logon_count;
      98        1436 :         resp->data.auth.info3.bad_pw_count = info3->base.bad_password_count;
      99             : 
     100        1436 :         resp->data.auth.info3.user_rid = info3->base.rid;
     101        1436 :         resp->data.auth.info3.group_rid = info3->base.primary_gid;
     102        1436 :         sid_to_fstring(resp->data.auth.info3.dom_sid, info3->base.domain_sid);
     103             : 
     104        1436 :         resp->data.auth.info3.num_groups = info3->base.groups.count;
     105        1436 :         resp->data.auth.info3.user_flgs = info3->base.user_flags;
     106             : 
     107        1436 :         resp->data.auth.info3.acct_flags = info3->base.acct_flags;
     108        1436 :         resp->data.auth.info3.num_other_sids = info3->sidcount;
     109             : 
     110        1436 :         fstrcpy(resp->data.auth.info3.user_name,
     111             :                 info3->base.account_name.string);
     112        1436 :         fstrcpy(resp->data.auth.info3.full_name,
     113             :                 info3->base.full_name.string);
     114        1436 :         fstrcpy(resp->data.auth.info3.logon_script,
     115             :                 info3->base.logon_script.string);
     116        1436 :         fstrcpy(resp->data.auth.info3.profile_path,
     117             :                 info3->base.profile_path.string);
     118        1436 :         fstrcpy(resp->data.auth.info3.home_dir,
     119             :                 info3->base.home_directory.string);
     120        1436 :         fstrcpy(resp->data.auth.info3.dir_drive,
     121             :                 info3->base.home_drive.string);
     122             : 
     123        1436 :         fstrcpy(resp->data.auth.info3.logon_srv,
     124             :                 info3->base.logon_server.string);
     125        1436 :         fstrcpy(resp->data.auth.info3.logon_dom,
     126             :                 info3->base.logon_domain.string);
     127             : 
     128        1436 :         resp->data.auth.validation_level = validation_level;
     129        1436 :         if (validation_level == 6) {
     130        1290 :                 fstrcpy(resp->data.auth.info6.dns_domainname,
     131             :                         validation->sam6->dns_domainname.string);
     132        1290 :                 fstrcpy(resp->data.auth.info6.principal_name,
     133             :                         validation->sam6->principal_name.string);
     134             :         }
     135             : 
     136        1436 :         ex = talloc_strdup(frame, "");
     137        1436 :         if (ex == NULL) {
     138           0 :                 status = NT_STATUS_NO_MEMORY;
     139           0 :                 goto out;
     140             :         }
     141             : 
     142        7554 :         for (i=0; i < info3->base.groups.count; i++) {
     143       12236 :                 ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
     144        6118 :                                                    info3->base.groups.rids[i].rid,
     145        6118 :                                                    info3->base.groups.rids[i].attributes);
     146        6118 :                 if (ex == NULL) {
     147           0 :                         status = NT_STATUS_NO_MEMORY;
     148           0 :                         goto out;
     149             :                 }
     150             :         }
     151             : 
     152        4074 :         for (i=0; i < info3->sidcount; i++) {
     153           0 :                 struct dom_sid_buf sidbuf;
     154             : 
     155        2638 :                 ex = talloc_asprintf_append_buffer(
     156             :                         ex,
     157             :                         "%s:0x%08X\n",
     158        2638 :                         dom_sid_str_buf(info3->sids[i].sid, &sidbuf),
     159        2638 :                         info3->sids[i].attributes);
     160        2638 :                 if (ex == NULL) {
     161           0 :                         status = NT_STATUS_NO_MEMORY;
     162           0 :                         goto out;
     163             :                 }
     164             :         }
     165             : 
     166        1436 :         resp->length += talloc_get_size(ex);
     167        1436 :         resp->extra_data.data = talloc_move(mem_ctx, &ex);
     168             : 
     169        1436 :         status = NT_STATUS_OK;
     170        1436 : out:
     171        1436 :         TALLOC_FREE(frame);
     172        1436 :         return status;
     173             : }
     174             : 
     175           0 : static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
     176             :                                     struct winbindd_response *resp,
     177             :                                     struct netr_SamInfo3 *info3)
     178             : {
     179           0 :         DATA_BLOB blob;
     180           0 :         enum ndr_err_code ndr_err;
     181             : 
     182           0 :         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, info3,
     183             :                                        (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
     184           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     185           0 :                 DEBUG(0,("append_info3_as_ndr: failed to append\n"));
     186           0 :                 return ndr_map_error2ntstatus(ndr_err);
     187             :         }
     188             : 
     189           0 :         resp->extra_data.data = blob.data;
     190           0 :         resp->length += blob.length;
     191             : 
     192           0 :         return NT_STATUS_OK;
     193             : }
     194             : 
     195         192 : static NTSTATUS append_unix_username(uint16_t validation_level,
     196             :                                      union netr_Validation  *validation,
     197             :                                      const char *name_domain,
     198             :                                      const char *name_user,
     199             :                                      TALLOC_CTX *mem_ctx,
     200             :                                      char **_unix_username)
     201             : {
     202         192 :         TALLOC_CTX *tmp_ctx = NULL;
     203         192 :         const char *nt_username = NULL;
     204         192 :         const char *nt_domain = NULL;
     205         192 :         char *unix_username = NULL;
     206         192 :         struct netr_SamBaseInfo *base_info = NULL;
     207           0 :         NTSTATUS status;
     208             : 
     209         192 :         tmp_ctx = talloc_new(mem_ctx);
     210         192 :         if (tmp_ctx == NULL) {
     211           0 :                 return NT_STATUS_NO_MEMORY;
     212             :         }
     213             : 
     214             :         /* We've been asked to return the unix username, per
     215             :            'winbind use default domain' settings and the like */
     216             : 
     217         192 :         switch (validation_level) {
     218          30 :         case 3:
     219          30 :                 base_info = &validation->sam3->base;
     220          30 :                 break;
     221         162 :         case 6:
     222         162 :                 base_info = &validation->sam6->base;
     223         162 :                 break;
     224           0 :         default:
     225           0 :                 DBG_ERR("Invalid validation level %d\n", validation_level);
     226           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     227           0 :                 goto out;
     228             :         }
     229             : 
     230         192 :         nt_domain = talloc_strdup(tmp_ctx, base_info->logon_domain.string);
     231         192 :         if (!nt_domain) {
     232             :                 /* If the server didn't give us one, just use the one
     233             :                  * we sent them */
     234           0 :                 nt_domain = name_domain;
     235             :         }
     236             : 
     237         192 :         nt_username = talloc_strdup(tmp_ctx, base_info->account_name.string);
     238         192 :         if (!nt_username) {
     239             :                 /* If the server didn't give us one, just use the one
     240             :                  * we sent them */
     241           0 :                 nt_username = name_user;
     242             :         }
     243             : 
     244         192 :         unix_username = fill_domain_username_talloc(tmp_ctx,
     245             :                                                     nt_domain,
     246             :                                                     nt_username,
     247             :                                                     true);
     248         192 :         if (unix_username == NULL) {
     249           0 :                 status = NT_STATUS_NO_MEMORY;
     250           0 :                 goto out;
     251             :         }
     252             : 
     253         192 :         DBG_INFO("Setting unix username to [%s]\n", unix_username);
     254             : 
     255         192 :         *_unix_username = talloc_move(mem_ctx, &unix_username);
     256             : 
     257         192 :         status = NT_STATUS_OK;
     258         192 : out:
     259         192 :         TALLOC_FREE(tmp_ctx);
     260             : 
     261         192 :         return status;
     262             : }
     263             : 
     264           0 : static NTSTATUS append_afs_token(uint16_t validation_level,
     265             :                                  union netr_Validation  *validation,
     266             :                                  const char *name_domain,
     267             :                                  const char *name_user,
     268             :                                  TALLOC_CTX *mem_ctx,
     269             :                                  DATA_BLOB *_blob)
     270             : {
     271           0 :         TALLOC_CTX *tmp_ctx = NULL;
     272           0 :         char *afsname = NULL;
     273           0 :         char *cell;
     274           0 :         char *token;
     275           0 :         struct netr_SamBaseInfo *base_info = NULL;
     276           0 :         NTSTATUS status;
     277             : 
     278           0 :         tmp_ctx = talloc_new(mem_ctx);
     279           0 :         if (tmp_ctx == NULL) {
     280           0 :                 return NT_STATUS_NO_MEMORY;
     281             :         }
     282             : 
     283           0 :         switch (validation_level) {
     284           0 :         case 3:
     285           0 :                 base_info = &validation->sam3->base;
     286           0 :                 break;
     287           0 :         case 6:
     288           0 :                 base_info = &validation->sam6->base;
     289           0 :                 break;
     290           0 :         default:
     291           0 :                 DBG_ERR("Invalid validation level %d\n", validation_level);
     292           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     293           0 :                 goto out;
     294             :         }
     295             : 
     296           0 :         afsname = talloc_strdup(tmp_ctx, lp_afs_username_map());
     297           0 :         if (afsname == NULL) {
     298           0 :                 status = NT_STATUS_NO_MEMORY;
     299           0 :                 goto out;
     300             :         }
     301             : 
     302           0 :         afsname = talloc_string_sub(tmp_ctx,
     303             :                                     lp_afs_username_map(),
     304             :                                     "%D", name_domain);
     305           0 :         afsname = talloc_string_sub(tmp_ctx, afsname,
     306             :                                     "%u", name_user);
     307           0 :         afsname = talloc_string_sub(tmp_ctx, afsname,
     308             :                                     "%U", name_user);
     309             : 
     310             :         {
     311           0 :                 struct dom_sid user_sid;
     312           0 :                 struct dom_sid_buf sidstr;
     313             : 
     314           0 :                 sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
     315           0 :                 afsname = talloc_string_sub(
     316             :                         tmp_ctx,
     317             :                         afsname,
     318             :                         "%s",
     319           0 :                         dom_sid_str_buf(&user_sid, &sidstr));
     320             :         }
     321             : 
     322           0 :         if (afsname == NULL) {
     323           0 :                 status = NT_STATUS_NO_MEMORY;
     324           0 :                 goto out;
     325             :         }
     326             : 
     327           0 :         if (!strlower_m(afsname)) {
     328           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     329           0 :                 goto out;
     330             :         }
     331             : 
     332           0 :         DEBUG(10, ("Generating token for user %s\n", afsname));
     333             : 
     334           0 :         cell = strchr(afsname, '@');
     335             : 
     336           0 :         if (cell == NULL) {
     337           0 :                 status = NT_STATUS_NO_MEMORY;
     338           0 :                 goto out;
     339             :         }
     340             : 
     341           0 :         *cell = '\0';
     342           0 :         cell += 1;
     343             : 
     344           0 :         token = afs_createtoken_str(afsname, cell);
     345           0 :         if (token == NULL) {
     346           0 :                 status = NT_STATUS_OK;
     347           0 :                 goto out;
     348             :         }
     349             : 
     350           0 :         talloc_steal(mem_ctx, token);
     351           0 :         *_blob = data_blob_string_const_null(token);
     352             : 
     353           0 :         status = NT_STATUS_OK;
     354           0 : out:
     355           0 :         TALLOC_FREE(tmp_ctx);
     356             : 
     357           0 :         return status;
     358             : }
     359             : 
     360        1101 : NTSTATUS extra_data_to_sid_array(const char *group_sid,
     361             :                                 TALLOC_CTX *mem_ctx,
     362             :                                 struct wbint_SidArray **_sid_array)
     363             : {
     364        1101 :         TALLOC_CTX *tmp_ctx = NULL;
     365        1101 :         struct wbint_SidArray *sid_array = NULL;
     366        1101 :         struct dom_sid *require_membership_of_sid = NULL;
     367        1101 :         uint32_t num_require_membership_of_sid = 0;
     368        1101 :         char *req_sid = NULL;
     369        1101 :         const char *p = NULL;
     370           0 :         NTSTATUS status;
     371             : 
     372        1101 :         if (_sid_array == NULL) {
     373           0 :                 return NT_STATUS_INVALID_PARAMETER;
     374             :         }
     375             : 
     376        1101 :         *_sid_array = NULL;
     377             : 
     378        1101 :         tmp_ctx = talloc_new(mem_ctx);
     379        1101 :         if (tmp_ctx == NULL) {
     380           0 :                 return NT_STATUS_NO_MEMORY;
     381             :         }
     382             : 
     383        1101 :         sid_array = talloc_zero(tmp_ctx, struct wbint_SidArray);
     384        1101 :         if (sid_array == NULL) {
     385           0 :                 status = NT_STATUS_NO_MEMORY;
     386           0 :                 goto fail;
     387             :         }
     388             : 
     389        1101 :         if (!group_sid || !group_sid[0]) {
     390             :                 /* NO sid supplied, all users may access */
     391        1049 :                 status = NT_STATUS_OK;
     392             :                 /*
     393             :                  * Always return an allocated wbint_SidArray,
     394             :                  * even if the array is empty.
     395             :                  */
     396        1049 :                 goto out;
     397             :         }
     398             : 
     399          52 :         num_require_membership_of_sid = 0;
     400          52 :         require_membership_of_sid = NULL;
     401          52 :         p = group_sid;
     402             : 
     403         104 :         while (next_token_talloc(tmp_ctx, &p, &req_sid, ",")) {
     404           0 :                 struct dom_sid sid;
     405             : 
     406          52 :                 if (!string_to_sid(&sid, req_sid)) {
     407           0 :                         DBG_ERR("check_info3_in_group: could not parse %s "
     408             :                                 "as a SID!\n", req_sid);
     409           0 :                         status = NT_STATUS_INVALID_PARAMETER;
     410           0 :                         goto fail;
     411             :                 }
     412             : 
     413          52 :                 status = add_sid_to_array(tmp_ctx, &sid,
     414             :                                           &require_membership_of_sid,
     415             :                                           &num_require_membership_of_sid);
     416          52 :                 if (!NT_STATUS_IS_OK(status)) {
     417           0 :                         DBG_ERR("add_sid_to_array failed\n");
     418           0 :                         goto fail;
     419             :                 }
     420             :         }
     421             : 
     422          52 :         sid_array->num_sids = num_require_membership_of_sid;
     423          52 :         sid_array->sids = talloc_move(sid_array, &require_membership_of_sid);
     424             : 
     425          52 :         status = NT_STATUS_OK;
     426        1101 : out:
     427        1101 :         *_sid_array = talloc_move(mem_ctx, &sid_array);
     428             : 
     429        1101 : fail:
     430        1101 :         TALLOC_FREE(tmp_ctx);
     431             : 
     432        1101 :         return status;
     433             : }
     434             : 
     435           0 : static NTSTATUS check_info3_in_group(struct netr_SamInfo3 *info3,
     436             :                                      struct wbint_SidArray *sid_array)
     437             : /**
     438             :  * Check whether a user belongs to a group or list of groups.
     439             :  *
     440             :  * @param mem_ctx talloc memory context.
     441             :  * @param info3 user information, including group membership info.
     442             :  * @param group_sid One or more groups , separated by commas.
     443             :  *
     444             :  * @return NT_STATUS_OK on success,
     445             :  *    NT_STATUS_LOGON_FAILURE if the user does not belong,
     446             :  *    or other NT_STATUS_IS_ERR(status) for other kinds of failure.
     447             :  */
     448             : {
     449           0 :         size_t i;
     450           0 :         struct security_token *token;
     451           0 :         NTSTATUS status;
     452             : 
     453             :         /* Parse the 'required group' SID */
     454             : 
     455           0 :         if (sid_array == NULL || sid_array->num_sids == 0) {
     456             :                 /* NO sid supplied, all users may access */
     457           0 :                 return NT_STATUS_OK;
     458             :         }
     459             : 
     460             :         /*
     461             :          * This is a limited-use security_token for the purpose of
     462             :          * checking the SID list below, so no claims need to be added
     463             :          * and se_access_check() will never run.
     464             :          */
     465           0 :         token = security_token_initialise(talloc_tos(),
     466             :                                           CLAIMS_EVALUATION_INVALID_STATE);
     467           0 :         if (token == NULL) {
     468           0 :                 DEBUG(0, ("talloc failed\n"));
     469           0 :                 return NT_STATUS_NO_MEMORY;
     470             :         }
     471             : 
     472           0 :         status = sid_array_from_info3(token, info3,
     473             :                                       &token->sids,
     474             :                                       &token->num_sids,
     475             :                                       true);
     476           0 :         if (!NT_STATUS_IS_OK(status)) {
     477           0 :                 return status;
     478             :         }
     479             : 
     480           0 :         if (!NT_STATUS_IS_OK(status = add_aliases(get_global_sam_sid(),
     481             :                                                   token))
     482           0 :             || !NT_STATUS_IS_OK(status = add_aliases(&global_sid_Builtin,
     483             :                                                      token))) {
     484           0 :                 DEBUG(3, ("could not add aliases: %s\n",
     485             :                           nt_errstr(status)));
     486           0 :                 return status;
     487             :         }
     488             : 
     489           0 :         security_token_debug(DBGC_CLASS, 10, token);
     490             : 
     491           0 :         for (i=0; i<sid_array->num_sids; i++) {
     492           0 :                 struct dom_sid_buf buf;
     493           0 :                 DEBUG(10, ("Checking SID %s\n",
     494             :                            dom_sid_str_buf(&sid_array->sids[i],
     495             :                                            &buf)));
     496           0 :                 if (nt_token_check_sid(&sid_array->sids[i],
     497             :                                        token)) {
     498           0 :                         DEBUG(10, ("Access ok\n"));
     499           0 :                         return NT_STATUS_OK;
     500             :                 }
     501             :         }
     502             : 
     503             :         /* Do not distinguish this error from a wrong username/pw */
     504             : 
     505           0 :         return NT_STATUS_LOGON_FAILURE;
     506             : }
     507             : 
     508        3423 : struct winbindd_domain *find_auth_domain(uint8_t flags,
     509             :                                          const char *domain_name)
     510             : {
     511           0 :         struct winbindd_domain *domain;
     512             : 
     513        3423 :         if (IS_DC) {
     514        2418 :                 domain = find_domain_from_name_noinit(domain_name);
     515        2418 :                 if (domain == NULL) {
     516        2184 :                         DEBUG(3, ("Authentication for domain [%s] refused "
     517             :                                   "as it is not a trusted domain\n",
     518             :                                   domain_name));
     519        2184 :                         return NULL;
     520             :                 }
     521             : 
     522         234 :                 if (domain->secure_channel_type != SEC_CHAN_NULL) {
     523         234 :                         return domain;
     524             :                 }
     525             : 
     526           0 :                 return domain->routing_domain;
     527             :         }
     528             : 
     529        1005 :         if (strequal(domain_name, get_global_sam_name())) {
     530          78 :                 return find_domain_from_name_noinit(domain_name);
     531             :         }
     532             : 
     533         927 :         if (lp_winbind_use_krb5_enterprise_principals()) {
     534             :                 /*
     535             :                  * If we use enterprise principals
     536             :                  * we always go through our primary domain
     537             :                  * and follow the WRONG_REALM replies.
     538             :                  */
     539         927 :                 flags &= ~WBFLAG_PAM_CONTACT_TRUSTDOM;
     540             :         }
     541             : 
     542             :         /* we can auth against trusted domains */
     543         927 :         if (flags & WBFLAG_PAM_CONTACT_TRUSTDOM) {
     544           0 :                 domain = find_domain_from_name_noinit(domain_name);
     545           0 :                 if (domain == NULL) {
     546           0 :                         DEBUG(3, ("Authentication for domain [%s] skipped "
     547             :                                   "as it is not a trusted domain\n",
     548             :                                   domain_name));
     549             :                 } else {
     550           0 :                         return domain;
     551             :                 }
     552             :         }
     553             : 
     554         927 :         return find_our_domain();
     555             : }
     556             : 
     557           0 : static NTSTATUS get_password_policy(struct winbindd_domain *domain,
     558             :                                     TALLOC_CTX *mem_ctx,
     559             :                                     struct samr_DomInfo1 **_policy)
     560             : {
     561           0 :         NTSTATUS status;
     562           0 :         struct samr_DomInfo1 *policy = NULL;
     563             : 
     564           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     565           0 :                 DBG_INFO("No inbound trust to contact domain %s\n",
     566             :                          domain->name);
     567           0 :                 return NT_STATUS_NOT_SUPPORTED;
     568             :         }
     569             : 
     570           0 :         policy = talloc_zero(mem_ctx, struct samr_DomInfo1);
     571           0 :         if (policy == NULL) {
     572           0 :                 return NT_STATUS_NO_MEMORY;
     573             :         }
     574             : 
     575           0 :         status = wb_cache_password_policy(domain, mem_ctx, policy);
     576           0 :         if (NT_STATUS_IS_ERR(status)) {
     577           0 :                 TALLOC_FREE(policy);
     578           0 :                 return status;
     579             :         }
     580             : 
     581           0 :         *_policy = talloc_move(mem_ctx, &policy);
     582             : 
     583           0 :         return NT_STATUS_OK;
     584             : }
     585             : 
     586           0 : static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain,
     587             :                                                          TALLOC_CTX *mem_ctx,
     588             :                                                          uint16_t *lockout_threshold)
     589             : {
     590           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     591           0 :         struct samr_DomInfo12 lockout_policy;
     592             : 
     593           0 :         *lockout_threshold = 0;
     594             : 
     595           0 :         status = wb_cache_lockout_policy(domain, mem_ctx, &lockout_policy);
     596           0 :         if (NT_STATUS_IS_ERR(status)) {
     597           0 :                 return status;
     598             :         }
     599             : 
     600           0 :         *lockout_threshold = lockout_policy.lockout_threshold;
     601             : 
     602           0 :         return NT_STATUS_OK;
     603             : }
     604             : 
     605           0 : static NTSTATUS get_pwd_properties(struct winbindd_domain *domain,
     606             :                                    TALLOC_CTX *mem_ctx,
     607             :                                    uint32_t *password_properties)
     608             : {
     609           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     610           0 :         struct samr_DomInfo1 password_policy;
     611             : 
     612           0 :         *password_properties = 0;
     613             : 
     614           0 :         status = wb_cache_password_policy(domain, mem_ctx, &password_policy);
     615           0 :         if (NT_STATUS_IS_ERR(status)) {
     616           0 :                 return status;
     617             :         }
     618             : 
     619           0 :         *password_properties = password_policy.password_properties;
     620             : 
     621           0 :         return NT_STATUS_OK;
     622             : }
     623             : 
     624             : #ifdef HAVE_KRB5
     625             : 
     626           0 : static bool generate_krb5_ccache(TALLOC_CTX *mem_ctx,
     627             :                                  const char *type,
     628             :                                  uid_t uid,
     629             :                                  const char **user_ccache_file)
     630             : {
     631             :         /* accept FILE and WRFILE as krb5_cc_type from the client and then
     632             :          * build the full ccname string based on the user's uid here -
     633             :          * Guenther*/
     634             : 
     635           0 :         const char *gen_cc = NULL;
     636             : 
     637           0 :         if (uid != -1) {
     638           0 :                 if (strequal(type, "FILE")) {
     639           0 :                         gen_cc = talloc_asprintf(
     640             :                                 mem_ctx, "FILE:/tmp/krb5cc_%d", uid);
     641           0 :                         if (gen_cc == NULL) {
     642           0 :                                 return false;
     643             :                         }
     644             :                 }
     645           0 :                 if (strequal(type, "WRFILE")) {
     646           0 :                         gen_cc = talloc_asprintf(
     647             :                                 mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid);
     648           0 :                         if (gen_cc == NULL) {
     649           0 :                                 return false;
     650             :                         }
     651             :                 }
     652           0 :                 if (strequal(type, "KEYRING")) {
     653           0 :                         gen_cc = talloc_asprintf(
     654             :                                 mem_ctx, "KEYRING:persistent:%d", uid);
     655           0 :                         if (gen_cc == NULL) {
     656           0 :                                 return false;
     657             :                         }
     658             :                 }
     659           0 :                 if (strequal(type, "KCM")) {
     660           0 :                         gen_cc = talloc_asprintf(mem_ctx,
     661             :                                                  "KCM:%d",
     662             :                                                  uid);
     663           0 :                         if (gen_cc == NULL) {
     664           0 :                                 return false;
     665             :                         }
     666             :                 }
     667             : 
     668           0 :                 if (strnequal(type, "FILE:/", 6) ||
     669           0 :                     strnequal(type, "WRFILE:/", 8) ||
     670           0 :                     strnequal(type, "DIR:/", 5)) {
     671             : 
     672             :                         /* we allow only one "%u" substitution */
     673             : 
     674           0 :                         char *p;
     675             : 
     676           0 :                         p = strchr(type, '%');
     677           0 :                         if (p != NULL) {
     678             : 
     679           0 :                                 p++;
     680             : 
     681           0 :                                 if (p != NULL && *p == 'u' && strchr(p, '%') == NULL) {
     682           0 :                                         char uid_str[sizeof("18446744073709551615")];
     683             : 
     684           0 :                                         snprintf(uid_str, sizeof(uid_str), "%u", uid);
     685             : 
     686           0 :                                         gen_cc = talloc_string_sub2(mem_ctx,
     687             :                                                         type,
     688             :                                                         "%u",
     689             :                                                         uid_str,
     690             :                                                         /* remove_unsafe_characters */
     691             :                                                         false,
     692             :                                                         /* replace_once */
     693             :                                                         true,
     694             :                                                         /* allow_trailing_dollar */
     695             :                                                         false);
     696           0 :                                         if (gen_cc == NULL) {
     697           0 :                                                 return false;
     698             :                                         }
     699             :                                 }
     700             :                         }
     701             :                 }
     702             :         }
     703             : 
     704           0 :         *user_ccache_file = gen_cc;
     705             : 
     706           0 :         DBG_DEBUG("using ccache: %s\n", gen_cc != NULL ? gen_cc : "(internal)");
     707             : 
     708           0 :         return true;
     709             : }
     710             : 
     711             : #endif
     712             : 
     713           0 : uid_t get_uid_from_request(struct winbindd_request *request)
     714             : {
     715           0 :         uid_t uid;
     716             : 
     717           0 :         uid = request->data.auth.uid;
     718             : 
     719           0 :         if (uid == (uid_t)-1) {
     720           0 :                 DEBUG(1,("invalid uid: '%u'\n", (unsigned int)uid));
     721           0 :                 return -1;
     722             :         }
     723           0 :         return uid;
     724             : }
     725             : 
     726             : /**********************************************************************
     727             :  Authenticate a user with a clear text password using Kerberos and fill up
     728             :  ccache if required
     729             :  **********************************************************************/
     730             : 
     731           0 : static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
     732             :                                             struct winbindd_domain *domain,
     733             :                                             const char *user,
     734             :                                             const char *pass,
     735             :                                             const char *krb5_cc_type,
     736             :                                             uid_t uid,
     737             :                                             struct netr_SamInfo6 **info6,
     738             :                                             const char **_krb5ccname)
     739             : {
     740             : #ifdef HAVE_KRB5
     741           0 :         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
     742           0 :         const char *cc = NULL;
     743           0 :         const char *principal_s = NULL;
     744           0 :         char *realm = NULL;
     745           0 :         char *name_namespace = NULL;
     746           0 :         char *name_domain = NULL;
     747           0 :         char *name_user = NULL;
     748           0 :         time_t ticket_lifetime = 0;
     749           0 :         time_t renewal_until = 0;
     750           0 :         const char *user_ccache_file;
     751           0 :         struct PAC_LOGON_INFO *logon_info = NULL;
     752           0 :         struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
     753           0 :         struct PAC_DATA *pac_data = NULL;
     754           0 :         struct PAC_DATA_CTR *pac_data_ctr = NULL;
     755           0 :         const char *local_service;
     756           0 :         uint32_t i;
     757           0 :         struct netr_SamInfo6 *info6_copy = NULL;
     758           0 :         char *canon_principal = NULL;
     759           0 :         char *canon_realm = NULL;
     760           0 :         bool ok;
     761             : 
     762           0 :         *info6 = NULL;
     763             : 
     764           0 :         if (domain->alt_name == NULL) {
     765           0 :                 return NT_STATUS_INVALID_PARAMETER;
     766             :         }
     767             : 
     768           0 :         if (_krb5ccname != NULL) {
     769           0 :                 *_krb5ccname = NULL;
     770             :         }
     771             : 
     772             :         /* 1st step:
     773             :          * prepare a krb5_cc_cache string for the user */
     774             : 
     775           0 :         if (uid == -1) {
     776           0 :                 DEBUG(0,("no valid uid\n"));
     777             :         }
     778             : 
     779           0 :         ok = generate_krb5_ccache(mem_ctx,
     780             :                                   krb5_cc_type,
     781             :                                   uid,
     782             :                                   &user_ccache_file);
     783           0 :         if (!ok) {
     784           0 :                 return NT_STATUS_NO_MEMORY;
     785             :         }
     786           0 :         cc = user_ccache_file;
     787             : 
     788             :         /* 2nd step:
     789             :          * get kerberos properties */
     790             : 
     791             : 
     792             :         /* 3rd step:
     793             :          * do kerberos auth and setup ccache as the user */
     794             : 
     795           0 :         ok = parse_domain_user(mem_ctx,
     796             :                         user,
     797             :                         &name_namespace,
     798             :                         &name_domain,
     799             :                         &name_user);
     800           0 :         if (!ok) {
     801           0 :                 return NT_STATUS_INVALID_PARAMETER;
     802             :         }
     803             : 
     804           0 :         realm = talloc_strdup(mem_ctx, domain->alt_name);
     805           0 :         if (realm == NULL) {
     806           0 :                 return NT_STATUS_NO_MEMORY;
     807             :         }
     808             : 
     809           0 :         if (!strupper_m(realm)) {
     810           0 :                 return NT_STATUS_INVALID_PARAMETER;
     811             :         }
     812             : 
     813           0 :         if (lp_winbind_use_krb5_enterprise_principals() &&
     814           0 :             name_namespace[0] != '\0')
     815             :         {
     816           0 :                 principal_s = talloc_asprintf(mem_ctx,
     817             :                                               "%s@%s@%s",
     818             :                                               name_user,
     819             :                                               name_namespace,
     820             :                                               realm);
     821             :         } else {
     822           0 :                 principal_s = talloc_asprintf(mem_ctx,
     823             :                                               "%s@%s",
     824             :                                               name_user,
     825             :                                               realm);
     826             :         }
     827           0 :         if (principal_s == NULL) {
     828           0 :                 return NT_STATUS_NO_MEMORY;
     829             :         }
     830             : 
     831           0 :         local_service = talloc_asprintf(mem_ctx, "%s$@%s",
     832             :                                         lp_netbios_name(), lp_realm());
     833           0 :         if (local_service == NULL) {
     834           0 :                 return NT_STATUS_NO_MEMORY;
     835             :         }
     836             : 
     837             : 
     838             :         /* if this is a user ccache, we need to act as the user to let the krb5
     839             :          * library handle the chown, etc. */
     840             : 
     841             :         /************************ ENTERING NON-ROOT **********************/
     842             : 
     843           0 :         if (user_ccache_file != NULL) {
     844           0 :                 set_effective_uid(uid);
     845           0 :                 DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid));
     846             :         }
     847             : 
     848             :         /*
     849             :          * Note cc can be NULL, it means
     850             :          * kerberos_return_pac() will use
     851             :          * a temporary krb5 ccache internally.
     852             :          */
     853           0 :         result = kerberos_return_pac(mem_ctx,
     854             :                                      principal_s,
     855             :                                      pass,
     856             :                                      0, /* time_offset */
     857             :                                      &ticket_lifetime,
     858             :                                      &renewal_until,
     859             :                                      cc,
     860             :                                      true,
     861             :                                      true,
     862             :                                      WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
     863             :                                      NULL,
     864             :                                      local_service,
     865             :                                      &canon_principal,
     866             :                                      &canon_realm,
     867             :                                      &pac_data_ctr);
     868           0 :         if (user_ccache_file != NULL) {
     869           0 :                 gain_root_privilege();
     870             :         }
     871             : 
     872             :         /************************ RETURNED TO ROOT **********************/
     873             : 
     874           0 :         if (!NT_STATUS_IS_OK(result)) {
     875           0 :                 goto failed;
     876             :         }
     877             : 
     878           0 :         if (pac_data_ctr == NULL) {
     879           0 :                 goto failed;
     880             :         }
     881             : 
     882           0 :         pac_data = pac_data_ctr->pac_data;
     883           0 :         if (pac_data == NULL) {
     884           0 :                 goto failed;
     885             :         }
     886             : 
     887           0 :         for (i=0; i < pac_data->num_buffers; i++) {
     888             : 
     889           0 :                 if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
     890           0 :                         logon_info = pac_data->buffers[i].info->logon_info.info;
     891           0 :                         continue;
     892             :                 }
     893             : 
     894           0 :                 if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
     895           0 :                         upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
     896           0 :                         continue;
     897             :                 }
     898             :         }
     899             : 
     900           0 :         if (logon_info == NULL) {
     901           0 :                 DEBUG(10,("Missing logon_info in ticket of %s\n",
     902             :                         principal_s));
     903           0 :                 return NT_STATUS_INVALID_PARAMETER;
     904             :         }
     905             : 
     906           0 :         DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n",
     907             :                 principal_s));
     908             : 
     909           0 :         result = create_info6_from_pac(mem_ctx, logon_info,
     910             :                                        upn_dns_info, &info6_copy);
     911           0 :         if (!NT_STATUS_IS_OK(result)) {
     912           0 :                 goto failed;
     913             :         }
     914             : 
     915             :         /* if we had a user's ccache then return that string for the pam
     916             :          * environment */
     917             : 
     918           0 :         if (user_ccache_file != NULL) {
     919             : 
     920           0 :                 if (_krb5ccname != NULL) {
     921           0 :                         *_krb5ccname = talloc_steal(mem_ctx, user_ccache_file);
     922             :                 }
     923             : 
     924           0 :                 result = add_ccache_to_list(principal_s,
     925             :                                             cc,
     926             :                                             user,
     927             :                                             pass,
     928             :                                             realm,
     929             :                                             uid,
     930             :                                             time(NULL),
     931             :                                             ticket_lifetime,
     932             :                                             renewal_until,
     933             :                                             false,
     934             :                                             canon_principal,
     935             :                                             canon_realm);
     936             : 
     937           0 :                 if (!NT_STATUS_IS_OK(result)) {
     938           0 :                         DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n",
     939             :                                 nt_errstr(result)));
     940             :                 }
     941             :         }
     942             : 
     943           0 :         *info6 = info6_copy;
     944           0 :         return NT_STATUS_OK;
     945             : 
     946           0 : failed:
     947             :         /*
     948             :          * Do not delete an existing valid credential cache, if the user
     949             :          * e.g. enters a wrong password
     950             :          */
     951           0 :         if ((strequal(krb5_cc_type, "FILE") || strequal(krb5_cc_type, "WRFILE"))
     952           0 :             && user_ccache_file != NULL) {
     953           0 :                 return result;
     954             :         }
     955             : 
     956             :         /* we could have created a new credential cache with a valid tgt in it
     957             :          * but we weren't able to get or verify the service ticket for this
     958             :          * local host and therefore didn't get the PAC, we need to remove that
     959             :          * cache entirely now */
     960             : 
     961           0 :         if (!NT_STATUS_IS_OK(remove_ccache(user))) {
     962           0 :                 DEBUG(3,("winbindd_raw_kerberos_login: "
     963             :                           "could not remove ccache for user %s\n",
     964             :                         user));
     965             :         }
     966             : 
     967           0 :         return result;
     968             : #else
     969             :         return NT_STATUS_NOT_SUPPORTED;
     970             : #endif /* HAVE_KRB5 */
     971             : }
     972             : 
     973             : /****************************************************************
     974             : ****************************************************************/
     975             : 
     976        3285 : bool check_request_flags(uint32_t flags)
     977             : {
     978        3285 :         uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN |
     979             :                                WBFLAG_PAM_INFO3_TEXT |
     980             :                                WBFLAG_PAM_INFO3_NDR;
     981             : 
     982        3285 :         if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) ||
     983        3285 :              ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) ||
     984        3285 :              ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)||
     985         277 :               !(flags & flags_edata) ) {
     986        3285 :                 return true;
     987             :         }
     988             : 
     989           0 :         DEBUG(1, ("check_request_flags: invalid request flags[0x%08X]\n",
     990             :                   flags));
     991             : 
     992           0 :         return false;
     993             : }
     994             : 
     995             : /****************************************************************
     996             : ****************************************************************/
     997             : 
     998        1651 : NTSTATUS append_auth_data(TALLOC_CTX *mem_ctx,
     999             :                           struct winbindd_response *resp,
    1000             :                           uint32_t request_flags,
    1001             :                           uint16_t validation_level,
    1002             :                           union netr_Validation *validation,
    1003             :                           const char *name_domain,
    1004             :                           const char *name_user)
    1005             : {
    1006        1651 :         struct netr_SamInfo3 *info3 = NULL;
    1007        1651 :         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
    1008             : 
    1009        1651 :         result = map_validation_to_info3(talloc_tos(),
    1010             :                                          validation_level,
    1011             :                                          validation,
    1012             :                                          &info3);
    1013        1651 :         if (!NT_STATUS_IS_OK(result)) {
    1014           0 :                 goto out;
    1015             :         }
    1016             : 
    1017        1651 :         if (request_flags & WBFLAG_PAM_USER_SESSION_KEY) {
    1018         756 :                 memcpy(resp->data.auth.user_session_key,
    1019         756 :                        info3->base.key.key,
    1020             :                        sizeof(resp->data.auth.user_session_key)
    1021             :                        /* 16 */);
    1022             :         }
    1023             : 
    1024        1651 :         if (request_flags & WBFLAG_PAM_LMKEY) {
    1025         696 :                 memcpy(resp->data.auth.first_8_lm_hash,
    1026         696 :                        info3->base.LMSessKey.key,
    1027             :                        sizeof(resp->data.auth.first_8_lm_hash)
    1028             :                        /* 8 */);
    1029             :         }
    1030             : 
    1031        1651 :         if (request_flags & WBFLAG_PAM_UNIX_NAME) {
    1032         192 :                 char *unix_username = NULL;
    1033         192 :                 result = append_unix_username(validation_level,
    1034             :                                               validation,
    1035             :                                               name_domain,
    1036             :                                               name_user,
    1037             :                                               mem_ctx,
    1038             :                                               &unix_username);
    1039         192 :                 if (!NT_STATUS_IS_OK(result)) {
    1040           0 :                         DEBUG(10,("Failed to append Unix Username: %s\n",
    1041             :                                 nt_errstr(result)));
    1042           0 :                         goto out;
    1043             :                 }
    1044         192 :                 fstrcpy(resp->data.auth.unix_username, unix_username);
    1045         192 :                 TALLOC_FREE(unix_username);
    1046             :         }
    1047             : 
    1048             :         /* currently, anything from here on potentially overwrites extra_data. */
    1049             : 
    1050        1651 :         if (request_flags & WBFLAG_PAM_INFO3_NDR) {
    1051           0 :                 result = append_info3_as_ndr(mem_ctx, resp, info3);
    1052           0 :                 if (!NT_STATUS_IS_OK(result)) {
    1053           0 :                         DEBUG(10,("Failed to append INFO3 (NDR): %s\n",
    1054             :                                 nt_errstr(result)));
    1055           0 :                         goto out;
    1056             :                 }
    1057             :         }
    1058             : 
    1059        1651 :         if (request_flags & WBFLAG_PAM_INFO3_TEXT) {
    1060        1436 :                 result = append_info3_as_txt(mem_ctx, resp,
    1061             :                                              validation_level,
    1062             :                                              validation);
    1063        1436 :                 if (!NT_STATUS_IS_OK(result)) {
    1064           0 :                         DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
    1065             :                                 nt_errstr(result)));
    1066           0 :                         goto out;
    1067             :                 }
    1068             :         }
    1069             : 
    1070        1651 :         if (request_flags & WBFLAG_PAM_AFS_TOKEN) {
    1071           0 :                 DATA_BLOB blob = data_blob_null;
    1072           0 :                 result = append_afs_token(validation_level,
    1073             :                                           validation,
    1074             :                                           name_domain,
    1075             :                                           name_user,
    1076             :                                           mem_ctx,
    1077             :                                           &blob);
    1078           0 :                 if (!NT_STATUS_IS_OK(result)) {
    1079           0 :                         DEBUG(10,("Failed to append AFS token: %s\n",
    1080             :                                 nt_errstr(result)));
    1081           0 :                         goto out;
    1082             :                 }
    1083           0 :                 resp->extra_data.data = blob.data;
    1084           0 :                 resp->length += blob.length;
    1085             :         }
    1086             : 
    1087        1651 :         result = NT_STATUS_OK;
    1088        1651 : out:
    1089        1651 :         TALLOC_FREE(info3);
    1090        1651 :         return result;
    1091             : }
    1092             : 
    1093           0 : static NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
    1094             :                                               bool krb5_auth,
    1095             :                                               const char *user,
    1096             :                                               const char *pass,
    1097             :                                               const char *krb5_cc_type,
    1098             :                                               uid_t uid,
    1099             :                                               TALLOC_CTX *mem_ctx,
    1100             :                                               uint16_t *_validation_level,
    1101             :                                               union netr_Validation **_validation,
    1102             :                                               const char **_krb5ccname)
    1103             : {
    1104           0 :         TALLOC_CTX *tmp_ctx = NULL;
    1105           0 :         NTSTATUS result = NT_STATUS_LOGON_FAILURE;
    1106           0 :         uint16_t max_allowed_bad_attempts;
    1107           0 :         char *name_namespace = NULL;
    1108           0 :         char *name_domain = NULL;
    1109           0 :         char *name_user = NULL;
    1110           0 :         struct dom_sid sid;
    1111           0 :         enum lsa_SidType type;
    1112           0 :         uchar new_nt_pass[NT_HASH_LEN];
    1113           0 :         const uint8_t *cached_nt_pass;
    1114           0 :         const uint8_t *cached_salt;
    1115           0 :         struct netr_SamInfo3 *my_info3;
    1116           0 :         time_t kickoff_time, must_change_time;
    1117           0 :         bool password_good = false;
    1118           0 :         bool ok;
    1119             : #ifdef HAVE_KRB5
    1120           0 :         struct winbindd_tdc_domain *tdc_domain = NULL;
    1121             : #endif
    1122             : 
    1123           0 :         if (_validation == NULL) {
    1124           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1125             :         }
    1126           0 :         *_validation = NULL;
    1127             : 
    1128           0 :         if (_krb5ccname != NULL) {
    1129           0 :                 *_krb5ccname = NULL;
    1130             :         }
    1131             : 
    1132           0 :         DEBUG(10,("winbindd_dual_pam_auth_cached\n"));
    1133             : 
    1134           0 :         tmp_ctx = talloc_new(mem_ctx);
    1135           0 :         if (tmp_ctx == NULL) {
    1136           0 :                 return NT_STATUS_NO_MEMORY;
    1137             :         }
    1138             : 
    1139             :         /* Parse domain and username */
    1140             : 
    1141           0 :         ok = parse_domain_user(tmp_ctx,
    1142             :                         user,
    1143             :                         &name_namespace,
    1144             :                         &name_domain,
    1145             :                         &name_user);
    1146           0 :         if (!ok) {
    1147           0 :                 DBG_DEBUG("parse_domain_user failed\n");
    1148           0 :                 result = NT_STATUS_NO_SUCH_USER;
    1149           0 :                 goto out;
    1150             :         }
    1151             : 
    1152           0 :         if (!lookup_cached_name(name_namespace,
    1153             :                                 name_domain,
    1154             :                                 name_user,
    1155             :                                 &sid,
    1156             :                                 &type)) {
    1157           0 :                 DEBUG(10,("winbindd_dual_pam_auth_cached: no such user in the cache\n"));
    1158           0 :                 result = NT_STATUS_NO_SUCH_USER;
    1159           0 :                 goto out;
    1160             :         }
    1161             : 
    1162           0 :         if (type != SID_NAME_USER) {
    1163           0 :                 DEBUG(10,("winbindd_dual_pam_auth_cached: not a user (%s)\n", sid_type_lookup(type)));
    1164           0 :                 result = NT_STATUS_LOGON_FAILURE;
    1165           0 :                 goto out;
    1166             :         }
    1167             : 
    1168           0 :         result = winbindd_get_creds(domain,
    1169             :                                     tmp_ctx,
    1170             :                                     &sid,
    1171             :                                     &my_info3,
    1172             :                                     &cached_nt_pass,
    1173             :                                     &cached_salt);
    1174           0 :         if (!NT_STATUS_IS_OK(result)) {
    1175           0 :                 DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result)));
    1176           0 :                 goto out;
    1177             :         }
    1178             : 
    1179           0 :         E_md4hash(pass, new_nt_pass);
    1180             : 
    1181           0 :         dump_data_pw("new_nt_pass", new_nt_pass, NT_HASH_LEN);
    1182           0 :         dump_data_pw("cached_nt_pass", cached_nt_pass, NT_HASH_LEN);
    1183           0 :         if (cached_salt) {
    1184           0 :                 dump_data_pw("cached_salt", cached_salt, NT_HASH_LEN);
    1185             :         }
    1186             : 
    1187           0 :         if (cached_salt) {
    1188             :                 /* In this case we didn't store the nt_hash itself,
    1189             :                    but the MD5 combination of salt + nt_hash. */
    1190           0 :                 uchar salted_hash[NT_HASH_LEN];
    1191           0 :                 gnutls_hash_hd_t hash_hnd = NULL;
    1192           0 :                 int rc;
    1193             : 
    1194           0 :                 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
    1195           0 :                 if (rc < 0) {
    1196           0 :                         result = gnutls_error_to_ntstatus(
    1197             :                                         rc, NT_STATUS_HASH_NOT_SUPPORTED);
    1198           0 :                         goto out;
    1199             :                 }
    1200             : 
    1201           0 :                 rc = gnutls_hash(hash_hnd, cached_salt, 16);
    1202           0 :                 if (rc < 0) {
    1203           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
    1204           0 :                         result = gnutls_error_to_ntstatus(
    1205             :                                         rc, NT_STATUS_HASH_NOT_SUPPORTED);
    1206           0 :                         goto out;
    1207             :                 }
    1208           0 :                 rc = gnutls_hash(hash_hnd, new_nt_pass, 16);
    1209           0 :                 if (rc < 0) {
    1210           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
    1211           0 :                         result = gnutls_error_to_ntstatus(
    1212             :                                         rc, NT_STATUS_HASH_NOT_SUPPORTED);
    1213           0 :                         goto out;
    1214             :                 }
    1215           0 :                 gnutls_hash_deinit(hash_hnd, salted_hash);
    1216             : 
    1217           0 :                 password_good = mem_equal_const_time(cached_nt_pass, salted_hash,
    1218             :                                                      NT_HASH_LEN);
    1219             :         } else {
    1220             :                 /* Old cached cred - direct store of nt_hash (bad bad bad !). */
    1221           0 :                 password_good = mem_equal_const_time(cached_nt_pass, new_nt_pass,
    1222             :                                                      NT_HASH_LEN);
    1223             :         }
    1224             : 
    1225           0 :         if (password_good) {
    1226             : 
    1227             :                 /* User *DOES* know the password, update logon_time and reset
    1228             :                  * bad_pw_count */
    1229             : 
    1230           0 :                 my_info3->base.user_flags |= NETLOGON_CACHED_ACCOUNT;
    1231             : 
    1232           0 :                 if (my_info3->base.acct_flags & ACB_AUTOLOCK) {
    1233           0 :                         result = NT_STATUS_ACCOUNT_LOCKED_OUT;
    1234           0 :                         goto out;
    1235             :                 }
    1236             : 
    1237           0 :                 if (my_info3->base.acct_flags & ACB_DISABLED) {
    1238           0 :                         result = NT_STATUS_ACCOUNT_DISABLED;
    1239           0 :                         goto out;
    1240             :                 }
    1241             : 
    1242           0 :                 if (my_info3->base.acct_flags & ACB_WSTRUST) {
    1243           0 :                         result = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
    1244           0 :                         goto out;
    1245             :                 }
    1246             : 
    1247           0 :                 if (my_info3->base.acct_flags & ACB_SVRTRUST) {
    1248           0 :                         result = NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
    1249           0 :                         goto out;
    1250             :                 }
    1251             : 
    1252           0 :                 if (my_info3->base.acct_flags & ACB_DOMTRUST) {
    1253           0 :                         result = NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
    1254           0 :                         goto out;
    1255             :                 }
    1256             : 
    1257           0 :                 if (!(my_info3->base.acct_flags & ACB_NORMAL)) {
    1258           0 :                         DEBUG(0,("winbindd_dual_pam_auth_cached: what's wrong with that one?: 0x%08x\n",
    1259             :                                 my_info3->base.acct_flags));
    1260           0 :                         result = NT_STATUS_LOGON_FAILURE;
    1261           0 :                         goto out;
    1262             :                 }
    1263             : 
    1264           0 :                 kickoff_time = nt_time_to_unix(my_info3->base.kickoff_time);
    1265           0 :                 if (kickoff_time != 0 && time(NULL) > kickoff_time) {
    1266           0 :                         result = NT_STATUS_ACCOUNT_EXPIRED;
    1267           0 :                         goto out;
    1268             :                 }
    1269             : 
    1270           0 :                 must_change_time = nt_time_to_unix(my_info3->base.force_password_change);
    1271           0 :                 if (must_change_time != 0 && must_change_time < time(NULL)) {
    1272             :                         /* we allow grace logons when the password has expired */
    1273           0 :                         my_info3->base.user_flags |= NETLOGON_GRACE_LOGON;
    1274             :                         /* return NT_STATUS_PASSWORD_EXPIRED; */
    1275           0 :                         goto success;
    1276             :                 }
    1277             : 
    1278             : #ifdef HAVE_KRB5
    1279           0 :                 if ((krb5_auth) &&
    1280           0 :                     ((tdc_domain = wcache_tdc_fetch_domain(tmp_ctx, name_domain)) != NULL) &&
    1281           0 :                     ((tdc_domain->trust_type & LSA_TRUST_TYPE_UPLEVEL) ||
    1282             :                     /* used to cope with the case winbindd starting without network. */
    1283           0 :                     !strequal(tdc_domain->domain_name, tdc_domain->dns_name))) {
    1284           0 :                         const char *cc = NULL;
    1285           0 :                         char *realm = NULL;
    1286           0 :                         const char *principal_s = NULL;
    1287           0 :                         const char *user_ccache_file;
    1288             : 
    1289           0 :                         if (domain->alt_name == NULL) {
    1290           0 :                                 result = NT_STATUS_INVALID_PARAMETER;
    1291           0 :                                 goto out;
    1292             :                         }
    1293             : 
    1294           0 :                         if (uid == -1) {
    1295           0 :                                 DEBUG(0,("winbindd_dual_pam_auth_cached: invalid uid\n"));
    1296           0 :                                 result = NT_STATUS_INVALID_PARAMETER;
    1297           0 :                                 goto out;
    1298             :                         }
    1299             : 
    1300           0 :                         ok = generate_krb5_ccache(tmp_ctx,
    1301             :                                                   krb5_cc_type,
    1302             :                                                   uid,
    1303             :                                                   &user_ccache_file);
    1304           0 :                         if (!ok) {
    1305           0 :                                 result = NT_STATUS_NO_MEMORY;
    1306           0 :                                 goto out;
    1307             :                         }
    1308           0 :                         cc = user_ccache_file;
    1309             : 
    1310           0 :                         realm = talloc_strdup(tmp_ctx, domain->alt_name);
    1311           0 :                         if (realm == NULL) {
    1312           0 :                                 result = NT_STATUS_NO_MEMORY;
    1313           0 :                                 goto out;
    1314             :                         }
    1315             : 
    1316           0 :                         if (!strupper_m(realm)) {
    1317           0 :                                 result = NT_STATUS_INVALID_PARAMETER;
    1318           0 :                                 goto out;
    1319             :                         }
    1320             : 
    1321           0 :                         principal_s = talloc_asprintf(tmp_ctx, "%s@%s", name_user, realm);
    1322           0 :                         if (principal_s == NULL) {
    1323           0 :                                 result = NT_STATUS_NO_MEMORY;
    1324           0 :                                 goto out;
    1325             :                         }
    1326             : 
    1327           0 :                         if (user_ccache_file != NULL) {
    1328             : 
    1329           0 :                                 if (_krb5ccname != NULL) {
    1330           0 :                                         *_krb5ccname = talloc_move(mem_ctx,
    1331             :                                                         &user_ccache_file);
    1332             :                                 }
    1333             : 
    1334           0 :                                 result = add_ccache_to_list(principal_s,
    1335             :                                                             cc,
    1336             :                                                             user,
    1337             :                                                             pass,
    1338             :                                                             realm,
    1339             :                                                             uid,
    1340             :                                                             time(NULL),
    1341           0 :                                                             time(NULL) + lp_winbind_cache_time(),
    1342           0 :                                                             time(NULL) + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
    1343             :                                                             true,
    1344             :                                                             principal_s,
    1345             :                                                             realm);
    1346             : 
    1347           0 :                                 if (!NT_STATUS_IS_OK(result)) {
    1348           0 :                                         DEBUG(10,("winbindd_dual_pam_auth_cached: failed "
    1349             :                                                 "to add ccache to list: %s\n",
    1350             :                                                 nt_errstr(result)));
    1351             :                                 }
    1352             :                         }
    1353             :                 }
    1354             : #endif /* HAVE_KRB5 */
    1355           0 :  success:
    1356             :                 /* FIXME: we possibly should handle logon hours as well (does xp when
    1357             :                  * offline?) see auth/auth_sam.c:sam_account_ok for details */
    1358             : 
    1359           0 :                 unix_to_nt_time(&my_info3->base.logon_time, time(NULL));
    1360           0 :                 my_info3->base.bad_password_count = 0;
    1361             : 
    1362           0 :                 result = winbindd_update_creds_by_info3(domain,
    1363             :                                                         user,
    1364             :                                                         pass,
    1365             :                                                         my_info3);
    1366           0 :                 if (!NT_STATUS_IS_OK(result)) {
    1367           0 :                         DEBUG(1,("winbindd_dual_pam_auth_cached: failed to update creds: %s\n",
    1368             :                                 nt_errstr(result)));
    1369           0 :                         goto out;
    1370             :                 }
    1371             : 
    1372           0 :                 result = map_info3_to_validation(mem_ctx,
    1373             :                                                  my_info3,
    1374             :                                                  _validation_level,
    1375             :                                                  _validation);
    1376           0 :                 if (!NT_STATUS_IS_OK(result)) {
    1377           0 :                         DBG_ERR("map_info3_to_validation failed: %s\n",
    1378             :                                 nt_errstr(result));
    1379           0 :                         goto out;
    1380             :                 }
    1381             : 
    1382           0 :                 result = NT_STATUS_OK;
    1383           0 :                 goto out;
    1384             :         }
    1385             : 
    1386             :         /* User does *NOT* know the correct password, modify info3 accordingly, but only if online */
    1387           0 :         if (domain->online == false) {
    1388           0 :                 goto failed;
    1389             :         }
    1390             : 
    1391             :         /* failure of this is not critical */
    1392           0 :         result = get_max_bad_attempts_from_lockout_policy(domain, tmp_ctx, &max_allowed_bad_attempts);
    1393           0 :         if (!NT_STATUS_IS_OK(result)) {
    1394           0 :                 DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get max_allowed_bad_attempts. "
    1395             :                           "Won't be able to honour account lockout policies\n"));
    1396             :         }
    1397             : 
    1398             :         /* increase counter */
    1399           0 :         my_info3->base.bad_password_count++;
    1400             : 
    1401           0 :         if (max_allowed_bad_attempts == 0) {
    1402           0 :                 goto failed;
    1403             :         }
    1404             : 
    1405             :         /* lockout user */
    1406           0 :         if (my_info3->base.bad_password_count >= max_allowed_bad_attempts) {
    1407             : 
    1408           0 :                 uint32_t password_properties;
    1409             : 
    1410           0 :                 result = get_pwd_properties(domain, tmp_ctx, &password_properties);
    1411           0 :                 if (!NT_STATUS_IS_OK(result)) {
    1412           0 :                         DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get password properties.\n"));
    1413             :                 }
    1414             : 
    1415           0 :                 if ((my_info3->base.rid != DOMAIN_RID_ADMINISTRATOR) ||
    1416           0 :                     (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) {
    1417           0 :                         my_info3->base.acct_flags |= ACB_AUTOLOCK;
    1418             :                 }
    1419             :         }
    1420             : 
    1421           0 : failed:
    1422           0 :         result = winbindd_update_creds_by_info3(domain, user, NULL, my_info3);
    1423           0 :         if (!NT_STATUS_IS_OK(result)) {
    1424           0 :                 DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n",
    1425             :                         nt_errstr(result)));
    1426             :         }
    1427             : 
    1428           0 :         result = NT_STATUS_LOGON_FAILURE;
    1429             : 
    1430           0 : out:
    1431           0 :         TALLOC_FREE(tmp_ctx);
    1432             : 
    1433           0 :         return result;
    1434             : }
    1435             : 
    1436           0 : static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
    1437             :                                                 const char *user,
    1438             :                                                 const char *pass,
    1439             :                                                 const char *krb5_cc_type,
    1440             :                                                 uid_t uid,
    1441             :                                                 TALLOC_CTX *mem_ctx,
    1442             :                                                 uint16_t *_validation_level,
    1443             :                                                 union netr_Validation **_validation,
    1444             :                                                 const char **_krb5ccname)
    1445             : {
    1446           0 :         struct netr_SamInfo6 *info6 = NULL;
    1447           0 :         struct winbindd_domain *contact_domain;
    1448           0 :         char *name_namespace = NULL;
    1449           0 :         char *name_domain = NULL;
    1450           0 :         char *name_user = NULL;
    1451           0 :         NTSTATUS result;
    1452           0 :         bool ok;
    1453             : 
    1454           0 :         DEBUG(10,("winbindd_dual_pam_auth_kerberos\n"));
    1455             : 
    1456             :         /* Parse domain and username */
    1457             : 
    1458           0 :         ok = parse_domain_user(mem_ctx,
    1459             :                                user,
    1460             :                                &name_namespace,
    1461             :                                &name_domain,
    1462             :                                &name_user);
    1463           0 :         if (!ok) {
    1464           0 :                 result = NT_STATUS_INVALID_PARAMETER;
    1465           0 :                 goto done;
    1466             :         }
    1467             : 
    1468             :         /* what domain should we contact? */
    1469             : 
    1470           0 :         if (lp_winbind_use_krb5_enterprise_principals()) {
    1471           0 :                 contact_domain = find_auth_domain(0, name_namespace);
    1472             :         } else {
    1473           0 :                 contact_domain = find_domain_from_name(name_namespace);
    1474             :         }
    1475           0 :         if (contact_domain == NULL) {
    1476           0 :                 DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
    1477             :                           user, name_domain, name_user, name_namespace));
    1478           0 :                 result = NT_STATUS_NO_SUCH_USER;
    1479           0 :                 goto done;
    1480             :         }
    1481             : 
    1482           0 :         if (contact_domain->initialized &&
    1483           0 :             contact_domain->active_directory) {
    1484           0 :                 goto try_login;
    1485             :         }
    1486             : 
    1487           0 :         if (!contact_domain->initialized) {
    1488           0 :                 init_dc_connection(contact_domain, false);
    1489             :         }
    1490             : 
    1491           0 :         if (!contact_domain->active_directory) {
    1492           0 :                 DEBUG(3,("krb5 auth requested but domain (%s) is not Active Directory\n",
    1493             :                       contact_domain->name));
    1494           0 :                 return NT_STATUS_INVALID_LOGON_TYPE;
    1495             :         }
    1496           0 : try_login:
    1497           0 :         result = winbindd_raw_kerberos_login(
    1498             :                 mem_ctx,
    1499             :                 contact_domain,
    1500             :                 user,
    1501             :                 pass,
    1502             :                 krb5_cc_type,
    1503             :                 uid,
    1504             :                 &info6,
    1505             :                 _krb5ccname);
    1506           0 :         if (!NT_STATUS_IS_OK(result)) {
    1507           0 :                 goto done;
    1508             :         }
    1509             : 
    1510           0 :         result = map_info6_to_validation(mem_ctx,
    1511             :                                          info6,
    1512             :                                          _validation_level,
    1513             :                                          _validation);
    1514           0 :         TALLOC_FREE(info6);
    1515           0 :         if (!NT_STATUS_IS_OK(result)) {
    1516           0 :                 DBG_ERR("map_info6_to_validation failed: %s\n",
    1517             :                         nt_errstr(result));
    1518             :         }
    1519             : 
    1520           0 : done:
    1521           0 :         return result;
    1522             : }
    1523             : 
    1524           0 : static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
    1525             :                                           uint32_t logon_parameters,
    1526             :                                           const char *domain,
    1527             :                                           const char *user,
    1528             :                                           const uint64_t logon_id,
    1529             :                                           const char *client_name,
    1530             :                                           const int client_pid,
    1531             :                                           const DATA_BLOB *challenge,
    1532             :                                           const DATA_BLOB *lm_resp,
    1533             :                                           const DATA_BLOB *nt_resp,
    1534             :                                           const struct tsocket_address *remote,
    1535             :                                           const struct tsocket_address *local,
    1536             :                                           bool interactive,
    1537             :                                           uint8_t *pauthoritative,
    1538             :                                           struct netr_SamInfo3 **pinfo3)
    1539             : {
    1540           0 :         struct auth_context *auth_context;
    1541           0 :         struct auth_serversupplied_info *server_info;
    1542           0 :         struct auth_usersupplied_info *user_info = NULL;
    1543           0 :         struct netr_SamInfo3 *info3;
    1544           0 :         NTSTATUS status;
    1545           0 :         bool ok;
    1546           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1547             : 
    1548             :         /*
    1549             :          * We are authoritative by default
    1550             :          */
    1551           0 :         *pauthoritative = 1;
    1552             : 
    1553           0 :         status = make_user_info(frame, &user_info, user, user, domain, domain,
    1554             :                                 lp_netbios_name(), remote, local,
    1555             :                                 "winbind",
    1556             :                                 lm_resp, nt_resp, NULL, NULL,
    1557             :                                 NULL, AUTH_PASSWORD_RESPONSE);
    1558           0 :         if (!NT_STATUS_IS_OK(status)) {
    1559           0 :                 DEBUG(10, ("make_user_info failed: %s\n", nt_errstr(status)));
    1560           0 :                 TALLOC_FREE(frame);
    1561           0 :                 return status;
    1562             :         }
    1563             : 
    1564           0 :         user_info->logon_parameters = logon_parameters;
    1565           0 :         user_info->logon_id = logon_id;
    1566           0 :         user_info->auth_description = talloc_asprintf(
    1567             :                 frame, "PASSDB, %s, %d", client_name, client_pid);
    1568           0 :         if (user_info->auth_description == NULL) {
    1569           0 :                 TALLOC_FREE(frame);
    1570           0 :                 return NT_STATUS_NO_MEMORY;
    1571             :         }
    1572             : 
    1573             :         /* We don't want to come back to winbindd or to do PAM account checks */
    1574           0 :         user_info->flags |= USER_INFO_INFO3_AND_NO_AUTHZ;
    1575             : 
    1576           0 :         if (interactive) {
    1577           0 :                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
    1578             :         }
    1579             : 
    1580           0 :         status = make_auth3_context_for_winbind(frame, &auth_context);
    1581           0 :         if (!NT_STATUS_IS_OK(status)) {
    1582           0 :                 DBG_ERR("make_auth3_context_for_winbind failed: %s\n",
    1583             :                         nt_errstr(status));
    1584           0 :                 TALLOC_FREE(frame);
    1585           0 :                 return status;
    1586             :         }
    1587             : 
    1588           0 :         ok = auth3_context_set_challenge(auth_context,
    1589           0 :                                          challenge->data, "fixed");
    1590           0 :         if (!ok) {
    1591           0 :                 TALLOC_FREE(frame);
    1592           0 :                 return NT_STATUS_NO_MEMORY;
    1593             :         }
    1594             : 
    1595           0 :         status = auth_check_ntlm_password(mem_ctx,
    1596             :                                           auth_context,
    1597             :                                           user_info,
    1598             :                                           &server_info,
    1599             :                                           pauthoritative);
    1600           0 :         if (!NT_STATUS_IS_OK(status)) {
    1601           0 :                 TALLOC_FREE(frame);
    1602           0 :                 return status;
    1603             :         }
    1604             : 
    1605           0 :         info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
    1606           0 :         if (info3 == NULL) {
    1607           0 :                 TALLOC_FREE(frame);
    1608           0 :                 return NT_STATUS_NO_MEMORY;
    1609             :         }
    1610             : 
    1611           0 :         status = serverinfo_to_SamInfo3(server_info, info3);
    1612           0 :         if (!NT_STATUS_IS_OK(status)) {
    1613           0 :                 TALLOC_FREE(frame);
    1614           0 :                 TALLOC_FREE(info3);
    1615           0 :                 DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
    1616             :                           nt_errstr(status)));
    1617           0 :                 return status;
    1618             :         }
    1619             : 
    1620           0 :         *pinfo3 = info3;
    1621           0 :         DBG_DEBUG("Authenticating user %s\\%s returned %s\n",
    1622             :                   domain,
    1623             :                   user,
    1624             :                   nt_errstr(status));
    1625           0 :         TALLOC_FREE(frame);
    1626           0 :         return status;
    1627             : }
    1628             : 
    1629           0 : static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
    1630             :                                             TALLOC_CTX *mem_ctx,
    1631             :                                             uint32_t logon_parameters,
    1632             :                                             const char *username,
    1633             :                                             const char *password,
    1634             :                                             const char *domainname,
    1635             :                                             const char *workstation,
    1636             :                                             const uint64_t logon_id,
    1637             :                                             bool plaintext_given,
    1638             :                                             DATA_BLOB chal,
    1639             :                                             DATA_BLOB lm_response,
    1640             :                                             DATA_BLOB nt_response,
    1641             :                                             bool interactive,
    1642             :                                             uint8_t *authoritative,
    1643             :                                             uint32_t *flags,
    1644             :                                             uint16_t *_validation_level,
    1645             :                                             union netr_Validation **_validation)
    1646             : {
    1647           0 :         int attempts = 0;
    1648           0 :         int netr_attempts = 0;
    1649           0 :         bool retry = false;
    1650           0 :         bool valid_result = false;
    1651           0 :         NTSTATUS result;
    1652           0 :         enum netr_LogonInfoClass logon_type_i;
    1653           0 :         enum netr_LogonInfoClass logon_type_n;
    1654           0 :         uint16_t validation_level = UINT16_MAX;
    1655           0 :         union netr_Validation *validation = NULL;
    1656           0 :         TALLOC_CTX *base_ctx = NULL;
    1657           0 :         struct netr_SamBaseInfo *base_info = NULL;
    1658             : 
    1659           0 :         do {
    1660           0 :                 struct rpc_pipe_client *netlogon_pipe;
    1661           0 :                 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
    1662             : 
    1663             :                 /*
    1664             :                  * We should always reset authoritative to 1
    1665             :                  * before calling a server again.
    1666             :                  *
    1667             :                  * Otherwise we could treat a local problem as
    1668             :                  * non-authoritative.
    1669             :                  */
    1670           0 :                 *authoritative = 1;
    1671             : 
    1672           0 :                 retry = false;
    1673             : 
    1674           0 :                 D_DEBUG("Creating a DCERPC netlogon connection for SAM logon. "
    1675             :                         "netlogon attempt: %d, samlogon attempt: %d.\n",
    1676             :                         netr_attempts,
    1677             :                         attempts);
    1678           0 :                 result = cm_connect_netlogon_secure(domain, &netlogon_pipe,
    1679             :                                                     &netlogon_creds_ctx);
    1680             : 
    1681           0 :                 if (NT_STATUS_EQUAL(result,
    1682             :                                     NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) {
    1683             :                         /*
    1684             :                          * This means we don't have a trust account.
    1685             :                          */
    1686           0 :                         *authoritative = 0;
    1687           0 :                         result = NT_STATUS_NO_SUCH_USER;
    1688           0 :                         break;
    1689             :                 }
    1690             : 
    1691           0 :                 if (!NT_STATUS_IS_OK(result)) {
    1692           0 :                         DEBUG(3,("Could not open handle to NETLOGON pipe "
    1693             :                                  "(error: %s, attempts: %d)\n",
    1694             :                                   nt_errstr(result), netr_attempts));
    1695             : 
    1696           0 :                         reset_cm_connection_on_error(domain, NULL, result);
    1697             : 
    1698             :                         /* After the first retry always close the connection */
    1699           0 :                         if (netr_attempts > 0) {
    1700           0 :                                 DEBUG(3, ("This is again a problem for this "
    1701             :                                           "particular call, forcing the close "
    1702             :                                           "of this connection\n"));
    1703           0 :                                 invalidate_cm_connection(domain);
    1704             :                         }
    1705             : 
    1706             :                         /* After the second retry failover to the next DC */
    1707           0 :                         if (netr_attempts > 1) {
    1708             :                                 /*
    1709             :                                  * If the netlogon server is not reachable then
    1710             :                                  * it is possible that the DC is rebuilding
    1711             :                                  * sysvol and shutdown netlogon for that time.
    1712             :                                  * We should failover to the next dc.
    1713             :                                  */
    1714           0 :                                 DEBUG(3, ("This is the third problem for this "
    1715             :                                           "particular call, adding DC to the "
    1716             :                                           "negative cache list: %s %s\n", domain->name, domain->dcname));
    1717           0 :                                 add_failed_connection_entry(domain->name,
    1718           0 :                                                             domain->dcname,
    1719             :                                                             result);
    1720           0 :                                 saf_delete(domain->name);
    1721             :                         }
    1722             : 
    1723             :                         /* Only allow 3 retries */
    1724           0 :                         if (netr_attempts < 3) {
    1725           0 :                                 DEBUG(3, ("The connection to netlogon "
    1726             :                                           "failed, retrying\n"));
    1727           0 :                                 netr_attempts++;
    1728           0 :                                 retry = true;
    1729           0 :                                 continue;
    1730             :                         }
    1731           0 :                         return result;
    1732             :                 }
    1733             : 
    1734           0 :                 logon_type_i = NetlogonInteractiveInformation;
    1735           0 :                 logon_type_n = NetlogonNetworkInformation;
    1736           0 :                 if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
    1737           0 :                         logon_type_i = NetlogonInteractiveTransitiveInformation;
    1738           0 :                         logon_type_n = NetlogonNetworkTransitiveInformation;
    1739             :                 }
    1740             : 
    1741           0 :                 if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
    1742           0 :                         logon_type_i = NetlogonInteractiveTransitiveInformation;
    1743           0 :                         logon_type_n = NetlogonNetworkTransitiveInformation;
    1744             :                 }
    1745             : 
    1746           0 :                 if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
    1747           0 :                         logon_type_i = NetlogonInteractiveInformation;
    1748           0 :                         logon_type_n = NetlogonNetworkInformation;
    1749             :                 }
    1750             : 
    1751           0 :                 if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
    1752           0 :                         logon_type_i = NetlogonInteractiveInformation;
    1753           0 :                         logon_type_n = NetlogonNetworkInformation;
    1754             :                 }
    1755             : 
    1756           0 :                 netr_attempts = 0;
    1757           0 :                 if (plaintext_given) {
    1758           0 :                         result = rpccli_netlogon_password_logon(
    1759             :                                 netlogon_creds_ctx,
    1760           0 :                                 netlogon_pipe->binding_handle,
    1761             :                                 mem_ctx,
    1762             :                                 logon_parameters,
    1763             :                                 domainname,
    1764             :                                 username,
    1765             :                                 password,
    1766             :                                 workstation,
    1767             :                                 logon_id,
    1768             :                                 logon_type_i,
    1769             :                                 authoritative,
    1770             :                                 flags,
    1771             :                                 &validation_level,
    1772             :                                 &validation);
    1773           0 :                 } else if (interactive) {
    1774           0 :                         result = rpccli_netlogon_interactive_logon(
    1775             :                                 netlogon_creds_ctx,
    1776           0 :                                 netlogon_pipe->binding_handle,
    1777             :                                 mem_ctx,
    1778             :                                 logon_parameters,
    1779             :                                 username,
    1780             :                                 domainname,
    1781             :                                 workstation,
    1782             :                                 logon_id,
    1783             :                                 lm_response,
    1784             :                                 nt_response,
    1785             :                                 logon_type_i,
    1786             :                                 authoritative,
    1787             :                                 flags,
    1788             :                                 &validation_level,
    1789             :                                 &validation);
    1790             :                 } else {
    1791           0 :                         result = rpccli_netlogon_network_logon(
    1792             :                                 netlogon_creds_ctx,
    1793           0 :                                 netlogon_pipe->binding_handle,
    1794             :                                 mem_ctx,
    1795             :                                 logon_parameters,
    1796             :                                 username,
    1797             :                                 domainname,
    1798             :                                 workstation,
    1799             :                                 logon_id,
    1800             :                                 chal,
    1801             :                                 lm_response,
    1802             :                                 nt_response,
    1803             :                                 logon_type_n,
    1804             :                                 authoritative,
    1805             :                                 flags,
    1806             :                                 &validation_level,
    1807             :                                 &validation);
    1808             :                 }
    1809             : 
    1810             :                 /*
    1811             :                  * we increment this after the "feature negotiation"
    1812             :                  * for can_do_samlogon_ex and can_do_validation6
    1813             :                  */
    1814           0 :                 attempts += 1;
    1815             : 
    1816             :                 /* We have to try a second time as cm_connect_netlogon
    1817             :                    might not yet have noticed that the DC has killed
    1818             :                    our connection. */
    1819             : 
    1820           0 :                 retry = reset_cm_connection_on_error(domain,
    1821           0 :                                                      netlogon_pipe->binding_handle,
    1822             :                                                      result);
    1823           0 :                 if (retry) {
    1824           0 :                         DBG_PREFIX(attempts > 1 ? DBGLVL_NOTICE : DBGLVL_INFO, (
    1825             :                                    "This is problem %d for this "
    1826             :                                    "particular call,"
    1827             :                                    "DOMAIN[%s] DC[%s] - %s\n",
    1828             :                                    attempts,
    1829             :                                    domain->name,
    1830             :                                    domain->dcname,
    1831             :                                    nt_errstr(result)));
    1832           0 :                         continue;
    1833             :                 }
    1834             : 
    1835           0 :                 valid_result = true;
    1836             : 
    1837           0 :                 if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
    1838             :                         /*
    1839             :                          * Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon
    1840             :                          * (no Ex). This happens against old Samba
    1841             :                          * DCs, if LogonSamLogonEx() fails with an error
    1842             :                          * e.g. NT_STATUS_NO_SUCH_USER or NT_STATUS_WRONG_PASSWORD.
    1843             :                          *
    1844             :                          * The server will log something like this:
    1845             :                          * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
    1846             :                          *
    1847             :                          * This sets the whole connection into a fault_state mode
    1848             :                          * and all following request get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
    1849             :                          *
    1850             :                          * This also happens to our retry with LogonSamLogonWithFlags()
    1851             :                          * and LogonSamLogon().
    1852             :                          *
    1853             :                          * In order to recover from this situation, we need to
    1854             :                          * drop the connection.
    1855             :                          */
    1856           0 :                         invalidate_cm_connection(domain);
    1857           0 :                         result = NT_STATUS_LOGON_FAILURE;
    1858           0 :                         break;
    1859             :                 }
    1860             : 
    1861           0 :         } while ( (attempts < 3) && retry );
    1862             : 
    1863           0 :         if (!valid_result) {
    1864             :                 /*
    1865             :                  * This matches what windows does. In a chain of transitive
    1866             :                  * trusts the ACCESS_DENIED/authoritative=0 is not propagated
    1867             :                  * instead of NT_STATUS_NO_LOGON_SERVERS/authoritative=1 is
    1868             :                  * passed along the chain if there's no other DC is available.
    1869             :                  */
    1870           0 :                 DBG_WARNING("Mapping %s/authoritative=%u to "
    1871             :                             "NT_STATUS_NO_LOGON_SERVERS/authoritative=1 for"
    1872             :                             "USERNAME[%s] USERDOMAIN[%s] REMOTE-DOMAIN[%s] \n",
    1873             :                             nt_errstr(result),
    1874             :                             *authoritative,
    1875             :                             username,
    1876             :                             domainname,
    1877             :                             domain->name);
    1878           0 :                 *authoritative = 1;
    1879           0 :                 return NT_STATUS_NO_LOGON_SERVERS;
    1880             :         }
    1881             : 
    1882           0 :         if (!NT_STATUS_IS_OK(result)) {
    1883           0 :                 return result;
    1884             :         }
    1885             : 
    1886           0 :         switch (validation_level) {
    1887           0 :         case 3:
    1888           0 :                 base_ctx = validation->sam3;
    1889           0 :                 base_info = &validation->sam3->base;
    1890           0 :                 break;
    1891           0 :         case 6:
    1892           0 :                 base_ctx = validation->sam6;
    1893           0 :                 base_info = &validation->sam6->base;
    1894           0 :                 break;
    1895           0 :         default:
    1896           0 :                 smb_panic(__location__);
    1897             :         }
    1898             : 
    1899           0 :         if (base_info->acct_flags == 0 || base_info->account_name.string == NULL) {
    1900           0 :                 struct dom_sid user_sid;
    1901           0 :                 struct dom_sid_buf sid_buf;
    1902           0 :                 const char *acct_flags_src = "server";
    1903           0 :                 const char *acct_name_src = "server";
    1904             : 
    1905             :                 /*
    1906             :                  * Handle the case where a NT4 DC does not fill in the acct_flags in
    1907             :                  * the samlogon reply info3. Yes, in 2021, there are still admins
    1908             :                  * around with real NT4 DCs.
    1909             :                  *
    1910             :                  * We used to call dcerpc_samr_QueryUserInfo(level=16) to fetch
    1911             :                  * acct_flags, but as NT4 DCs reject authentication with workstation
    1912             :                  * accounts with NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, even if
    1913             :                  * MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT is specified, we only ever got
    1914             :                  * ACB_NORMAL back (maybe with ACB_PWNOEXP in addition).
    1915             :                  *
    1916             :                  * For network logons NT4 DCs also skip the
    1917             :                  * account_name, so we have to fallback to the
    1918             :                  * one given by the client.
    1919             :                  */
    1920             : 
    1921           0 :                 if (base_info->acct_flags == 0) {
    1922           0 :                         base_info->acct_flags = ACB_NORMAL;
    1923           0 :                         if (base_info->force_password_change == NTTIME_MAX) {
    1924           0 :                                 base_info->acct_flags |= ACB_PWNOEXP;
    1925             :                         }
    1926           0 :                         acct_flags_src = "calculated";
    1927             :                 }
    1928             : 
    1929           0 :                 if (base_info->account_name.string == NULL) {
    1930           0 :                         base_info->account_name.string = talloc_strdup(base_ctx,
    1931             :                                                                        username);
    1932           0 :                         if (base_info->account_name.string == NULL) {
    1933           0 :                                 TALLOC_FREE(validation);
    1934           0 :                                 return NT_STATUS_NO_MEMORY;
    1935             :                         }
    1936           0 :                         acct_name_src = "client";
    1937             :                 }
    1938             : 
    1939           0 :                 sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
    1940             : 
    1941           0 :                 DBG_DEBUG("Fallback to %s_acct_flags[0x%x] %s_acct_name[%s] for %s\n",
    1942             :                           acct_flags_src,
    1943             :                           base_info->acct_flags,
    1944             :                           acct_name_src,
    1945             :                           base_info->account_name.string,
    1946             :                           dom_sid_str_buf(&user_sid, &sid_buf));
    1947             :         }
    1948             : 
    1949           0 :         *_validation_level = validation_level;
    1950           0 :         *_validation = validation;
    1951           0 :         return NT_STATUS_OK;
    1952             : }
    1953             : 
    1954           0 : static NTSTATUS nt_dual_auth_passdb(TALLOC_CTX *mem_ctx,
    1955             :                                     fstring name_user,
    1956             :                                     fstring name_domain,
    1957             :                                     const char *pass,
    1958             :                                     uint64_t logon_id,
    1959             :                                     const char *client_name,
    1960             :                                     const int client_pid,
    1961             :                                     const struct tsocket_address *remote,
    1962             :                                     const struct tsocket_address *local,
    1963             :                                     uint8_t *authoritative,
    1964             :                                     struct netr_SamInfo3 **info3)
    1965             : {
    1966           0 :         unsigned char local_nt_response[24];
    1967           0 :         uchar chal[8];
    1968           0 :         DATA_BLOB chal_blob;
    1969           0 :         DATA_BLOB lm_resp;
    1970           0 :         DATA_BLOB nt_resp;
    1971             : 
    1972             :         /* do password magic */
    1973             : 
    1974           0 :         generate_random_buffer(chal, sizeof(chal));
    1975           0 :         chal_blob = data_blob_const(chal, sizeof(chal));
    1976             : 
    1977           0 :         if (lp_client_ntlmv2_auth()) {
    1978           0 :                 DATA_BLOB server_chal;
    1979           0 :                 DATA_BLOB names_blob;
    1980           0 :                 server_chal = data_blob_const(chal, 8);
    1981             : 
    1982             :                 /* note that the 'workgroup' here is for the local
    1983             :                    machine.  The 'server name' must match the
    1984             :                    'workstation' passed to the actual SamLogon call.
    1985             :                 */
    1986           0 :                 names_blob = NTLMv2_generate_names_blob(mem_ctx,
    1987             :                                                         lp_netbios_name(),
    1988             :                                                         lp_workgroup());
    1989             : 
    1990           0 :                 if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain,
    1991             :                                       pass, &server_chal, &names_blob,
    1992             :                                       &lm_resp, &nt_resp, NULL, NULL)) {
    1993           0 :                         data_blob_free(&names_blob);
    1994           0 :                         DEBUG(0, ("SMBNTLMv2encrypt() failed!\n"));
    1995           0 :                         return NT_STATUS_NO_MEMORY;
    1996             :                 }
    1997           0 :                 data_blob_free(&names_blob);
    1998             :         } else {
    1999           0 :                 int rc;
    2000           0 :                 lm_resp = data_blob_null;
    2001             : 
    2002           0 :                 rc = SMBNTencrypt(pass, chal, local_nt_response);
    2003           0 :                 if (rc != 0) {
    2004           0 :                         DEBUG(0, ("SMBNTencrypt() failed!\n"));
    2005           0 :                         return gnutls_error_to_ntstatus(rc,
    2006             :                                     NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
    2007             :                 }
    2008             : 
    2009           0 :                 nt_resp = data_blob_talloc(mem_ctx, local_nt_response,
    2010             :                                            sizeof(local_nt_response));
    2011             :         }
    2012             : 
    2013           0 :         return winbindd_dual_auth_passdb(talloc_tos(), 0, name_domain,
    2014             :                                          name_user, logon_id, client_name,
    2015             :                                          client_pid, &chal_blob, &lm_resp,
    2016             :                                          &nt_resp, remote, local,
    2017             :                                          true, /* interactive */
    2018             :                                          authoritative, info3);
    2019             : }
    2020             : 
    2021           0 : static NTSTATUS winbindd_dual_pam_auth_samlogon(
    2022             :         TALLOC_CTX *mem_ctx,
    2023             :         struct winbindd_domain *domain,
    2024             :         const char *user,
    2025             :         const char *pass,
    2026             :         uint64_t logon_id,
    2027             :         const char *client_name,
    2028             :         const int client_pid,
    2029             :         uint32_t request_flags,
    2030             :         const struct tsocket_address *remote,
    2031             :         const struct tsocket_address *local,
    2032             :         uint16_t *_validation_level,
    2033             :         union netr_Validation **_validation)
    2034             : {
    2035           0 :         char *name_namespace = NULL;
    2036           0 :         char *name_domain = NULL;
    2037           0 :         char *name_user = NULL;
    2038           0 :         NTSTATUS result;
    2039           0 :         uint8_t authoritative = 1;
    2040           0 :         uint32_t flags = 0;
    2041           0 :         uint16_t validation_level = 0;
    2042           0 :         union netr_Validation *validation = NULL;
    2043           0 :         bool ok;
    2044             : 
    2045           0 :         DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
    2046             : 
    2047             :         /* Parse domain and username */
    2048             : 
    2049           0 :         ok = parse_domain_user(mem_ctx,
    2050             :                         user,
    2051             :                         &name_namespace,
    2052             :                         &name_domain,
    2053             :                         &name_user);
    2054           0 :         if (!ok) {
    2055           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2056             :         }
    2057             : 
    2058             :         /*
    2059             :          * We check against domain->name instead of
    2060             :          * name_domain, as find_auth_domain() ->
    2061             :          * find_domain_from_name_noinit() already decided
    2062             :          * that we are in a child for the correct domain.
    2063             :          *
    2064             :          * name_domain can also be lp_realm()
    2065             :          * we need to check against domain->name.
    2066             :          */
    2067           0 :         if (strequal(domain->name, get_global_sam_name())) {
    2068           0 :                 struct netr_SamInfo3 *info3 = NULL;
    2069             : 
    2070           0 :                 result = nt_dual_auth_passdb(mem_ctx, name_user, name_domain,
    2071             :                                              pass, logon_id, client_name,
    2072             :                                              client_pid, remote, local,
    2073             :                                              &authoritative, &info3);
    2074             : 
    2075             :                 /*
    2076             :                  * We need to try the remote NETLOGON server if this is
    2077             :                  * not authoritative (for example on the RODC).
    2078             :                  */
    2079           0 :                 if (authoritative != 0) {
    2080           0 :                         if (!NT_STATUS_IS_OK(result)) {
    2081           0 :                                 return result;
    2082             :                         }
    2083           0 :                         result = map_info3_to_validation(mem_ctx,
    2084             :                                                          info3,
    2085             :                                                          &validation_level,
    2086             :                                                          &validation);
    2087           0 :                         TALLOC_FREE(info3);
    2088           0 :                         if (!NT_STATUS_IS_OK(result)) {
    2089           0 :                                 return result;
    2090             :                         }
    2091             : 
    2092           0 :                         goto done;
    2093             :                 }
    2094             :         }
    2095             : 
    2096             :         /* check authentication loop */
    2097             : 
    2098           0 :         result = winbind_samlogon_retry_loop(domain,
    2099             :                                              mem_ctx,
    2100             :                                              0,
    2101             :                                              name_user,
    2102             :                                              pass,
    2103             :                                              name_domain,
    2104             :                                              lp_netbios_name(),
    2105             :                                              logon_id,
    2106             :                                              true, /* plaintext_given */
    2107             :                                              data_blob_null,
    2108             :                                              data_blob_null, data_blob_null,
    2109             :                                              true, /* interactive */
    2110             :                                              &authoritative,
    2111             :                                              &flags,
    2112             :                                              &validation_level,
    2113             :                                              &validation);
    2114           0 :         if (!NT_STATUS_IS_OK(result)) {
    2115           0 :                 return result;
    2116             :         }
    2117             : 
    2118           0 : done:
    2119           0 :         *_validation_level = validation_level;
    2120           0 :         *_validation = validation;
    2121             : 
    2122           0 :         return NT_STATUS_OK;
    2123             : }
    2124             : 
    2125             : /*
    2126             :  * @brief generate an authentication message in the logs.
    2127             :  *
    2128             :  */
    2129           0 : static void log_authentication(
    2130             :         TALLOC_CTX *mem_ctx,
    2131             :         const struct winbindd_domain *domain,
    2132             :         const char *client_name,
    2133             :         pid_t client_pid,
    2134             :         uint16_t validation_level,
    2135             :         union netr_Validation *validation,
    2136             :         const struct timeval start_time,
    2137             :         const uint64_t logon_id,
    2138             :         const char *command,
    2139             :         const char *user_name,
    2140             :         const char *domain_name,
    2141             :         const char *workstation,
    2142             :         const DATA_BLOB lm_resp,
    2143             :         const DATA_BLOB nt_resp,
    2144             :         const struct tsocket_address *remote,
    2145             :         const struct tsocket_address *local,
    2146             :         NTSTATUS result)
    2147             : {
    2148           0 :         struct auth_usersupplied_info *ui = NULL;
    2149           0 :         struct dom_sid *sid = NULL;
    2150           0 :         struct loadparm_context *lp_ctx = NULL;
    2151           0 :         struct imessaging_context *msg_ctx = NULL;
    2152           0 :         struct netr_SamBaseInfo *base_info = NULL;
    2153             : 
    2154           0 :         if (validation != NULL) {
    2155           0 :                 switch (validation_level) {
    2156           0 :                 case 3:
    2157           0 :                         base_info = &validation->sam3->base;
    2158           0 :                         break;
    2159           0 :                 case 6:
    2160           0 :                         base_info = &validation->sam6->base;
    2161           0 :                         break;
    2162           0 :                 default:
    2163           0 :                         DBG_WARNING("Unexpected validation level '%d'\n",
    2164             :                                     validation_level);
    2165           0 :                         break;
    2166             :                 }
    2167             :         }
    2168             : 
    2169           0 :         ui = talloc_zero(mem_ctx, struct auth_usersupplied_info);
    2170           0 :         ui->logon_id = logon_id;
    2171           0 :         ui->service_description = "winbind";
    2172           0 :         ui->password.response.nt.length = nt_resp.length;
    2173           0 :         ui->password.response.nt.data = nt_resp.data;
    2174           0 :         ui->password.response.lanman.length = lm_resp.length;
    2175           0 :         ui->password.response.lanman.data = lm_resp.data;
    2176           0 :         if (nt_resp.length == 0 && lm_resp.length == 0) {
    2177           0 :                 ui->password_state = AUTH_PASSWORD_PLAIN;
    2178             :         } else {
    2179           0 :                 ui->password_state = AUTH_PASSWORD_RESPONSE;
    2180             :         }
    2181             :         /*
    2182             :          * In the event of a failure ui->auth_description will be null,
    2183             :          * the logging code handles this correctly so it can be ignored.
    2184             :          */
    2185           0 :         ui->auth_description = talloc_asprintf(
    2186             :                 ui,
    2187             :                 "%s, %s, %d",
    2188             :                 command,
    2189             :                 client_name,
    2190             :                 client_pid);
    2191           0 :         if (ui->auth_description == NULL) {
    2192           0 :                 DBG_ERR("OOM Unable to create auth_description\n");
    2193             :         }
    2194           0 :         ui->client.account_name = user_name;
    2195           0 :         ui->client.domain_name = domain_name;
    2196           0 :         ui->workstation_name = workstation;
    2197           0 :         ui->remote_host = remote;
    2198           0 :         ui->local_host = local;
    2199             : 
    2200           0 :         if (base_info != NULL) {
    2201           0 :                 sid = dom_sid_dup(ui, base_info->domain_sid);
    2202           0 :                 if (sid != NULL) {
    2203           0 :                         sid_append_rid(sid, base_info->rid);
    2204             :                 }
    2205             :         }
    2206             : 
    2207           0 :         if (lp_auth_event_notification()) {
    2208           0 :                 lp_ctx = loadparm_init_s3(ui, loadparm_s3_helpers());
    2209           0 :                 msg_ctx = imessaging_client_init(
    2210             :                     ui, lp_ctx, global_event_context());
    2211             :         }
    2212           0 :         log_authentication_event(
    2213             :             msg_ctx,
    2214             :             lp_ctx,
    2215             :             &start_time,
    2216             :             ui,
    2217             :             result,
    2218             :             base_info != NULL ? base_info->logon_domain.string : "",
    2219             :             base_info != NULL ? base_info->account_name.string : "",
    2220             :             sid,
    2221             :             NULL /* client_audit_info */,
    2222             :             NULL /* server_audit_info */);
    2223           0 :         TALLOC_FREE(ui);
    2224           0 : }
    2225             : 
    2226           0 : NTSTATUS _wbint_PamAuth(struct pipes_struct *p,
    2227             :                         struct wbint_PamAuth *r)
    2228             : {
    2229           0 :         struct winbindd_domain *domain = wb_child_domain();
    2230           0 :         NTSTATUS result = NT_STATUS_LOGON_FAILURE;
    2231           0 :         NTSTATUS krb5_result = NT_STATUS_OK;
    2232           0 :         char *name_namespace = NULL;
    2233           0 :         char *name_domain = NULL;
    2234           0 :         char *name_user = NULL;
    2235           0 :         char *mapped_user = NULL;
    2236           0 :         const char *domain_user = NULL;
    2237           0 :         uint16_t validation_level = UINT16_MAX;
    2238           0 :         union netr_Validation *validation = NULL;
    2239           0 :         struct netr_SamBaseInfo *base_info = NULL;
    2240           0 :         NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
    2241           0 :         bool ok;
    2242           0 :         uint64_t logon_id = 0;
    2243           0 :         const struct timeval start_time = timeval_current();
    2244           0 :         const struct tsocket_address *remote = NULL;
    2245           0 :         const struct tsocket_address *local = NULL;
    2246           0 :         const char *krb5ccname = NULL;
    2247           0 :         uid_t uid;
    2248           0 :         pid_t client_pid;
    2249             : 
    2250           0 :         if (domain == NULL) {
    2251           0 :                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
    2252             :         }
    2253             : 
    2254             :         /* Cut client_pid to 32bit */
    2255           0 :         client_pid = r->in.client_pid;
    2256           0 :         if ((uint64_t)client_pid != r->in.client_pid) {
    2257           0 :                 DBG_DEBUG("pid out of range\n");
    2258           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2259             :         }
    2260             : 
    2261             :         /* Cut uid to 32bit */
    2262           0 :         uid = r->in.info->uid;
    2263           0 :         if ((uint64_t)uid != r->in.info->uid) {
    2264           0 :                 DBG_DEBUG("uid out of range\n");
    2265           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2266             :         }
    2267             : 
    2268             :         /*
    2269             :          * Generate a logon_id for this session.
    2270             :          */
    2271           0 :         logon_id = generate_random_u64();
    2272           0 :         remote = dcesrv_connection_get_remote_address(p->dce_call->conn);
    2273           0 :         local = dcesrv_connection_get_local_address(p->dce_call->conn);
    2274           0 :         DEBUG(3, ("[%"PRIu32"]: dual pam auth %s\n", client_pid,
    2275             :                   r->in.info->username));
    2276             : 
    2277             :         /* Parse domain and username */
    2278             : 
    2279           0 :         name_map_status = normalize_name_unmap(p->mem_ctx,
    2280           0 :                                                r->in.info->username,
    2281             :                                                &mapped_user);
    2282             : 
    2283             :         /* If the name normalization didn't actually do anything,
    2284             :            just use the original name */
    2285             : 
    2286           0 :         if (!NT_STATUS_IS_OK(name_map_status) &&
    2287           0 :             !NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
    2288             :         {
    2289           0 :                 mapped_user = discard_const(r->in.info->username);
    2290             :         }
    2291             : 
    2292           0 :         ok = parse_domain_user(p->mem_ctx,
    2293             :                                mapped_user,
    2294             :                                &name_namespace,
    2295             :                                &name_domain,
    2296             :                                &name_user);
    2297           0 :         if (!ok) {
    2298           0 :                 result = NT_STATUS_INVALID_PARAMETER;
    2299           0 :                 goto done;
    2300             :         }
    2301             : 
    2302           0 :         if (mapped_user != r->in.info->username) {
    2303           0 :                 domain_user = talloc_asprintf(talloc_tos(),
    2304             :                                               "%s%c%s",
    2305             :                                               name_domain,
    2306           0 :                                               *lp_winbind_separator(),
    2307             :                                               name_user);
    2308           0 :                 if (domain_user == NULL) {
    2309           0 :                         result = NT_STATUS_NO_MEMORY;
    2310           0 :                         goto done;
    2311             :                 }
    2312           0 :                 r->in.info->username = domain_user;
    2313             :         }
    2314             : 
    2315           0 :         if (!domain->online) {
    2316           0 :                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
    2317           0 :                 if (domain->startup) {
    2318             :                         /* Logons are very important to users. If we're offline and
    2319             :                            we get a request within the first 30 seconds of startup,
    2320             :                            try very hard to find a DC and go online. */
    2321             : 
    2322           0 :                         DEBUG(10,("winbindd_dual_pam_auth: domain: %s offline and auth "
    2323             :                                 "request in startup mode.\n", domain->name ));
    2324             : 
    2325           0 :                         winbindd_flush_negative_conn_cache(domain);
    2326           0 :                         result = init_dc_connection(domain, false);
    2327             :                 }
    2328             :         }
    2329             : 
    2330           0 :         DEBUG(10,("winbindd_dual_pam_auth: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline"));
    2331             : 
    2332             :         /* Check for Kerberos authentication */
    2333           0 :         if (domain->online && (r->in.flags & WBFLAG_PAM_KRB5)) {
    2334           0 :                 result = winbindd_dual_pam_auth_kerberos(
    2335             :                                 domain,
    2336           0 :                                 r->in.info->username,
    2337           0 :                                 r->in.info->password,
    2338           0 :                                 r->in.info->krb5_cc_type,
    2339             :                                 uid,
    2340             :                                 p->mem_ctx,
    2341             :                                 &validation_level,
    2342             :                                 &validation,
    2343             :                                 &krb5ccname);
    2344             : 
    2345             :                 /* save for later */
    2346           0 :                 krb5_result = result;
    2347             : 
    2348           0 :                 if (NT_STATUS_IS_OK(result)) {
    2349           0 :                         DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
    2350           0 :                         goto process_result;
    2351             :                 }
    2352             : 
    2353           0 :                 DBG_DEBUG("winbindd_dual_pam_auth_kerberos failed: %s\n",
    2354             :                           nt_errstr(result));
    2355             : 
    2356           0 :                 if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
    2357           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
    2358           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
    2359           0 :                         DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n"));
    2360           0 :                         set_domain_offline( domain );
    2361           0 :                         goto cached_logon;
    2362             :                 }
    2363             : 
    2364             :                 /* there are quite some NT_STATUS errors where there is no
    2365             :                  * point in retrying with a samlogon, we explicitly have to take
    2366             :                  * care not to increase the bad logon counter on the DC */
    2367             : 
    2368           0 :                 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_DISABLED) ||
    2369           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_EXPIRED) ||
    2370           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_LOCKED_OUT) ||
    2371           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_INVALID_LOGON_HOURS) ||
    2372           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_INVALID_WORKSTATION) ||
    2373           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE) ||
    2374           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) ||
    2375           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED) ||
    2376           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) ||
    2377           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) {
    2378           0 :                         goto done;
    2379             :                 }
    2380             : 
    2381           0 :                 if (r->in.flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) {
    2382           0 :                         DEBUG(3,("falling back to samlogon\n"));
    2383           0 :                         goto sam_logon;
    2384             :                 } else {
    2385           0 :                         goto cached_logon;
    2386             :                 }
    2387             :         }
    2388             : 
    2389           0 : sam_logon:
    2390             :         /* Check for Samlogon authentication */
    2391           0 :         if (domain->online) {
    2392           0 :                 result = winbindd_dual_pam_auth_samlogon(
    2393             :                         p->mem_ctx,
    2394             :                         domain,
    2395           0 :                         r->in.info->username,
    2396           0 :                         r->in.info->password,
    2397             :                         logon_id,
    2398             :                         r->in.client_name,
    2399             :                         client_pid,
    2400             :                         r->in.flags,
    2401             :                         remote,
    2402             :                         local,
    2403             :                         &validation_level,
    2404             :                         &validation);
    2405             : 
    2406           0 :                 if (NT_STATUS_IS_OK(result)) {
    2407           0 :                         DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n"));
    2408             : 
    2409           0 :                         switch (validation_level) {
    2410           0 :                         case 3:
    2411           0 :                                 base_info = &validation->sam3->base;
    2412           0 :                                 break;
    2413           0 :                         case 6:
    2414           0 :                                 base_info = &validation->sam6->base;
    2415           0 :                                 break;
    2416           0 :                         default:
    2417           0 :                                 DBG_ERR("Bad validation level %d\n",
    2418             :                                         validation_level);
    2419           0 :                                 result = NT_STATUS_INTERNAL_ERROR;
    2420           0 :                                 goto done;
    2421             :                         }
    2422             : 
    2423             :                         /* add the Krb5 err if we have one */
    2424           0 :                         if ( NT_STATUS_EQUAL(krb5_result, NT_STATUS_TIME_DIFFERENCE_AT_DC ) ) {
    2425           0 :                                 base_info->user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW;
    2426             :                         }
    2427             : 
    2428           0 :                         goto process_result;
    2429             :                 }
    2430             : 
    2431           0 :                 DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n",
    2432             :                           nt_errstr(result)));
    2433             : 
    2434           0 :                 if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
    2435           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
    2436           0 :                     NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND))
    2437             :                 {
    2438           0 :                         DEBUG(10,("winbindd_dual_pam_auth_samlogon setting domain to offline\n"));
    2439           0 :                         set_domain_offline( domain );
    2440           0 :                         goto cached_logon;
    2441             :                 }
    2442             : 
    2443           0 :                 if (domain->online) {
    2444             :                         /* We're still online - fail. */
    2445           0 :                         goto done;
    2446             :                 }
    2447             :         }
    2448             : 
    2449           0 : cached_logon:
    2450             :         /* Check for Cached logons */
    2451           0 :         if (!domain->online && (r->in.flags & WBFLAG_PAM_CACHED_LOGIN) &&
    2452           0 :             lp_winbind_offline_logon()) {
    2453           0 :                 result = winbindd_dual_pam_auth_cached(domain,
    2454           0 :                                 (r->in.flags & WBFLAG_PAM_KRB5),
    2455           0 :                                 r->in.info->username,
    2456           0 :                                 r->in.info->password,
    2457           0 :                                 r->in.info->krb5_cc_type,
    2458             :                                 uid,
    2459             :                                 p->mem_ctx,
    2460             :                                 &validation_level,
    2461             :                                 &validation,
    2462             :                                 &krb5ccname);
    2463             : 
    2464           0 :                 if (!NT_STATUS_IS_OK(result)) {
    2465           0 :                         DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result)));
    2466           0 :                         goto done;
    2467             :                 }
    2468           0 :                 DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n"));
    2469             :         }
    2470             : 
    2471           0 : process_result:
    2472             : 
    2473           0 :         if (NT_STATUS_IS_OK(result)) {
    2474           0 :                 struct dom_sid user_sid;
    2475           0 :                 TALLOC_CTX *base_ctx = NULL;
    2476           0 :                 struct netr_SamInfo3 *info3 = NULL;
    2477             : 
    2478           0 :                 switch (validation_level) {
    2479           0 :                 case 3:
    2480           0 :                         base_ctx = validation->sam3;
    2481           0 :                         base_info = &validation->sam3->base;
    2482           0 :                         break;
    2483           0 :                 case 6:
    2484           0 :                         base_ctx = validation->sam6;
    2485           0 :                         base_info = &validation->sam6->base;
    2486           0 :                         break;
    2487           0 :                 default:
    2488           0 :                         DBG_ERR("Bad validation level %d\n", validation_level);
    2489           0 :                         result = NT_STATUS_INTERNAL_ERROR;
    2490           0 :                         goto done;
    2491             :                 }
    2492             : 
    2493           0 :                 sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
    2494             : 
    2495           0 :                 if (base_info->full_name.string == NULL) {
    2496           0 :                         struct netr_SamInfo3 *cached_info3;
    2497             : 
    2498           0 :                         cached_info3 = netsamlogon_cache_get(p->mem_ctx,
    2499             :                                                              &user_sid);
    2500           0 :                         if (cached_info3 != NULL &&
    2501           0 :                             cached_info3->base.full_name.string != NULL) {
    2502           0 :                                 base_info->full_name.string = talloc_strdup(
    2503             :                                         base_ctx,
    2504             :                                         cached_info3->base.full_name.string);
    2505           0 :                                 if (base_info->full_name.string == NULL) {
    2506           0 :                                         result = NT_STATUS_NO_MEMORY;
    2507           0 :                                         goto done;
    2508             :                                 }
    2509             :                         } else {
    2510             : 
    2511             :                                 /* this might fail so we don't check the return code */
    2512           0 :                                 wcache_query_user_fullname(domain,
    2513             :                                                 base_ctx,
    2514             :                                                 &user_sid,
    2515             :                                                 &base_info->full_name.string);
    2516             :                         }
    2517             :                 }
    2518             : 
    2519           0 :                 result = map_validation_to_info3(talloc_tos(),
    2520             :                                                  validation_level,
    2521             :                                                  validation,
    2522             :                                                  &info3);
    2523           0 :                 if (!NT_STATUS_IS_OK(result)) {
    2524           0 :                         goto done;
    2525             :                 }
    2526             : 
    2527           0 :                 wcache_invalidate_samlogon(find_domain_from_name(name_domain),
    2528             :                                            &user_sid);
    2529           0 :                 netsamlogon_cache_store(name_user, info3);
    2530             : 
    2531             :                 /* save name_to_sid info as early as possible (only if
    2532             :                    this is our primary domain so we don't invalidate
    2533             :                    the cache entry by storing the seq_num for the wrong
    2534             :                    domain). */
    2535           0 :                 if ( domain->primary ) {
    2536           0 :                         cache_name2sid(domain, name_domain, name_user,
    2537             :                                        SID_NAME_USER, &user_sid);
    2538             :                 }
    2539             : 
    2540             :                 /* Check if the user is in the right group */
    2541             : 
    2542           0 :                 result = check_info3_in_group(info3,
    2543             :                                               r->in.require_membership_of_sid);
    2544           0 :                 if (!NT_STATUS_IS_OK(result)) {
    2545           0 :                         char *s = NDR_PRINT_STRUCT_STRING(p->mem_ctx,
    2546             :                                         wbint_SidArray,
    2547             :                                         r->in.require_membership_of_sid);
    2548           0 :                         DBG_NOTICE("User %s is not in the required groups:\n",
    2549             :                                    r->in.info->username);
    2550           0 :                         DEBUGADD(DBGLVL_NOTICE, ("%s", s));
    2551           0 :                         DEBUGADD(DBGLVL_NOTICE,
    2552             :                                  ("Plaintext authentication is rejected\n"));
    2553           0 :                         goto done;
    2554             :                 }
    2555             : 
    2556           0 :                 if (!is_allowed_domain(info3->base.logon_domain.string)) {
    2557           0 :                         DBG_NOTICE("Authentication failed for user [%s] "
    2558             :                                    "from firewalled domain [%s]\n",
    2559             :                                    info3->base.account_name.string,
    2560             :                                    info3->base.logon_domain.string);
    2561           0 :                         result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
    2562           0 :                         goto done;
    2563             :                 }
    2564             : 
    2565           0 :                 r->out.validation = talloc_zero(p->mem_ctx,
    2566             :                                                 struct wbint_Validation);
    2567           0 :                 if (r->out.validation == NULL) {
    2568           0 :                         result = NT_STATUS_NO_MEMORY;
    2569           0 :                         goto done;
    2570             :                 }
    2571             : 
    2572           0 :                 r->out.validation->level = validation_level;
    2573           0 :                 r->out.validation->validation = talloc_steal(r->out.validation,
    2574             :                                                              validation);
    2575           0 :                 r->out.validation->krb5ccname = talloc_steal(r->out.validation,
    2576             :                                                              krb5ccname);
    2577           0 :                 if ((r->in.flags & WBFLAG_PAM_CACHED_LOGIN)
    2578           0 :                     && lp_winbind_offline_logon()) {
    2579             : 
    2580           0 :                         result = winbindd_store_creds(domain,
    2581           0 :                                                       r->in.info->username,
    2582           0 :                                                       r->in.info->password,
    2583             :                                                       info3);
    2584             :                 }
    2585             : 
    2586           0 :                 result = NT_STATUS_OK;
    2587             :         }
    2588             : 
    2589           0 : done:
    2590             :         /* give us a more useful (more correct?) error code */
    2591           0 :         if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
    2592           0 :             (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
    2593           0 :                 result = NT_STATUS_NO_LOGON_SERVERS;
    2594             :         }
    2595             : 
    2596           0 :         DBG_PREFIX(NT_STATUS_IS_OK(result) ? 5 : 2,
    2597             :                    ("Plain-text authentication for user %s returned %s"
    2598             :                    " (PAM: %d)\n",
    2599             :                    r->in.info->username,
    2600             :                    nt_errstr(result),
    2601             :                    nt_status_to_pam(result)));
    2602             : 
    2603             :         /*
    2604             :          * Log the winbind pam authentication, the logon_id will tie this to
    2605             :          * any of the logons invoked from this request.
    2606             :          */
    2607             : 
    2608           0 :         log_authentication(
    2609             :             p->mem_ctx,
    2610             :             domain,
    2611             :             r->in.client_name,
    2612             :             client_pid,
    2613             :             validation_level,
    2614             :             validation,
    2615             :             start_time,
    2616             :             logon_id,
    2617             :             "PAM_AUTH",
    2618             :             name_user,
    2619             :             name_domain,
    2620             :             NULL,
    2621             :             data_blob_null,
    2622             :             data_blob_null,
    2623             :             remote,
    2624             :             local,
    2625             :             result);
    2626             : 
    2627           0 :         if (NT_STATUS_IS_OK(result)) {
    2628           0 :                 gpupdate_user_init(r->in.info->username);
    2629             :         }
    2630             : 
    2631           0 :         return result;
    2632             : }
    2633             : 
    2634           0 : NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
    2635             :                                TALLOC_CTX *mem_ctx,
    2636             :                                bool interactive,
    2637             :                                uint32_t logon_parameters,
    2638             :                                const char *name_user,
    2639             :                                const char *name_domain,
    2640             :                                const char *workstation,
    2641             :                                const uint64_t logon_id,
    2642             :                                const char* client_name,
    2643             :                                const int client_pid,
    2644             :                                DATA_BLOB chal_blob,
    2645             :                                DATA_BLOB lm_response,
    2646             :                                DATA_BLOB nt_response,
    2647             :                                const struct tsocket_address *remote,
    2648             :                                const struct tsocket_address *local,
    2649             :                                uint8_t *authoritative,
    2650             :                                bool skip_sam,
    2651             :                                uint32_t *flags,
    2652             :                                uint16_t *_validation_level,
    2653             :                                union netr_Validation **_validation)
    2654             : {
    2655           0 :         uint16_t validation_level = 0;
    2656           0 :         union netr_Validation *validation = NULL;
    2657           0 :         NTSTATUS result;
    2658             : 
    2659             :         /*
    2660             :          * We check against domain->name instead of
    2661             :          * name_domain, as find_auth_domain() ->
    2662             :          * find_domain_from_name_noinit() already decided
    2663             :          * that we are in a child for the correct domain.
    2664             :          *
    2665             :          * name_domain can also be lp_realm()
    2666             :          * we need to check against domain->name.
    2667             :          */
    2668           0 :         if (!skip_sam && strequal(domain->name, get_global_sam_name())) {
    2669           0 :                 struct netr_SamInfo3 *info3 = NULL;
    2670             : 
    2671           0 :                 result = winbindd_dual_auth_passdb(
    2672             :                         talloc_tos(),
    2673             :                         logon_parameters,
    2674             :                         name_domain, name_user,
    2675             :                         logon_id,
    2676             :                         client_name,
    2677             :                         client_pid,
    2678             :                         &chal_blob, &lm_response, &nt_response,
    2679             :                         remote,
    2680             :                         local,
    2681             :                         interactive,
    2682             :                         authoritative,
    2683             :                         &info3);
    2684           0 :                 if (NT_STATUS_IS_OK(result)) {
    2685           0 :                         result = map_info3_to_validation(mem_ctx,
    2686             :                                                          info3,
    2687             :                                                          &validation_level,
    2688             :                                                          &validation);
    2689           0 :                         TALLOC_FREE(info3);
    2690           0 :                         if (!NT_STATUS_IS_OK(result)) {
    2691           0 :                                 goto done;
    2692             :                         }
    2693             :                 }
    2694             : 
    2695             :                 /*
    2696             :                  * We need to try the remote NETLOGON server if this is
    2697             :                  * not authoritative.
    2698             :                  */
    2699           0 :                 if (*authoritative != 0) {
    2700           0 :                         *flags = 0;
    2701           0 :                         goto process_result;
    2702             :                 }
    2703             :         }
    2704             : 
    2705           0 :         result = winbind_samlogon_retry_loop(domain,
    2706             :                                              mem_ctx,
    2707             :                                              logon_parameters,
    2708             :                                              name_user,
    2709             :                                              NULL, /* password */
    2710             :                                              name_domain,
    2711             :                                              /* Bug #3248 - found by Stefan Burkei. */
    2712             :                                              workstation, /* We carefully set this above so use it... */
    2713             :                                              logon_id,
    2714             :                                              false, /* plaintext_given */
    2715             :                                              chal_blob,
    2716             :                                              lm_response,
    2717             :                                              nt_response,
    2718             :                                              interactive,
    2719             :                                              authoritative,
    2720             :                                              flags,
    2721             :                                              &validation_level,
    2722             :                                              &validation);
    2723           0 :         if (!NT_STATUS_IS_OK(result)) {
    2724           0 :                 goto done;
    2725             :         }
    2726             : 
    2727           0 : process_result:
    2728             : 
    2729           0 :         if (NT_STATUS_IS_OK(result)) {
    2730           0 :                 struct dom_sid user_sid;
    2731           0 :                 TALLOC_CTX *base_ctx = NULL;
    2732           0 :                 struct netr_SamBaseInfo *base_info = NULL;
    2733           0 :                 struct netr_SamInfo3 *info3 = NULL;
    2734             : 
    2735           0 :                 switch (validation_level) {
    2736           0 :                 case 3:
    2737           0 :                         base_ctx = validation->sam3;
    2738           0 :                         base_info = &validation->sam3->base;
    2739           0 :                         break;
    2740           0 :                 case 6:
    2741           0 :                         base_ctx = validation->sam6;
    2742           0 :                         base_info = &validation->sam6->base;
    2743           0 :                         break;
    2744           0 :                 default:
    2745           0 :                         result = NT_STATUS_INTERNAL_ERROR;
    2746           0 :                         goto done;
    2747             :                 }
    2748             : 
    2749           0 :                 sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
    2750             : 
    2751           0 :                 if (base_info->full_name.string == NULL) {
    2752           0 :                         struct netr_SamInfo3 *cached_info3;
    2753             : 
    2754           0 :                         cached_info3 = netsamlogon_cache_get(mem_ctx,
    2755             :                                                              &user_sid);
    2756           0 :                         if (cached_info3 != NULL &&
    2757           0 :                             cached_info3->base.full_name.string != NULL)
    2758             :                         {
    2759           0 :                                 base_info->full_name.string = talloc_strdup(
    2760             :                                         base_ctx,
    2761             :                                         cached_info3->base.full_name.string);
    2762             :                         } else {
    2763             : 
    2764             :                                 /* this might fail so we don't check the return code */
    2765           0 :                                 wcache_query_user_fullname(domain,
    2766             :                                                 base_ctx,
    2767             :                                                 &user_sid,
    2768             :                                                 &base_info->full_name.string);
    2769             :                         }
    2770             :                 }
    2771             : 
    2772           0 :                 result = map_validation_to_info3(talloc_tos(),
    2773             :                                                  validation_level,
    2774             :                                                  validation,
    2775             :                                                  &info3);
    2776           0 :                 if (!NT_STATUS_IS_OK(result)) {
    2777           0 :                         goto done;
    2778             :                 }
    2779           0 :                 wcache_invalidate_samlogon(find_domain_from_name(name_domain),
    2780             :                                            &user_sid);
    2781           0 :                 netsamlogon_cache_store(name_user, info3);
    2782           0 :                 TALLOC_FREE(info3);
    2783             :         }
    2784             : 
    2785           0 : done:
    2786             : 
    2787             :         /* give us a more useful (more correct?) error code */
    2788           0 :         if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
    2789           0 :             (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
    2790           0 :                 result = NT_STATUS_NO_LOGON_SERVERS;
    2791             :         }
    2792             : 
    2793           0 :         DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
    2794             :               ("NTLM CRAP authentication for user [%s]\\[%s] returned %s\n",
    2795             :                name_domain,
    2796             :                name_user,
    2797             :                nt_errstr(result)));
    2798             : 
    2799           0 :         if (!NT_STATUS_IS_OK(result)) {
    2800           0 :                 return result;
    2801             :         }
    2802             : 
    2803           0 :         *_validation_level = validation_level;
    2804           0 :         *_validation = validation;
    2805           0 :         return NT_STATUS_OK;
    2806             : }
    2807             : 
    2808           0 : NTSTATUS _wbint_PamAuthCrap(struct pipes_struct *p, struct wbint_PamAuthCrap *r)
    2809             : {
    2810           0 :         struct winbindd_domain *domain = wb_child_domain();
    2811           0 :         NTSTATUS result;
    2812           0 :         uint64_t logon_id = 0;
    2813           0 :         uint8_t authoritative = 1;
    2814           0 :         uint32_t flags = 0;
    2815           0 :         uint16_t validation_level = UINT16_MAX;
    2816           0 :         union netr_Validation *validation = NULL;
    2817           0 :         const struct timeval start_time = timeval_current();
    2818           0 :         const struct tsocket_address *remote = NULL;
    2819           0 :         const struct tsocket_address *local = NULL;
    2820           0 :         struct netr_SamInfo3 *info3 = NULL;
    2821           0 :         pid_t client_pid;
    2822             : 
    2823           0 :         if (domain == NULL) {
    2824           0 :                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
    2825             :         }
    2826             : 
    2827             :         /* Cut client_pid to 32bit */
    2828           0 :         client_pid = r->in.client_pid;
    2829           0 :         if ((uint64_t)client_pid != r->in.client_pid) {
    2830           0 :                 DBG_DEBUG("pid out of range\n");
    2831           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2832             :         }
    2833             : 
    2834           0 :         logon_id = generate_random_u64();
    2835           0 :         remote = dcesrv_connection_get_remote_address(p->dce_call->conn);
    2836           0 :         local = dcesrv_connection_get_local_address(p->dce_call->conn);
    2837             : 
    2838           0 :         DBG_NOTICE("[%"PRIu32"]: pam auth crap domain: %s user: %s\n",
    2839             :                    client_pid, r->in.domain, r->in.user);
    2840             : 
    2841           0 :         result = winbind_dual_SamLogon(domain,
    2842             :                                        p->mem_ctx,
    2843             :                                        false, /* interactive */
    2844             :                                        r->in.logon_parameters,
    2845             :                                        r->in.user,
    2846             :                                        r->in.domain,
    2847             :                                        r->in.workstation,
    2848             :                                        logon_id,
    2849             :                                        r->in.client_name,
    2850             :                                        client_pid,
    2851             :                                        r->in.chal,
    2852             :                                        r->in.lm_resp,
    2853             :                                        r->in.nt_resp,
    2854             :                                        remote,
    2855             :                                        local,
    2856             :                                        &authoritative,
    2857             :                                        false,
    2858             :                                        &flags,
    2859             :                                        &validation_level,
    2860             :                                        &validation);
    2861           0 :         if (!NT_STATUS_IS_OK(result)) {
    2862           0 :                 goto done;
    2863             :         }
    2864             : 
    2865           0 :         result = map_validation_to_info3(p->mem_ctx,
    2866             :                                          validation_level,
    2867             :                                          validation,
    2868             :                                          &info3);
    2869           0 :         if (!NT_STATUS_IS_OK(result)) {
    2870           0 :                 goto done;
    2871             :         }
    2872             : 
    2873             :         /* Check if the user is in the right group */
    2874           0 :         result = check_info3_in_group(info3, r->in.require_membership_of_sid);
    2875           0 :         if (!NT_STATUS_IS_OK(result)) {
    2876           0 :                 char *s = NDR_PRINT_STRUCT_STRING(p->mem_ctx,
    2877             :                                                   wbint_SidArray,
    2878             :                                                   r->in.require_membership_of_sid);
    2879           0 :                 DBG_NOTICE("User %s is not in the required groups:\n",
    2880             :                            r->in.user);
    2881           0 :                 DEBUGADD(DBGLVL_NOTICE, ("%s", s));
    2882           0 :                 DEBUGADD(DBGLVL_NOTICE,
    2883             :                          ("CRAP authentication is rejected\n"));
    2884           0 :                 goto done;
    2885             :         }
    2886             : 
    2887           0 :         if (!is_allowed_domain(info3->base.logon_domain.string)) {
    2888           0 :                 DBG_NOTICE("Authentication failed for user [%s] "
    2889             :                            "from firewalled domain [%s]\n",
    2890             :                            info3->base.account_name.string,
    2891             :                            info3->base.logon_domain.string);
    2892           0 :                 result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
    2893           0 :                 goto done;
    2894             :         }
    2895             : 
    2896           0 :         r->out.validation = talloc_zero(p->mem_ctx,
    2897             :                                         struct wbint_PamAuthCrapValidation);
    2898           0 :         if (r->out.validation == NULL) {
    2899           0 :                 result = NT_STATUS_NO_MEMORY;
    2900           0 :                 goto done;
    2901             :         }
    2902             : 
    2903           0 :         r->out.validation->level = validation_level;
    2904           0 :         r->out.validation->validation = talloc_move(r->out.validation,
    2905             :                                                     &validation);
    2906           0 : done:
    2907             : 
    2908           0 :         if (r->in.flags & WBFLAG_PAM_NT_STATUS_SQUASH) {
    2909           0 :                 result = nt_status_squash(result);
    2910             :         }
    2911             : 
    2912           0 :         *r->out.authoritative = authoritative;
    2913             : 
    2914             :         /*
    2915             :          * Log the winbind pam authentication, the logon_id will tie this to
    2916             :          * any of the logons invoked from this request.
    2917             :          */
    2918           0 :         log_authentication(
    2919             :             p->mem_ctx,
    2920             :             domain,
    2921             :             r->in.client_name,
    2922             :             client_pid,
    2923           0 :             r->out.validation->level,
    2924           0 :             r->out.validation->validation,
    2925             :             start_time,
    2926             :             logon_id,
    2927             :             "NTLM_AUTH",
    2928             :             r->in.user,
    2929             :             r->in.domain,
    2930             :             r->in.workstation,
    2931             :             r->in.lm_resp,
    2932             :             r->in.nt_resp,
    2933             :             remote,
    2934             :             local,
    2935             :             result);
    2936             : 
    2937           0 :         return result;
    2938             : }
    2939             : 
    2940           0 : NTSTATUS _wbint_PamAuthChangePassword(struct pipes_struct *p,
    2941             :                                       struct wbint_PamAuthChangePassword *r)
    2942             : {
    2943           0 :         struct winbindd_domain *contact_domain = wb_child_domain();
    2944           0 :         struct policy_handle dom_pol;
    2945           0 :         struct rpc_pipe_client *cli = NULL;
    2946           0 :         bool got_info = false;
    2947           0 :         struct samr_DomInfo1 *info = NULL;
    2948           0 :         struct userPwdChangeFailureInformation *reject = NULL;
    2949           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    2950           0 :         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
    2951           0 :         char *namespace = NULL;
    2952           0 :         char *domain = NULL;
    2953           0 :         char *user = NULL;
    2954           0 :         struct dcerpc_binding_handle *b = NULL;
    2955           0 :         bool ok;
    2956           0 :         pid_t client_pid;
    2957             : 
    2958           0 :         ZERO_STRUCT(dom_pol);
    2959             : 
    2960           0 :         if (contact_domain == NULL) {
    2961           0 :                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
    2962             :         }
    2963             : 
    2964             :         /* Cut client_pid to 32bit */
    2965           0 :         client_pid = r->in.client_pid;
    2966           0 :         if ((uint64_t)client_pid != r->in.client_pid) {
    2967           0 :                 DBG_DEBUG("pid out of range\n");
    2968           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2969             :         }
    2970             : 
    2971           0 :         DBG_NOTICE("[%"PRIu32"]: dual pam chauthtok %s\n",
    2972             :                    client_pid, r->in.user);
    2973             : 
    2974           0 :         ok = parse_domain_user(p->mem_ctx,
    2975             :                                r->in.user,
    2976             :                                &namespace,
    2977             :                                &domain,
    2978             :                                &user);
    2979           0 :         if (!ok) {
    2980           0 :                 goto done;
    2981             :         }
    2982             : 
    2983           0 :         if (!is_allowed_domain(domain)) {
    2984           0 :                 DBG_NOTICE("Authentication failed for user [%s] "
    2985             :                            "from firewalled domain [%s]\n",
    2986             :                            user, domain);
    2987           0 :                 result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
    2988           0 :                 goto done;
    2989             :         }
    2990             : 
    2991             :         /* Initialize reject reason */
    2992           0 :         *r->out.reject_reason = Undefined;
    2993             : 
    2994             :         /* Get sam handle */
    2995             : 
    2996           0 :         result = cm_connect_sam(contact_domain,
    2997             :                                 p->mem_ctx,
    2998             :                                 true,
    2999             :                                 &cli,
    3000             :                                 &dom_pol);
    3001           0 :         if (!NT_STATUS_IS_OK(result)) {
    3002           0 :                 DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
    3003           0 :                 goto done;
    3004             :         }
    3005             : 
    3006           0 :         b = cli->binding_handle;
    3007             : 
    3008           0 :         status = dcerpc_samr_chgpasswd_user4(cli->binding_handle,
    3009             :                                              p->mem_ctx,
    3010           0 :                                              cli->srv_name_slash,
    3011             :                                              user,
    3012             :                                              r->in.old_password,
    3013             :                                              r->in.new_password,
    3014             :                                              &result);
    3015           0 :         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
    3016             :                 /* Password successfully changed. */
    3017           0 :                 goto done;
    3018             :         }
    3019           0 :         if (!NT_STATUS_IS_OK(status)) {
    3020           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) ||
    3021           0 :                     NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
    3022           0 :                     NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
    3023             :                         /* DO NOT FALLBACK TO RC4 */
    3024           0 :                         if (lp_weak_crypto() == SAMBA_WEAK_CRYPTO_DISALLOWED) {
    3025           0 :                                 result = NT_STATUS_STRONG_CRYPTO_NOT_SUPPORTED;
    3026           0 :                                 goto process_result;
    3027             :                         }
    3028             :                 }
    3029             :         } else {
    3030             :                 /* Password change was unsuccessful. */
    3031           0 :                 if (!NT_STATUS_IS_OK(result)) {
    3032           0 :                         goto done;
    3033             :                 }
    3034             :         }
    3035             : 
    3036           0 :         result = rpccli_samr_chgpasswd_user3(cli,
    3037             :                                              p->mem_ctx,
    3038             :                                              user,
    3039             :                                              r->in.new_password,
    3040             :                                              r->in.old_password,
    3041             :                                              &info,
    3042             :                                              &reject);
    3043             : 
    3044             :         /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */
    3045             : 
    3046           0 :         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) {
    3047             : 
    3048           0 :                 *r->out.dominfo = talloc_steal(p->mem_ctx, info);
    3049           0 :                 *r->out.reject_reason = reject->extendedFailureReason;
    3050             : 
    3051           0 :                 got_info = true;
    3052             :         }
    3053             : 
    3054             :         /* atm the pidl generated rpccli_samr_ChangePasswordUser3 function will
    3055             :          * return with NT_STATUS_BUFFER_TOO_SMALL for w2k dcs as w2k just
    3056             :          * returns with 4byte error code (NT_STATUS_NOT_SUPPORTED) which is too
    3057             :          * short to comply with the samr_ChangePasswordUser3 idl - gd */
    3058             : 
    3059             :         /* only fallback when the chgpasswd_user3 call is not supported */
    3060           0 :         if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) ||
    3061           0 :             NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ||
    3062           0 :             NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL) ||
    3063           0 :             NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
    3064             : 
    3065           0 :                 DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n",
    3066             :                         nt_errstr(result)));
    3067             : 
    3068           0 :                 result = rpccli_samr_chgpasswd_user2(cli,
    3069             :                                                      p->mem_ctx,
    3070             :                                                      user,
    3071             :                                                      r->in.new_password,
    3072             :                                                      r->in.old_password);
    3073             : 
    3074             :                 /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION.
    3075             :                    Map to the same status code as Windows 2003. */
    3076             : 
    3077           0 :                 if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) {
    3078           0 :                         result = NT_STATUS_PASSWORD_RESTRICTION;
    3079             :                 }
    3080             :         }
    3081             : 
    3082           0 : done:
    3083             : 
    3084           0 :         if (NT_STATUS_IS_OK(result)
    3085           0 :             && (r->in.flags & WBFLAG_PAM_CACHED_LOGIN)
    3086           0 :             && lp_winbind_offline_logon()) {
    3087           0 :                 result = winbindd_update_creds_by_name(contact_domain, user,
    3088             :                                                        r->in.new_password);
    3089             :                 /* Again, this happens when we login from gdm or xdm
    3090             :                  * and the password expires, *BUT* cached credentials
    3091             :                  * don't exist. winbindd_update_creds_by_name()
    3092             :                  * returns NT_STATUS_NO_SUCH_USER.
    3093             :                  * This is not a failure.
    3094             :                  * --- BoYang
    3095             :                  * */
    3096           0 :                 if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {
    3097           0 :                         result = NT_STATUS_OK;
    3098             :                 }
    3099             : 
    3100           0 :                 if (!NT_STATUS_IS_OK(result)) {
    3101           0 :                         DEBUG(10, ("Failed to store creds: %s\n",
    3102             :                                    nt_errstr(result)));
    3103           0 :                         goto process_result;
    3104             :                 }
    3105             :         }
    3106             : 
    3107           0 :         if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) {
    3108             : 
    3109           0 :                 NTSTATUS policy_ret;
    3110             : 
    3111           0 :                 policy_ret = get_password_policy(contact_domain,
    3112             :                                                  p->mem_ctx,
    3113             :                                                  &info);
    3114             : 
    3115             :                 /* failure of this is non critical, it will just provide no
    3116             :                  * additional information to the client why the change has
    3117             :                  * failed - Guenther */
    3118             : 
    3119           0 :                 if (!NT_STATUS_IS_OK(policy_ret)) {
    3120           0 :                         DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(policy_ret)));
    3121           0 :                         goto process_result;
    3122             :                 }
    3123             : 
    3124           0 :                 *r->out.dominfo = talloc_steal(p->mem_ctx, info);
    3125             :         }
    3126             : 
    3127           0 : process_result:
    3128             : 
    3129           0 :         if (strequal(contact_domain->name, get_global_sam_name())) {
    3130             :                 /* FIXME: internal rpc pipe does not cache handles yet */
    3131           0 :                 if (b) {
    3132           0 :                         if (is_valid_policy_hnd(&dom_pol)) {
    3133           0 :                                 NTSTATUS _result;
    3134           0 :                                 dcerpc_samr_Close(b,
    3135             :                                                   p->mem_ctx,
    3136             :                                                   &dom_pol,
    3137             :                                                   &_result);
    3138             :                         }
    3139           0 :                         TALLOC_FREE(cli);
    3140             :                 }
    3141             :         }
    3142             : 
    3143           0 :         DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
    3144             :               ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
    3145             :                domain,
    3146             :                user,
    3147             :                nt_errstr(result),
    3148             :                nt_status_to_pam(result)));
    3149             : 
    3150           0 :         return result;
    3151             : }
    3152             : 
    3153           0 : NTSTATUS _wbint_PamLogOff(struct pipes_struct *p, struct wbint_PamLogOff *r)
    3154             : {
    3155           0 :         struct winbindd_domain *domain = wb_child_domain();
    3156           0 :         NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
    3157           0 :         pid_t client_pid;
    3158           0 :         uid_t user_uid;
    3159             : 
    3160           0 :         if (domain == NULL) {
    3161           0 :                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
    3162             :         }
    3163             : 
    3164             :         /* Cut client_pid to 32bit */
    3165           0 :         client_pid = r->in.client_pid;
    3166           0 :         if ((uint64_t)client_pid != r->in.client_pid) {
    3167           0 :                 DBG_DEBUG("pid out of range\n");
    3168           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3169             :         }
    3170             : 
    3171             :         /* Cut uid to 32bit */
    3172           0 :         user_uid = r->in.uid;
    3173           0 :         if ((uint64_t)user_uid != r->in.uid) {
    3174           0 :                 DBG_DEBUG("uid out of range\n");
    3175           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3176             :         }
    3177             : 
    3178           0 :         DBG_NOTICE("[%"PRIu32"]: pam dual logoff %s\n", client_pid, r->in.user);
    3179             : 
    3180           0 :         if (!(r->in.flags & WBFLAG_PAM_KRB5)) {
    3181           0 :                 result = NT_STATUS_OK;
    3182           0 :                 goto process_result;
    3183             :         }
    3184             : 
    3185           0 :         if ((r->in.krb5ccname == NULL) || (strlen(r->in.krb5ccname) == 0)) {
    3186           0 :                 result = NT_STATUS_OK;
    3187           0 :                 goto process_result;
    3188             :         }
    3189             : 
    3190             : #ifdef HAVE_KRB5
    3191             : 
    3192           0 :         if (user_uid == (uid_t)-1) {
    3193           0 :                 DBG_DEBUG("Invalid uid for user '%s'\n", r->in.user);
    3194           0 :                 goto process_result;
    3195             :         }
    3196             : 
    3197             :         /* what we need here is to find the corresponding krb5 ccache name *we*
    3198             :          * created for a given username and destroy it */
    3199             : 
    3200           0 :         if (!ccache_entry_exists(r->in.user)) {
    3201           0 :                 result = NT_STATUS_OK;
    3202           0 :                 DBG_DEBUG("No entry found for user '%s'.\n", r->in.user);
    3203           0 :                 goto process_result;
    3204             :         }
    3205             : 
    3206           0 :         if (!ccache_entry_identical(r->in.user, user_uid, r->in.krb5ccname)) {
    3207           0 :                 DBG_DEBUG("Cached entry differs for user '%s'\n", r->in.user);
    3208           0 :                 goto process_result;
    3209             :         }
    3210             : 
    3211           0 :         result = remove_ccache(r->in.user);
    3212           0 :         if (!NT_STATUS_IS_OK(result)) {
    3213           0 :                 DBG_DEBUG("Failed to remove ccache for user '%s': %s\n",
    3214             :                           r->in.user, nt_errstr(result));
    3215           0 :                 goto process_result;
    3216             :         }
    3217             : 
    3218             :         /*
    3219             :          * Remove any mlock'ed memory creds in the child
    3220             :          * we might be using for krb5 ticket renewal.
    3221             :          */
    3222             : 
    3223           0 :         winbindd_delete_memory_creds(r->in.user);
    3224             : 
    3225             : #else
    3226             :         result = NT_STATUS_NOT_SUPPORTED;
    3227             : #endif
    3228             : 
    3229           0 : process_result:
    3230             : 
    3231           0 :         return result;
    3232             : }
    3233             : 
    3234             : /* Change user password with auth crap*/
    3235             : 
    3236           0 : NTSTATUS _wbint_PamAuthCrapChangePassword(struct pipes_struct *p,
    3237             :                                 struct wbint_PamAuthCrapChangePassword *r)
    3238             : {
    3239           0 :         NTSTATUS result;
    3240           0 :         char *namespace = NULL;
    3241           0 :         char *domain = NULL;
    3242           0 :         char *user = NULL;
    3243           0 :         struct policy_handle dom_pol;
    3244           0 :         struct winbindd_domain *contact_domain = wb_child_domain();
    3245           0 :         struct rpc_pipe_client *cli = NULL;
    3246           0 :         struct dcerpc_binding_handle *b = NULL;
    3247           0 :         TALLOC_CTX *frame = talloc_stackframe();
    3248           0 :         pid_t client_pid;
    3249             : 
    3250           0 :         ZERO_STRUCT(dom_pol);
    3251             : 
    3252           0 :         if (contact_domain == NULL) {
    3253           0 :                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
    3254             :         }
    3255             : 
    3256             :         /* Cut client_pid to 32bit */
    3257           0 :         client_pid = r->in.client_pid;
    3258           0 :         if ((uint64_t)client_pid != r->in.client_pid) {
    3259           0 :                 DBG_DEBUG("pid out of range\n");
    3260           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3261             :         }
    3262             : 
    3263           0 :         DBG_NOTICE("[%"PRIu32"]: pam change pswd auth crap domain: %s "
    3264             :                    "user: %s\n", client_pid, r->in.domain, r->in.user);
    3265             : 
    3266           0 :         if (lp_winbind_offline_logon()) {
    3267           0 :                 DEBUG(0,("Refusing password change as winbind offline logons are enabled. "));
    3268           0 :                 DEBUGADD(0,("Changing passwords here would risk inconsistent logons\n"));
    3269           0 :                 result = NT_STATUS_ACCESS_DENIED;
    3270           0 :                 goto done;
    3271             :         }
    3272             : 
    3273           0 :         if (r->in.domain != NULL && strlen(r->in.domain) > 0) {
    3274           0 :                 user = talloc_strdup(frame, "");
    3275           0 :                 namespace = talloc_strdup(frame, "");
    3276           0 :                 domain = talloc_strdup(frame, r->in.domain);
    3277           0 :                 if (domain == NULL || user == NULL || namespace == NULL) {
    3278           0 :                         result = NT_STATUS_NO_MEMORY;
    3279           0 :                         goto done;
    3280             :                 }
    3281             : 
    3282             :         } else {
    3283           0 :                 bool ok;
    3284             : 
    3285           0 :                 ok = parse_domain_user(frame,
    3286             :                                        r->in.user,
    3287             :                                        &namespace,
    3288             :                                        &domain,
    3289             :                                        &user);
    3290           0 :                 if (!ok) {
    3291           0 :                         result = NT_STATUS_INVALID_PARAMETER;
    3292           0 :                         goto done;
    3293             :                 }
    3294             : 
    3295           0 :                 if (strlen(domain) == 0) {
    3296           0 :                         DBG_NOTICE("no domain specified with username (%s) - "
    3297             :                                    "failing auth\n", r->in.user);
    3298           0 :                         result = NT_STATUS_NO_SUCH_USER;
    3299           0 :                         goto done;
    3300             :                 }
    3301             :         }
    3302             : 
    3303           0 :         if (!*domain && lp_winbind_use_default_domain()) {
    3304           0 :                 TALLOC_FREE(domain);
    3305           0 :                 domain = talloc_strdup(frame, lp_workgroup());
    3306           0 :                 if (domain == NULL) {
    3307           0 :                         result = NT_STATUS_NO_MEMORY;
    3308           0 :                         goto done;
    3309             :                 }
    3310             :         }
    3311             : 
    3312           0 :         if (!is_allowed_domain(domain)) {
    3313           0 :                 DBG_NOTICE("Authentication failed for user [%s] "
    3314             :                            "from firewalled domain [%s]\n",
    3315             :                            r->in.user,
    3316             :                            domain);
    3317           0 :                 result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
    3318           0 :                 goto done;
    3319             :         }
    3320             : 
    3321           0 :         if(!*user) {
    3322           0 :                 TALLOC_FREE(user);
    3323           0 :                 user = talloc_strdup(frame, r->in.user);
    3324           0 :                 if (user == NULL) {
    3325           0 :                         result = NT_STATUS_NO_SUCH_USER;
    3326           0 :                         goto done;
    3327             :                 }
    3328             :         }
    3329             : 
    3330             :         /* Get sam handle */
    3331             : 
    3332           0 :         result = cm_connect_sam(contact_domain,
    3333             :                                 p->mem_ctx,
    3334             :                                 true,
    3335             :                                 &cli,
    3336             :                                 &dom_pol);
    3337           0 :         if (!NT_STATUS_IS_OK(result)) {
    3338           0 :                 DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
    3339           0 :                 goto done;
    3340             :         }
    3341             : 
    3342           0 :         b = cli->binding_handle;
    3343             : 
    3344           0 :         result = rpccli_samr_chng_pswd_auth_crap(cli,
    3345             :                                                  p->mem_ctx,
    3346             :                                                  user,
    3347             :                                                  r->in.new_nt_pswd,
    3348             :                                                  r->in.old_nt_hash_enc,
    3349             :                                                  r->in.new_lm_pswd,
    3350             :                                                  r->in.old_lm_hash_enc);
    3351             : 
    3352           0 :  done:
    3353             : 
    3354           0 :         if (strequal(contact_domain->name, get_global_sam_name())) {
    3355             :                 /* FIXME: internal rpc pipe does not cache handles yet */
    3356           0 :                 if (b) {
    3357           0 :                         if (is_valid_policy_hnd(&dom_pol)) {
    3358           0 :                                 NTSTATUS _result;
    3359           0 :                                 dcerpc_samr_Close(b,
    3360             :                                                   p->mem_ctx,
    3361             :                                                   &dom_pol,
    3362             :                                                   &_result);
    3363             :                         }
    3364           0 :                         TALLOC_FREE(cli);
    3365             :                 }
    3366             :         }
    3367             : 
    3368           0 :         DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
    3369             :               ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
    3370             :                domain, user,
    3371             :                nt_errstr(result),
    3372             :                nt_status_to_pam(result)));
    3373           0 :         TALLOC_FREE(frame);
    3374           0 :         return result;
    3375             : }
    3376             : 
    3377             : #ifdef HAVE_KRB5
    3378         884 : static NTSTATUS extract_pac_vrfy_sigs(TALLOC_CTX *mem_ctx, DATA_BLOB pac_blob,
    3379             :                                       struct PAC_DATA **p_pac_data)
    3380             : {
    3381         884 :         krb5_context krbctx = NULL;
    3382           0 :         krb5_error_code k5ret;
    3383           0 :         krb5_keytab keytab;
    3384           0 :         krb5_kt_cursor cursor;
    3385           0 :         krb5_keytab_entry entry;
    3386         884 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    3387             : 
    3388         884 :         ZERO_STRUCT(entry);
    3389         884 :         ZERO_STRUCT(cursor);
    3390             : 
    3391         884 :         k5ret = smb_krb5_init_context_common(&krbctx);
    3392         884 :         if (k5ret) {
    3393           0 :                 DBG_ERR("kerberos init context failed (%s)\n",
    3394             :                         error_message(k5ret));
    3395           0 :                 status = krb5_to_nt_status(k5ret);
    3396           0 :                 goto out;
    3397             :         }
    3398             : 
    3399         884 :         k5ret =  gse_krb5_get_server_keytab(krbctx, &keytab);
    3400         884 :         if (k5ret) {
    3401           0 :                 DEBUG(1, ("Failed to get keytab: %s\n",
    3402             :                           error_message(k5ret)));
    3403           0 :                 status = krb5_to_nt_status(k5ret);
    3404           0 :                 goto out_free;
    3405             :         }
    3406             : 
    3407         884 :         k5ret = krb5_kt_start_seq_get(krbctx, keytab, &cursor);
    3408         884 :         if (k5ret) {
    3409           0 :                 DEBUG(1, ("Failed to start seq: %s\n",
    3410             :                           error_message(k5ret)));
    3411           0 :                 status = krb5_to_nt_status(k5ret);
    3412           0 :                 goto out_keytab;
    3413             :         }
    3414             : 
    3415         884 :         k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor);
    3416        3560 :         while (k5ret == 0) {
    3417        3560 :                 status = kerberos_decode_pac(mem_ctx,
    3418             :                                              pac_blob,
    3419             :                                              krbctx,
    3420             :                                              NULL, /* krbtgt_keyblock */
    3421             :                                              KRB5_KT_KEY(&entry), /* service_keyblock */
    3422             :                                              NULL, /* client_principal */
    3423             :                                              0, /* tgs_authtime */
    3424             :                                              p_pac_data);
    3425        3560 :                 (void)smb_krb5_kt_free_entry(krbctx, &entry);
    3426        3560 :                 if (NT_STATUS_IS_OK(status)) {
    3427         884 :                         break;
    3428             :                 }
    3429        2676 :                 k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor);
    3430             :         }
    3431         884 :         if (k5ret != 0 && k5ret != KRB5_KT_END) {
    3432           0 :                 DEBUG(1, ("Failed to get next entry: %s\n",
    3433             :                           error_message(k5ret)));
    3434           0 :                 (void)smb_krb5_kt_free_entry(krbctx, &entry);
    3435             :         }
    3436             : 
    3437         884 :         k5ret = krb5_kt_end_seq_get(krbctx, keytab, &cursor);
    3438         884 :         if (k5ret) {
    3439           0 :                 DEBUG(1, ("Failed to end seq: %s\n",
    3440             :                           error_message(k5ret)));
    3441             :         }
    3442         884 : out_keytab:
    3443         884 :         k5ret = krb5_kt_close(krbctx, keytab);
    3444         884 :         if (k5ret) {
    3445           0 :                 DEBUG(1, ("Failed to close keytab: %s\n",
    3446             :                           error_message(k5ret)));
    3447             :         }
    3448         884 : out_free:
    3449         884 :         krb5_free_context(krbctx);
    3450         884 : out:
    3451         884 :         return status;
    3452             : }
    3453             : 
    3454         884 : NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
    3455             :                                       TALLOC_CTX *mem_ctx,
    3456             :                                       bool *p_is_trusted,
    3457             :                                       uint16_t *p_validation_level,
    3458             :                                       union netr_Validation **p_validation)
    3459             : {
    3460         884 :         struct winbindd_request *req = state->request;
    3461           0 :         DATA_BLOB pac_blob;
    3462         884 :         struct PAC_DATA *pac_data = NULL;
    3463         884 :         struct PAC_LOGON_INFO *logon_info = NULL;
    3464         884 :         struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
    3465         884 :         struct netr_SamInfo6 *info6 = NULL;
    3466         884 :         uint16_t validation_level = 0;
    3467         884 :         union netr_Validation *validation = NULL;
    3468         884 :         struct netr_SamInfo3 *info3_copy = NULL;
    3469           0 :         NTSTATUS result;
    3470         884 :         bool is_trusted = false;
    3471           0 :         uint32_t i;
    3472         884 :         TALLOC_CTX *tmp_ctx = NULL;
    3473             : 
    3474         884 :         tmp_ctx = talloc_new(mem_ctx);
    3475         884 :         if (tmp_ctx == NULL) {
    3476           0 :                 return NT_STATUS_NO_MEMORY;
    3477             :         }
    3478             : 
    3479         884 :         *p_is_trusted = false;
    3480         884 :         *p_validation_level = 0;
    3481         884 :         *p_validation = NULL;
    3482             : 
    3483         884 :         pac_blob = data_blob_const(req->extra_data.data, req->extra_len);
    3484         884 :         result = extract_pac_vrfy_sigs(tmp_ctx, pac_blob, &pac_data);
    3485         884 :         if (NT_STATUS_IS_OK(result)) {
    3486         884 :                 is_trusted = true;
    3487             :         }
    3488         884 :         if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
    3489             :                 /* Try without signature verification */
    3490           0 :                 result = kerberos_decode_pac(tmp_ctx,
    3491             :                                              pac_blob,
    3492             :                                              NULL, /* krb5_context */
    3493             :                                              NULL, /* krbtgt_keyblock */
    3494             :                                              NULL, /* service_keyblock */
    3495             :                                              NULL, /* client_principal */
    3496             :                                              0, /* tgs_authtime */
    3497             :                                              &pac_data);
    3498             :         }
    3499         884 :         if (!NT_STATUS_IS_OK(result)) {
    3500           0 :                 DEBUG(1, ("Error during PAC signature verification: %s\n",
    3501             :                           nt_errstr(result)));
    3502           0 :                 goto out;
    3503             :         }
    3504             : 
    3505        7460 :         for (i=0; i < pac_data->num_buffers; i++) {
    3506        6576 :                 if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
    3507         884 :                         logon_info = pac_data->buffers[i].info->logon_info.info;
    3508         884 :                         continue;
    3509             :                 }
    3510        5692 :                 if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
    3511         760 :                         upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
    3512         760 :                         continue;
    3513             :                 }
    3514             :         }
    3515             : 
    3516         884 :         result = create_info6_from_pac(tmp_ctx,
    3517             :                                        logon_info,
    3518             :                                        upn_dns_info,
    3519             :                                        &info6);
    3520         884 :         if (!NT_STATUS_IS_OK(result)) {
    3521           0 :                 goto out;
    3522             :         }
    3523             : 
    3524         884 :         if (!is_allowed_domain(info6->base.logon_domain.string)) {
    3525           2 :                 DBG_NOTICE("Authentication failed for user [%s] "
    3526             :                            "from firewalled domain [%s]\n",
    3527             :                            info6->base.account_name.string,
    3528             :                            info6->base.logon_domain.string);
    3529           2 :                 result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
    3530           2 :                 goto out;
    3531             :         }
    3532             : 
    3533         882 :         result = map_info6_to_validation(tmp_ctx,
    3534             :                                          info6,
    3535             :                                          &validation_level,
    3536             :                                          &validation);
    3537         882 :         if (!NT_STATUS_IS_OK(result)) {
    3538           0 :                 goto out;
    3539             :         }
    3540             : 
    3541         882 :         result = map_validation_to_info3(tmp_ctx,
    3542             :                                          validation_level,
    3543             :                                          validation,
    3544             :                                          &info3_copy);
    3545         882 :         if (!NT_STATUS_IS_OK(result)) {
    3546           0 :                 goto out;
    3547             :         }
    3548             : 
    3549         882 :         if (is_trusted) {
    3550             :                 /*
    3551             :                  * Signature verification succeeded, we can
    3552             :                  * trust the PAC and prime the netsamlogon
    3553             :                  * and name2sid caches. DO NOT DO THIS
    3554             :                  * in the signature verification failed
    3555             :                  * code path.
    3556             :                  */
    3557         882 :                 struct winbindd_domain *domain = NULL;
    3558             : 
    3559         882 :                 netsamlogon_cache_store(NULL, info3_copy);
    3560             : 
    3561             :                 /*
    3562             :                  * We're in the parent here, so find the child
    3563             :                  * pointer from the PAC domain name.
    3564             :                  */
    3565         882 :                 domain = find_lookup_domain_from_name(
    3566         882 :                                 info3_copy->base.logon_domain.string);
    3567         882 :                 if (domain && domain->primary ) {
    3568           0 :                         struct dom_sid user_sid;
    3569           0 :                         struct dom_sid_buf buf;
    3570             : 
    3571         882 :                         sid_compose(&user_sid,
    3572         882 :                                 info3_copy->base.domain_sid,
    3573         882 :                                 info3_copy->base.rid);
    3574             : 
    3575         882 :                         cache_name2sid_trusted(domain,
    3576         882 :                                 info3_copy->base.logon_domain.string,
    3577         882 :                                 info3_copy->base.account_name.string,
    3578             :                                 SID_NAME_USER,
    3579             :                                 &user_sid);
    3580             : 
    3581         882 :                         DBG_INFO("PAC for user %s\\%s SID %s primed cache\n",
    3582             :                                 info3_copy->base.logon_domain.string,
    3583             :                                 info3_copy->base.account_name.string,
    3584             :                                 dom_sid_str_buf(&user_sid, &buf));
    3585             :                 }
    3586             :         }
    3587             : 
    3588         882 :         *p_is_trusted = is_trusted;
    3589         882 :         *p_validation_level = validation_level;
    3590         882 :         *p_validation = talloc_move(mem_ctx, &validation);
    3591             : 
    3592         882 :         result = NT_STATUS_OK;
    3593         884 : out:
    3594         884 :         TALLOC_FREE(tmp_ctx);
    3595         884 :         return result;
    3596             : }
    3597             : #else /* HAVE_KRB5 */
    3598             : NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
    3599             :                                       TALLOC_CTX *mem_ctx,
    3600             :                                       bool *p_is_trusted,
    3601             :                                       uint16_t *p_validation_level,
    3602             :                                       union netr_Validation **p_validation);
    3603             : {
    3604             : 
    3605             :         *p_is_trusted = false;
    3606             :         *p_validation_level = 0;
    3607             :         *p_validation = NULL;
    3608             :         return NT_STATUS_NO_SUCH_USER;
    3609             : }
    3610             : #endif /* HAVE_KRB5 */

Generated by: LCOV version 1.14