LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_pam.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 249 1450 17.2 %
Date: 2024-06-13 04:01:37 Functions: 8 30 26.7 %

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

Generated by: LCOV version 1.13