LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_pam_chauthtok.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 52 93 55.9 %
Date: 2024-04-21 15:09:00 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    async implementation of WINBINDD_PAM_CHAUTHTOK
       4             :    Copyright (C) Volker Lendecke 2010
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "winbindd.h"
      22             : #include "lib/util/string_wrappers.h"
      23             : #include "lib/global_contexts.h"
      24             : #include "librpc/gen_ndr/ndr_winbind_c.h"
      25             : 
      26           0 : static void fill_in_password_policy(struct winbindd_response *r,
      27             :                                     const struct samr_DomInfo1 *p)
      28             : {
      29           0 :         r->data.auth.policy.min_length_password =
      30           0 :                 p->min_password_length;
      31           0 :         r->data.auth.policy.password_history =
      32           0 :                 p->password_history_length;
      33           0 :         r->data.auth.policy.password_properties =
      34           0 :                 p->password_properties;
      35           0 :         r->data.auth.policy.expire   =
      36           0 :                 nt_time_to_unix_abs((const NTTIME *)&(p->max_password_age));
      37           0 :         r->data.auth.policy.min_passwordage =
      38           0 :                 nt_time_to_unix_abs((const NTTIME *)&(p->min_password_age));
      39           0 : }
      40             : 
      41             : struct winbindd_pam_chauthtok_state {
      42             :         struct wbint_PamAuthChangePassword r;
      43             : };
      44             : 
      45             : static void winbindd_pam_chauthtok_done(struct tevent_req *subreq);
      46             : 
      47          14 : struct tevent_req *winbindd_pam_chauthtok_send(
      48             :         TALLOC_CTX *mem_ctx,
      49             :         struct tevent_context *ev,
      50             :         struct winbindd_cli_state *cli,
      51             :         struct winbindd_request *request)
      52             : {
      53           0 :         struct tevent_req *req, *subreq;
      54           0 :         struct winbindd_pam_chauthtok_state *state;
      55           0 :         struct winbindd_domain *contact_domain;
      56          14 :         char *namespace = NULL;
      57          14 :         char *domain = NULL;
      58          14 :         char *user = NULL;
      59          14 :         char *chauthtok_user = NULL;
      60           0 :         char *mapped_user;
      61           0 :         NTSTATUS status;
      62           0 :         bool ok;
      63             : 
      64          14 :         req = tevent_req_create(mem_ctx, &state,
      65             :                                 struct winbindd_pam_chauthtok_state);
      66          14 :         if (req == NULL) {
      67           0 :                 return NULL;
      68             :         }
      69             : 
      70             :         /* Ensure null termination */
      71           0 :         request->data.chauthtok.user[
      72          14 :                 sizeof(request->data.chauthtok.user)-1]='\0';
      73             : 
      74          14 :         DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)cli->pid,
      75             :                   request->data.chauthtok.user));
      76             : 
      77          14 :         status = normalize_name_unmap(state, request->data.chauthtok.user,
      78             :                                       &mapped_user);
      79             : 
      80          14 :         if (NT_STATUS_IS_OK(status) ||
      81          14 :             NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
      82           0 :                 fstrcpy(request->data.chauthtok.user, mapped_user);
      83             :         }
      84             : 
      85          14 :         chauthtok_user = request->data.chauthtok.user;
      86          14 :         ok = canonicalize_username(req,
      87             :                                    &chauthtok_user,
      88             :                                    &namespace,
      89             :                                    &domain,
      90             :                                    &user);
      91          14 :         if (!ok) {
      92           0 :                 DEBUG(10, ("winbindd_pam_chauthtok: canonicalize_username %s "
      93             :                            "failed with\n", request->data.chauthtok.user));
      94           0 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
      95           0 :                 return tevent_req_post(req, ev);
      96             :         }
      97             : 
      98          14 :         fstrcpy(request->data.chauthtok.user, chauthtok_user);
      99             : 
     100          14 :         contact_domain = find_domain_from_name(namespace);
     101          14 :         if (contact_domain == NULL) {
     102           0 :                 DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] "
     103             :                           "as %s is not a trusted domain\n",
     104             :                           request->data.chauthtok.user, domain, user, domain));
     105           0 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
     106           0 :                 return tevent_req_post(req, ev);
     107             :         }
     108             : 
     109          14 :         state->r.in.client_pid = request->pid;
     110          14 :         state->r.in.flags = request->flags;
     111             : 
     112          14 :         state->r.in.client_name = talloc_strdup(state, request->client_name);
     113          14 :         if (tevent_req_nomem(state->r.in.client_name, req)) {
     114           0 :                 return tevent_req_post(req, ev);
     115             :         }
     116             : 
     117          14 :         state->r.in.user = talloc_strdup(state, request->data.chauthtok.user);
     118          14 :         if (tevent_req_nomem(state->r.in.user, req)) {
     119           0 :                 return tevent_req_post(req, ev);
     120             :         }
     121             : 
     122          28 :         state->r.in.old_password = talloc_strdup(state,
     123          14 :                         request->data.chauthtok.oldpass);
     124          14 :         if (tevent_req_nomem(state->r.in.old_password, req)) {
     125           0 :                 return tevent_req_post(req, ev);
     126             :         }
     127             : 
     128          28 :         state->r.in.new_password = talloc_strdup(state,
     129          14 :                         request->data.chauthtok.newpass);
     130          14 :         if (tevent_req_nomem(state->r.in.new_password, req)) {
     131           0 :                 return tevent_req_post(req, ev);
     132             :         }
     133             : 
     134          14 :         subreq = dcerpc_wbint_PamAuthChangePassword_r_send(state,
     135             :                                         global_event_context(),
     136             :                                         dom_child_handle(contact_domain),
     137          14 :                                         &state->r);
     138          14 :         if (tevent_req_nomem(subreq, req)) {
     139           0 :                 return tevent_req_post(req, ev);
     140             :         }
     141          14 :         tevent_req_set_callback(subreq, winbindd_pam_chauthtok_done, req);
     142          14 :         return req;
     143             : }
     144             : 
     145          14 : static void winbindd_pam_chauthtok_done(struct tevent_req *subreq)
     146             : {
     147          14 :         struct tevent_req *req = tevent_req_callback_data(
     148             :                 subreq, struct tevent_req);
     149          14 :         struct winbindd_pam_chauthtok_state *state = tevent_req_data(
     150             :                 req, struct winbindd_pam_chauthtok_state);
     151           0 :         NTSTATUS status;
     152             : 
     153          14 :         status = dcerpc_wbint_PamAuthChangePassword_r_recv(subreq, state);
     154          14 :         TALLOC_FREE(subreq);
     155          14 :         if (tevent_req_nterror(req, status)) {
     156           0 :                 return;
     157             :         }
     158             : 
     159          14 :         tevent_req_done(req);
     160             : }
     161             : 
     162          14 : NTSTATUS winbindd_pam_chauthtok_recv(struct tevent_req *req,
     163             :                                      struct winbindd_response *response)
     164             : {
     165          14 :         struct winbindd_pam_chauthtok_state *state = tevent_req_data(
     166             :                 req, struct winbindd_pam_chauthtok_state);
     167          14 :         NTSTATUS status = NT_STATUS_OK;
     168             : 
     169          14 :         if (tevent_req_is_nterror(req, &status)) {
     170           0 :                 set_auth_errors(response, status);
     171           0 :                 return status;
     172             :         }
     173             : 
     174          14 :         response->result = WINBINDD_PENDING;
     175             : 
     176          14 :         set_auth_errors(response, state->r.out.result);
     177          14 :         if (*state->r.out.dominfo != NULL) {
     178           0 :                 fill_in_password_policy(response, *state->r.out.dominfo);
     179             :         }
     180          14 :         response->data.auth.reject_reason = *state->r.out.reject_reason;
     181             : 
     182          14 :         if (state->r.in.flags & WBFLAG_PAM_CACHED_LOGIN) {
     183             : 
     184             :                 /* Update the single sign-on memory creds. */
     185           0 :                 status = winbindd_replace_memory_creds(
     186             :                         state->r.in.user, state->r.in.new_password);
     187             : 
     188           0 :                 DEBUG(10, ("winbindd_replace_memory_creds returned %s\n",
     189             :                            nt_errstr(status)));
     190             : 
     191             :                 /*
     192             :                  * When we login from gdm or xdm and password expires,
     193             :                  * we change password, but there are no memory
     194             :                  * credentials. So, winbindd_replace_memory_creds()
     195             :                  * returns NT_STATUS_OBJECT_NAME_NOT_FOUND. This is
     196             :                  * not a failure.  --- BoYang
     197             :                  */
     198           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     199           0 :                         status = NT_STATUS_OK;
     200             :                 }
     201             :         }
     202             : 
     203          14 :         return NT_STATUS(response->data.auth.nt_status);
     204             : }

Generated by: LCOV version 1.14