LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_getpwent.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 55 70 78.6 %
Date: 2024-04-21 15:09:00 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    async implementation of WINBINDD_GETPWENT
       4             :    Copyright (C) Volker Lendecke 2009
       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             : 
      23             : struct winbindd_getpwent_state {
      24             :         struct tevent_context *ev;
      25             :         struct winbindd_cli_state *cli;
      26             :         uint32_t max_users;
      27             :         uint32_t num_users;
      28             :         struct winbindd_pw *users;
      29             : };
      30             : 
      31             : static void winbindd_getpwent_done(struct tevent_req *subreq);
      32             : 
      33          54 : struct tevent_req *winbindd_getpwent_send(TALLOC_CTX *mem_ctx,
      34             :                                           struct tevent_context *ev,
      35             :                                           struct winbindd_cli_state *cli,
      36             :                                           struct winbindd_request *request)
      37             : {
      38           0 :         struct tevent_req *req, *subreq;
      39           0 :         struct winbindd_getpwent_state *state;
      40             : 
      41          54 :         req = tevent_req_create(mem_ctx, &state,
      42             :                                 struct winbindd_getpwent_state);
      43          54 :         if (req == NULL) {
      44           0 :                 return NULL;
      45             :         }
      46          54 :         state->ev = ev;
      47          54 :         state->num_users = 0;
      48          54 :         state->cli = cli;
      49             : 
      50          54 :         D_NOTICE("[%s (%u)] Winbind external command GETPWENT start.\n"
      51             :                  "The caller (%s) provided room for %d entries.\n",
      52             :                  cli->client_name,
      53             :                  (unsigned int)cli->pid,
      54             :                  cli->client_name,
      55             :                  request->data.num_entries);
      56             : 
      57          54 :         if (cli->pwent_state == NULL) {
      58          20 :                 tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES);
      59          20 :                 return tevent_req_post(req, ev);
      60             :         }
      61             : 
      62          34 :         state->max_users = MIN(500, request->data.num_entries);
      63          34 :         if (state->max_users == 0) {
      64           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
      65           0 :                 return tevent_req_post(req, ev);
      66             :         }
      67             : 
      68          34 :         state->users = talloc_zero_array(state, struct winbindd_pw,
      69             :                                          state->max_users);
      70          34 :         if (tevent_req_nomem(state->users, req)) {
      71           0 :                 return tevent_req_post(req, ev);
      72             :         }
      73             : 
      74          34 :         subreq = wb_next_pwent_send(state, ev, cli->pwent_state,
      75          34 :                                     &state->users[state->num_users]);
      76          34 :         if (tevent_req_nomem(subreq, req)) {
      77           0 :                 return tevent_req_post(req, ev);
      78             :         }
      79          34 :         tevent_req_set_callback(subreq, winbindd_getpwent_done, req);
      80          34 :         return req;
      81             : }
      82             : 
      83        1774 : static void winbindd_getpwent_done(struct tevent_req *subreq)
      84             : {
      85        1774 :         struct tevent_req *req = tevent_req_callback_data(
      86             :                 subreq, struct tevent_req);
      87        1774 :         struct winbindd_getpwent_state *state = tevent_req_data(
      88             :                 req, struct winbindd_getpwent_state);
      89           0 :         NTSTATUS status;
      90             : 
      91        1774 :         status = wb_next_pwent_recv(subreq);
      92        1774 :         TALLOC_FREE(subreq);
      93        1774 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
      94          30 :                 D_DEBUG("winbindd_getpwent_done: done with %"PRIu32" users\n",
      95             :                         state->num_users);
      96          30 :                 TALLOC_FREE(state->cli->pwent_state);
      97          30 :                 tevent_req_done(req);
      98          30 :                 return;
      99             :         }
     100        1744 :         if (tevent_req_nterror(req, status)) {
     101           0 :                 return;
     102             :         }
     103        1744 :         state->num_users += 1;
     104        1744 :         if (state->num_users >= state->max_users) {
     105           4 :                 D_DEBUG("winbindd_getpwent_done: Got enough users: %"PRIu32"\n",
     106             :                         state->num_users);
     107           4 :                 tevent_req_done(req);
     108           4 :                 return;
     109             :         }
     110        1740 :         if (state->cli->pwent_state == NULL) {
     111           0 :                 D_DEBUG("winbindd_getpwent_done: endpwent called in between\n");
     112           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     113           0 :                 return;
     114             :         }
     115        1740 :         subreq = wb_next_pwent_send(state, state->ev, state->cli->pwent_state,
     116        1740 :                                     &state->users[state->num_users]);
     117        1740 :         if (tevent_req_nomem(subreq, req)) {
     118           0 :                 return;
     119             :         }
     120        1740 :         tevent_req_set_callback(subreq, winbindd_getpwent_done, req);
     121             : }
     122             : 
     123          54 : NTSTATUS winbindd_getpwent_recv(struct tevent_req *req,
     124             :                                 struct winbindd_response *response)
     125             : {
     126          54 :         struct winbindd_getpwent_state *state = tevent_req_data(
     127             :                 req, struct winbindd_getpwent_state);
     128           0 :         NTSTATUS status;
     129           0 :         uint32_t i;
     130             : 
     131          54 :         if (tevent_req_is_nterror(req, &status)) {
     132          20 :                 TALLOC_FREE(state->cli->pwent_state);
     133          20 :                 D_WARNING("getpwent failed: %s\n", nt_errstr(status));
     134          20 :                 return status;
     135             :         }
     136             : 
     137          34 :         D_NOTICE("Winbind external command GETPWENT end.\n"
     138             :                  "Received %"PRIu32" entries.\n"
     139             :                  "(name:passwd:uid:gid:gecos:dir:shell)\n",
     140             :                  state->num_users);
     141             : 
     142          34 :         if (state->num_users == 0) {
     143          10 :                 return NT_STATUS_NO_MORE_ENTRIES;
     144             :         }
     145             : 
     146        1768 :         for (i = 0; i < state->num_users; i++) {
     147        1744 :                 D_NOTICE("%"PRIu32": %s:%s:%u:%u:%s:%s:%s\n",
     148             :                         i,
     149             :                         state->users[i].pw_name,
     150             :                         state->users[i].pw_passwd,
     151             :                         (unsigned int)state->users[i].pw_uid,
     152             :                         (unsigned int)state->users[i].pw_gid,
     153             :                         state->users[i].pw_gecos,
     154             :                         state->users[i].pw_dir,
     155             :                         state->users[i].pw_shell
     156             :                         );
     157             :         }
     158          24 :         response->data.num_entries = state->num_users;
     159          24 :         response->extra_data.data = talloc_move(response, &state->users);
     160          24 :         response->length += state->num_users * sizeof(struct winbindd_pw);
     161          24 :         return NT_STATUS_OK;
     162             : }

Generated by: LCOV version 1.14