LCOV - code coverage report
Current view: top level - nsswitch - wb_reqtrans.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 150 198 75.8 %
Date: 2024-02-28 12:06:22 Functions: 18 18 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Async transfer of winbindd_request and _response structs
       5             : 
       6             :    Copyright (C) Volker Lendecke 2008
       7             : 
       8             :      ** NOTE! The following LGPL license applies to the wbclient
       9             :      ** library. This does NOT imply that all of Samba is released
      10             :      ** under the LGPL
      11             : 
      12             :    This library is free software; you can redistribute it and/or
      13             :    modify it under the terms of the GNU Lesser General Public
      14             :    License as published by the Free Software Foundation; either
      15             :    version 3 of the License, or (at your option) any later version.
      16             : 
      17             :    This library is distributed in the hope that it will be useful,
      18             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      20             :    Library General Public License for more details.
      21             : 
      22             :    You should have received a copy of the GNU Lesser General Public License
      23             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include "replace.h"
      27             : #include "system/filesys.h"
      28             : #include "system/network.h"
      29             : #include <talloc.h>
      30             : #include <tevent.h>
      31             : #include "lib/async_req/async_sock.h"
      32             : #include "lib/util/tevent_unix.h"
      33             : #include "nsswitch/winbind_struct_protocol.h"
      34             : #include "nsswitch/libwbclient/wbclient.h"
      35             : #include "nsswitch/wb_reqtrans.h"
      36             : 
      37             : /* can't use DEBUG here... */
      38             : #define DEBUG(a,b)
      39             : 
      40             : struct req_read_state {
      41             :         struct winbindd_request *wb_req;
      42             :         size_t max_extra_data;
      43             :         ssize_t ret;
      44             : };
      45             : 
      46             : static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data);
      47             : static void wb_req_read_done(struct tevent_req *subreq);
      48             : 
      49      258428 : struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
      50             :                                     struct tevent_context *ev,
      51             :                                     int fd, size_t max_extra_data)
      52             : {
      53           0 :         struct tevent_req *req, *subreq;
      54           0 :         struct req_read_state *state;
      55             : 
      56      258428 :         req = tevent_req_create(mem_ctx, &state, struct req_read_state);
      57      258428 :         if (req == NULL) {
      58           0 :                 return NULL;
      59             :         }
      60      258428 :         state->max_extra_data = max_extra_data;
      61             : 
      62      258428 :         subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state);
      63      258428 :         if (tevent_req_nomem(subreq, req)) {
      64           0 :                 return tevent_req_post(req, ev);
      65             :         }
      66      258428 :         tevent_req_set_callback(subreq, wb_req_read_done, req);
      67      258428 :         return req;
      68             : }
      69             : 
      70      509066 : static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data)
      71             : {
      72      509066 :         struct req_read_state *state = talloc_get_type_abort(
      73             :                 private_data, struct req_read_state);
      74      509066 :         struct winbindd_request *req = (struct winbindd_request *)buf;
      75             : 
      76      509066 :         if (buflen == 4) {
      77      250369 :                 if (req->length != sizeof(struct winbindd_request)) {
      78             :                         DEBUG(0, ("wb_req_read_len: Invalid request size "
      79             :                                   "received: %d (expected %d)\n",
      80             :                                   (int)req->length,
      81             :                                   (int)sizeof(struct winbindd_request)));
      82           0 :                         return -1;
      83             :                 }
      84      250369 :                 return sizeof(struct winbindd_request) - 4;
      85             :         }
      86             : 
      87      258697 :         if (buflen > sizeof(struct winbindd_request)) {
      88             :                 /* We've been here, we're done */
      89        8328 :                 return 0;
      90             :         }
      91             : 
      92      250369 :         if ((state->max_extra_data != 0)
      93      250369 :             && (req->extra_len > state->max_extra_data)) {
      94             :                 DEBUG(3, ("Got request with %d bytes extra data on "
      95             :                           "unprivileged socket\n", (int)req->extra_len));
      96           0 :                 return -1;
      97             :         }
      98             : 
      99      250369 :         return req->extra_len;
     100             : }
     101             : 
     102      258304 : static void wb_req_read_done(struct tevent_req *subreq)
     103             : {
     104      258304 :         struct tevent_req *req = tevent_req_callback_data(
     105             :                 subreq, struct tevent_req);
     106      258304 :         struct req_read_state *state = tevent_req_data(
     107             :                 req, struct req_read_state);
     108           0 :         int err;
     109           0 :         uint8_t *buf;
     110             : 
     111      258304 :         state->ret = read_packet_recv(subreq, state, &buf, &err);
     112      258304 :         TALLOC_FREE(subreq);
     113      258304 :         if (state->ret == -1) {
     114        7935 :                 tevent_req_error(req, err);
     115        7935 :                 return;
     116             :         }
     117             : 
     118      250369 :         state->wb_req = (struct winbindd_request *)buf;
     119             : 
     120      250369 :         if (state->wb_req->extra_len != 0) {
     121        8328 :                 state->wb_req->extra_data.data =
     122        8328 :                         (char *)buf + sizeof(struct winbindd_request);
     123             :         } else {
     124      242041 :                 state->wb_req->extra_data.data = NULL;
     125             :         }
     126      250369 :         tevent_req_done(req);
     127             : }
     128             : 
     129      258304 : ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     130             :                          struct winbindd_request **preq, int *err)
     131             : {
     132      258304 :         struct req_read_state *state = tevent_req_data(
     133             :                 req, struct req_read_state);
     134             : 
     135      258304 :         if (tevent_req_is_unix_error(req, err)) {
     136        7935 :                 return -1;
     137             :         }
     138      250369 :         *preq = talloc_move(mem_ctx, &state->wb_req);
     139      250369 :         return state->ret;
     140             : }
     141             : 
     142             : struct req_write_state {
     143             :         struct iovec iov[2];
     144             :         ssize_t ret;
     145             : };
     146             : 
     147             : static void wb_req_write_done(struct tevent_req *subreq);
     148             : 
     149      127821 : struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
     150             :                                      struct tevent_context *ev,
     151             :                                      struct tevent_queue *queue, int fd,
     152             :                                      struct winbindd_request *wb_req)
     153             : {
     154           0 :         struct tevent_req *req, *subreq;
     155           0 :         struct req_write_state *state;
     156      127821 :         int count = 1;
     157             : 
     158      127821 :         req = tevent_req_create(mem_ctx, &state, struct req_write_state);
     159      127821 :         if (req == NULL) {
     160           0 :                 return NULL;
     161             :         }
     162             : 
     163      127821 :         state->iov[0].iov_base = (void *)wb_req;
     164      127821 :         state->iov[0].iov_len = sizeof(struct winbindd_request);
     165             : 
     166      127821 :         if (wb_req->extra_len != 0) {
     167      126902 :                 state->iov[1].iov_base = (void *)wb_req->extra_data.data;
     168      126902 :                 state->iov[1].iov_len = wb_req->extra_len;
     169      126902 :                 count = 2;
     170             :         }
     171             : 
     172      127821 :         subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
     173      127821 :         if (tevent_req_nomem(subreq, req)) {
     174           0 :                 return tevent_req_post(req, ev);
     175             :         }
     176      127821 :         tevent_req_set_callback(subreq, wb_req_write_done, req);
     177      127821 :         return req;
     178             : }
     179             : 
     180      127821 : static void wb_req_write_done(struct tevent_req *subreq)
     181             : {
     182      127821 :         struct tevent_req *req = tevent_req_callback_data(
     183             :                 subreq, struct tevent_req);
     184      127821 :         struct req_write_state *state = tevent_req_data(
     185             :                 req, struct req_write_state);
     186           0 :         int err;
     187             : 
     188      127821 :         state->ret = writev_recv(subreq, &err);
     189      127821 :         TALLOC_FREE(subreq);
     190      127821 :         if (state->ret < 0) {
     191           0 :                 tevent_req_error(req, err);
     192           0 :                 return;
     193             :         }
     194      127821 :         tevent_req_done(req);
     195             : }
     196             : 
     197      127821 : ssize_t wb_req_write_recv(struct tevent_req *req, int *err)
     198             : {
     199      127821 :         struct req_write_state *state = tevent_req_data(
     200             :                 req, struct req_write_state);
     201             : 
     202      127821 :         if (tevent_req_is_unix_error(req, err)) {
     203           0 :                 return -1;
     204             :         }
     205      127821 :         return state->ret;
     206             : }
     207             : 
     208             : struct resp_read_state {
     209             :         struct winbindd_response *wb_resp;
     210             :         ssize_t ret;
     211             : };
     212             : 
     213             : static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data);
     214             : static void wb_resp_read_done(struct tevent_req *subreq);
     215             : 
     216      127821 : struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
     217             :                                      struct tevent_context *ev, int fd)
     218             : {
     219           0 :         struct tevent_req *req, *subreq;
     220           0 :         struct resp_read_state *state;
     221             : 
     222      127821 :         req = tevent_req_create(mem_ctx, &state, struct resp_read_state);
     223      127821 :         if (req == NULL) {
     224           0 :                 return NULL;
     225             :         }
     226             : 
     227      127821 :         subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state);
     228      127821 :         if (tevent_req_nomem(subreq, req)) {
     229           0 :                 return tevent_req_post(req, ev);
     230             :         }
     231      127821 :         tevent_req_set_callback(subreq, wb_resp_read_done, req);
     232      127821 :         return req;
     233             : }
     234             : 
     235      255642 : static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data)
     236             : {
     237      255642 :         struct winbindd_response *resp = (struct winbindd_response *)buf;
     238             : 
     239      255642 :         if (buflen == 4) {
     240      127821 :                 if (resp->length < sizeof(struct winbindd_response)) {
     241             :                         DEBUG(0, ("wb_resp_read_len: Invalid response size "
     242             :                                   "received: %d (expected at least%d)\n",
     243             :                                   (int)resp->length,
     244             :                                   (int)sizeof(struct winbindd_response)));
     245           0 :                         return -1;
     246             :                 }
     247             :         }
     248      255642 :         return resp->length - buflen;
     249             : }
     250             : 
     251      127821 : static void wb_resp_read_done(struct tevent_req *subreq)
     252             : {
     253      127821 :         struct tevent_req *req = tevent_req_callback_data(
     254             :                 subreq, struct tevent_req);
     255      127821 :         struct resp_read_state *state = tevent_req_data(
     256             :                 req, struct resp_read_state);
     257           0 :         uint8_t *buf;
     258           0 :         int err;
     259             : 
     260      127821 :         state->ret = read_packet_recv(subreq, state, &buf, &err);
     261      127821 :         TALLOC_FREE(subreq);
     262      127821 :         if (state->ret == -1) {
     263           0 :                 tevent_req_error(req, err);
     264           0 :                 return;
     265             :         }
     266             : 
     267      127821 :         state->wb_resp = (struct winbindd_response *)buf;
     268             : 
     269      127821 :         if (state->wb_resp->length > sizeof(struct winbindd_response)) {
     270      127619 :                 state->wb_resp->extra_data.data =
     271      127619 :                         (char *)buf + sizeof(struct winbindd_response);
     272             :         } else {
     273         202 :                 state->wb_resp->extra_data.data = NULL;
     274             :         }
     275      127821 :         tevent_req_done(req);
     276             : }
     277             : 
     278      127821 : ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     279             :                           struct winbindd_response **presp, int *err)
     280             : {
     281      127821 :         struct resp_read_state *state = tevent_req_data(
     282             :                 req, struct resp_read_state);
     283             : 
     284      127821 :         if (tevent_req_is_unix_error(req, err)) {
     285           0 :                 return -1;
     286             :         }
     287      127821 :         *presp = talloc_move(mem_ctx, &state->wb_resp);
     288      127821 :         return state->ret;
     289             : }
     290             : 
     291             : struct resp_write_state {
     292             :         struct iovec iov[2];
     293             :         ssize_t ret;
     294             : };
     295             : 
     296             : static void wb_resp_write_done(struct tevent_req *subreq);
     297             : 
     298      250369 : struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
     299             :                                       struct tevent_context *ev,
     300             :                                       struct tevent_queue *queue, int fd,
     301             :                                       struct winbindd_response *wb_resp)
     302             : {
     303           0 :         struct tevent_req *req, *subreq;
     304           0 :         struct resp_write_state *state;
     305      250369 :         int count = 1;
     306             : 
     307      250369 :         req = tevent_req_create(mem_ctx, &state, struct resp_write_state);
     308      250369 :         if (req == NULL) {
     309           0 :                 return NULL;
     310             :         }
     311             : 
     312      250369 :         state->iov[0].iov_base = (void *)wb_resp;
     313      250369 :         state->iov[0].iov_len = sizeof(struct winbindd_response);
     314             : 
     315      250369 :         if (wb_resp->length > sizeof(struct winbindd_response)) {
     316        8475 :                 state->iov[1].iov_base = (void *)wb_resp->extra_data.data;
     317        8475 :                 state->iov[1].iov_len =
     318        8475 :                         wb_resp->length - sizeof(struct winbindd_response);
     319        8475 :                 count = 2;
     320             :         }
     321             : 
     322      250369 :         subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
     323      250369 :         if (tevent_req_nomem(subreq, req)) {
     324           0 :                 return tevent_req_post(req, ev);
     325             :         }
     326      250369 :         tevent_req_set_callback(subreq, wb_resp_write_done, req);
     327      250369 :         return req;
     328             : }
     329             : 
     330      250369 : static void wb_resp_write_done(struct tevent_req *subreq)
     331             : {
     332      250369 :         struct tevent_req *req = tevent_req_callback_data(
     333             :                 subreq, struct tevent_req);
     334      250369 :         struct resp_write_state *state = tevent_req_data(
     335             :                 req, struct resp_write_state);
     336           0 :         int err;
     337             : 
     338      250369 :         state->ret = writev_recv(subreq, &err);
     339      250369 :         TALLOC_FREE(subreq);
     340      250369 :         if (state->ret < 0) {
     341           0 :                 tevent_req_error(req, err);
     342           0 :                 return;
     343             :         }
     344      250369 :         tevent_req_done(req);
     345             : }
     346             : 
     347      250369 : ssize_t wb_resp_write_recv(struct tevent_req *req, int *err)
     348             : {
     349      250369 :         struct resp_write_state *state = tevent_req_data(
     350             :                 req, struct resp_write_state);
     351             : 
     352      250369 :         if (tevent_req_is_unix_error(req, err)) {
     353           0 :                 return -1;
     354             :         }
     355      250369 :         return state->ret;
     356             : }
     357             : 
     358             : struct wb_simple_trans_state {
     359             :         struct tevent_context *ev;
     360             :         int fd;
     361             :         struct winbindd_response *wb_resp;
     362             : };
     363             : 
     364             : static void wb_simple_trans_write_done(struct tevent_req *subreq);
     365             : static void wb_simple_trans_read_done(struct tevent_req *subreq);
     366             : 
     367      127821 : struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx,
     368             :                                         struct tevent_context *ev,
     369             :                                         struct tevent_queue *queue, int fd,
     370             :                                         struct winbindd_request *wb_req)
     371             : {
     372           0 :         struct tevent_req *req, *subreq;
     373           0 :         struct wb_simple_trans_state *state;
     374             : 
     375      127821 :         req = tevent_req_create(mem_ctx, &state, struct wb_simple_trans_state);
     376      127821 :         if (req == NULL) {
     377           0 :                 return NULL;
     378             :         }
     379             : 
     380      127821 :         wb_req->length = sizeof(struct winbindd_request);
     381             : 
     382      127821 :         state->ev = ev;
     383      127821 :         state->fd = fd;
     384             : 
     385      127821 :         subreq = wb_req_write_send(state, ev, queue, fd, wb_req);
     386      127821 :         if (tevent_req_nomem(subreq, req)) {
     387           0 :                 return tevent_req_post(req, ev);
     388             :         }
     389      127821 :         tevent_req_set_callback(subreq, wb_simple_trans_write_done, req);
     390             : 
     391      127821 :         return req;
     392             : }
     393             : 
     394      127821 : static void wb_simple_trans_write_done(struct tevent_req *subreq)
     395             : {
     396      127821 :         struct tevent_req *req = tevent_req_callback_data(
     397             :                 subreq, struct tevent_req);
     398      127821 :         struct wb_simple_trans_state *state = tevent_req_data(
     399             :                 req, struct wb_simple_trans_state);
     400           0 :         ssize_t ret;
     401           0 :         int err;
     402             : 
     403      127821 :         ret = wb_req_write_recv(subreq, &err);
     404      127821 :         TALLOC_FREE(subreq);
     405      127821 :         if (ret == -1) {
     406           0 :                 tevent_req_error(req, err);
     407           0 :                 return;
     408             :         }
     409      127821 :         subreq = wb_resp_read_send(state, state->ev, state->fd);
     410      127821 :         if (tevent_req_nomem(subreq, req)) {
     411           0 :                 return;
     412             :         }
     413      127821 :         tevent_req_set_callback(subreq, wb_simple_trans_read_done, req);
     414             : }
     415             : 
     416      127821 : static void wb_simple_trans_read_done(struct tevent_req *subreq)
     417             : {
     418      127821 :         struct tevent_req *req = tevent_req_callback_data(
     419             :                 subreq, struct tevent_req);
     420      127821 :         struct wb_simple_trans_state *state = tevent_req_data(
     421             :                 req, struct wb_simple_trans_state);
     422           0 :         ssize_t ret;
     423           0 :         int err;
     424             : 
     425      127821 :         ret = wb_resp_read_recv(subreq, state, &state->wb_resp, &err);
     426      127821 :         TALLOC_FREE(subreq);
     427      127821 :         if (ret == -1) {
     428           0 :                 tevent_req_error(req, err);
     429           0 :                 return;
     430             :         }
     431             : 
     432      127821 :         tevent_req_done(req);
     433             : }
     434             : 
     435      127821 : int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     436             :                          struct winbindd_response **presponse, int *err)
     437             : {
     438      127821 :         struct wb_simple_trans_state *state = tevent_req_data(
     439             :                 req, struct wb_simple_trans_state);
     440             : 
     441      127821 :         if (tevent_req_is_unix_error(req, err)) {
     442           0 :                 return -1;
     443             :         }
     444      127821 :         *presponse = talloc_move(mem_ctx, &state->wb_resp);
     445      127821 :         return 0;
     446             : }

Generated by: LCOV version 1.14