rpc_client/cli_pipe.c

説明を見る。
00001 /* 
00002  *  Unix SMB/CIFS implementation.
00003  *  RPC Pipe client / server routines
00004  *  Largely rewritten by Jeremy Allison             2005.
00005  *  
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *  
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *  
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include "includes.h"
00022 
00023 #undef DBGC_CLASS
00024 #define DBGC_CLASS DBGC_RPC_CLI
00025 
00026 extern struct pipe_id_info pipe_names[];
00027 
00028 /********************************************************************
00029  Map internal value to wire value.
00030  ********************************************************************/
00031 
00032 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
00033 {
00034         switch (auth_type) {
00035 
00036         case PIPE_AUTH_TYPE_NONE:
00037                 return RPC_ANONYMOUS_AUTH_TYPE;
00038 
00039         case PIPE_AUTH_TYPE_NTLMSSP:
00040                 return RPC_NTLMSSP_AUTH_TYPE;
00041 
00042         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
00043         case PIPE_AUTH_TYPE_SPNEGO_KRB5:
00044                 return RPC_SPNEGO_AUTH_TYPE;
00045 
00046         case PIPE_AUTH_TYPE_SCHANNEL:
00047                 return RPC_SCHANNEL_AUTH_TYPE;
00048 
00049         case PIPE_AUTH_TYPE_KRB5:
00050                 return RPC_KRB5_AUTH_TYPE;
00051 
00052         default:
00053                 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
00054                         "auth type %u\n",
00055                         (unsigned int)auth_type ));
00056                 break;
00057         }
00058         return -1;
00059 }
00060 
00061 /********************************************************************
00062  Rpc pipe call id.
00063  ********************************************************************/
00064 
00065 static uint32 get_rpc_call_id(void)
00066 {
00067         static uint32 call_id = 0;
00068         return ++call_id;
00069 }
00070 
00071 /*******************************************************************
00072  Use SMBreadX to get rest of one fragment's worth of rpc data.
00073  Will expand the current_pdu struct to the correct size.
00074  ********************************************************************/
00075 
00076 static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
00077                         prs_struct *current_pdu,
00078                         uint32 data_to_read,
00079                         uint32 *current_pdu_offset)
00080 {
00081         size_t size = (size_t)cli->max_recv_frag;
00082         uint32 stream_offset = 0;
00083         ssize_t num_read;
00084         char *pdata;
00085         ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
00086 
00087         DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
00088                 (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
00089 
00090         /*
00091          * Grow the buffer if needed to accommodate the data to be read.
00092          */
00093 
00094         if (extra_data_size > 0) {
00095                 if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
00096                         DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
00097                         return NT_STATUS_NO_MEMORY;
00098                 }
00099                 DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
00100         }
00101 
00102         pdata = prs_data_p(current_pdu) + *current_pdu_offset;
00103 
00104         do {
00105                 /* read data using SMBreadX */
00106                 if (size > (size_t)data_to_read) {
00107                         size = (size_t)data_to_read;
00108                 }
00109 
00110                 num_read = cli_read(cli->cli, cli->fnum, pdata,
00111                                          (off_t)stream_offset, size);
00112 
00113                 DEBUG(5,("rpc_read: num_read = %d, read offset: %u, to read: %u\n",
00114                         (int)num_read, (unsigned int)stream_offset, (unsigned int)data_to_read));
00115 
00116                 /*
00117                  * A dos error of ERRDOS/ERRmoredata is not an error.
00118                  */
00119                 if (cli_is_dos_error(cli->cli)) {
00120                         uint32 ecode;
00121                         uint8 eclass;
00122                         cli_dos_error(cli->cli, &eclass, &ecode);
00123                         if (eclass != ERRDOS && ecode != ERRmoredata) {
00124                                 DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read on pipe %s\n",
00125                                         eclass, (unsigned int)ecode,
00126                                         cli_errstr(cli->cli),
00127                                         cli->pipe_name ));
00128                                 return dos_to_ntstatus(eclass, ecode);
00129                         }
00130                 }
00131 
00132                 /*
00133                  * Likewise for NT_STATUS_BUFFER_TOO_SMALL
00134                  */
00135                 if (cli_is_nt_error(cli->cli)) {
00136                         if (!NT_STATUS_EQUAL(cli_nt_error(cli->cli), NT_STATUS_BUFFER_TOO_SMALL)) {
00137                                 DEBUG(0,("rpc_read: Error (%s) in cli_read on pipe %s\n",
00138                                         nt_errstr(cli_nt_error(cli->cli)),
00139                                         cli->pipe_name ));
00140                                 return cli_nt_error(cli->cli);
00141                         }
00142                 }
00143 
00144                 if (num_read == -1) {
00145                         DEBUG(0,("rpc_read: Error - cli_read on pipe %s returned -1\n",
00146                                 cli->pipe_name ));
00147                         return cli_get_nt_error(cli->cli);
00148                 }
00149 
00150                 data_to_read -= num_read;
00151                 stream_offset += num_read;
00152                 pdata += num_read;
00153 
00154         } while (num_read > 0 && data_to_read > 0);
00155         /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
00156 
00157         /*
00158          * Update the current offset into current_pdu by the amount read.
00159          */
00160         *current_pdu_offset += stream_offset;
00161         return NT_STATUS_OK;
00162 }
00163 
00164 /****************************************************************************
00165  Try and get a PDU's worth of data from current_pdu. If not, then read more
00166  from the wire.
00167  ****************************************************************************/
00168 
00169 static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
00170 {
00171         NTSTATUS ret = NT_STATUS_OK;
00172         uint32 current_pdu_len = prs_data_size(current_pdu);
00173 
00174         /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
00175         if (current_pdu_len < RPC_HEADER_LEN) {
00176                 /* rpc_read expands the current_pdu struct as neccessary. */
00177                 ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
00178                 if (!NT_STATUS_IS_OK(ret)) {
00179                         return ret;
00180                 }
00181         }
00182 
00183         /* This next call sets the endian bit correctly in current_pdu. */
00184         /* We will propagate this to rbuf later. */
00185         if(!smb_io_rpc_hdr("rpc_hdr   ", prhdr, current_pdu, 0)) {
00186                 DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
00187                 return NT_STATUS_BUFFER_TOO_SMALL;
00188         }
00189 
00190         /* Ensure we have frag_len bytes of data. */
00191         if (current_pdu_len < prhdr->frag_len) {
00192                 /* rpc_read expands the current_pdu struct as neccessary. */
00193                 ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
00194                 if (!NT_STATUS_IS_OK(ret)) {
00195                         return ret;
00196                 }
00197         }
00198 
00199         if (current_pdu_len < prhdr->frag_len) {
00200                 return NT_STATUS_BUFFER_TOO_SMALL;
00201         }
00202 
00203         return NT_STATUS_OK;
00204 }
00205 
00206 /****************************************************************************
00207  NTLMSSP specific sign/seal.
00208  Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
00209  In fact I should probably abstract these into identical pieces of code... JRA.
00210  ****************************************************************************/
00211 
00212 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
00213                                 prs_struct *current_pdu,
00214                                 uint8 *p_ss_padding_len)
00215 {
00216         RPC_HDR_AUTH auth_info;
00217         uint32 save_offset = prs_offset(current_pdu);
00218         uint32 auth_len = prhdr->auth_len;
00219         NTLMSSP_STATE *ntlmssp_state = cli->auth.a_u.ntlmssp_state;
00220         unsigned char *data = NULL;
00221         size_t data_len;
00222         unsigned char *full_packet_data = NULL;
00223         size_t full_packet_data_len;
00224         DATA_BLOB auth_blob;
00225         NTSTATUS status;
00226 
00227         if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
00228                 return NT_STATUS_OK;
00229         }
00230 
00231         if (!ntlmssp_state) {
00232                 return NT_STATUS_INVALID_PARAMETER;
00233         }
00234 
00235         /* Ensure there's enough data for an authenticated response. */
00236         if ((auth_len > RPC_MAX_SIGN_SIZE) ||
00237                         (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
00238                 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
00239                         (unsigned int)auth_len ));
00240                 return NT_STATUS_BUFFER_TOO_SMALL;
00241         }
00242 
00243         /*
00244          * We need the full packet data + length (minus auth stuff) as well as the packet data + length
00245          * after the RPC header.
00246          * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
00247          * functions as NTLMv2 checks the rpc headers also.
00248          */
00249 
00250         data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
00251         data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
00252 
00253         full_packet_data = (unsigned char *)prs_data_p(current_pdu);
00254         full_packet_data_len = prhdr->frag_len - auth_len;
00255 
00256         /* Pull the auth header and the following data into a blob. */
00257         if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
00258                 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
00259                         (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
00260                 return NT_STATUS_BUFFER_TOO_SMALL;
00261         }
00262 
00263         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
00264                 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
00265                 return NT_STATUS_BUFFER_TOO_SMALL;
00266         }
00267 
00268         auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
00269         auth_blob.length = auth_len;
00270 
00271         switch (cli->auth.auth_level) {
00272                 case PIPE_AUTH_LEVEL_PRIVACY:
00273                         /* Data is encrypted. */
00274                         status = ntlmssp_unseal_packet(ntlmssp_state,
00275                                                         data, data_len,
00276                                                         full_packet_data,
00277                                                         full_packet_data_len,
00278                                                         &auth_blob);
00279                         if (!NT_STATUS_IS_OK(status)) {
00280                                 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
00281                                         "packet from remote machine %s on pipe %s "
00282                                         "fnum 0x%x. Error was %s.\n",
00283                                         cli->cli->desthost,
00284                                         cli->pipe_name,
00285                                         (unsigned int)cli->fnum,
00286                                         nt_errstr(status) ));
00287                                 return status;
00288                         }
00289                         break;
00290                 case PIPE_AUTH_LEVEL_INTEGRITY:
00291                         /* Data is signed. */
00292                         status = ntlmssp_check_packet(ntlmssp_state,
00293                                                         data, data_len,
00294                                                         full_packet_data,
00295                                                         full_packet_data_len,
00296                                                         &auth_blob);
00297                         if (!NT_STATUS_IS_OK(status)) {
00298                                 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
00299                                         "packet from remote machine %s on pipe %s "
00300                                         "fnum 0x%x. Error was %s.\n",
00301                                         cli->cli->desthost,
00302                                         cli->pipe_name,
00303                                         (unsigned int)cli->fnum,
00304                                         nt_errstr(status) ));
00305                                 return status;
00306                         }
00307                         break;
00308                 default:
00309                         DEBUG(0,("cli_pipe_verify_ntlmssp: unknown internal auth level %d\n",
00310                                 cli->auth.auth_level ));
00311                         return NT_STATUS_INVALID_INFO_CLASS;
00312         }
00313 
00314         /*
00315          * Return the current pointer to the data offset.
00316          */
00317 
00318         if(!prs_set_offset(current_pdu, save_offset)) {
00319                 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
00320                         (unsigned int)save_offset ));
00321                 return NT_STATUS_BUFFER_TOO_SMALL;
00322         }
00323 
00324         /*
00325          * Remember the padding length. We must remove it from the real data
00326          * stream once the sign/seal is done.
00327          */
00328 
00329         *p_ss_padding_len = auth_info.auth_pad_len;
00330 
00331         return NT_STATUS_OK;
00332 }
00333 
00334 /****************************************************************************
00335  schannel specific sign/seal.
00336  ****************************************************************************/
00337 
00338 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
00339                                 prs_struct *current_pdu,
00340                                 uint8 *p_ss_padding_len)
00341 {
00342         RPC_HDR_AUTH auth_info;
00343         RPC_AUTH_SCHANNEL_CHK schannel_chk;
00344         uint32 auth_len = prhdr->auth_len;
00345         uint32 save_offset = prs_offset(current_pdu);
00346         struct schannel_auth_struct *schannel_auth = cli->auth.a_u.schannel_auth;
00347         uint32 data_len;
00348 
00349         if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
00350                 return NT_STATUS_OK;
00351         }
00352 
00353         if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
00354                 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
00355                 return NT_STATUS_INVALID_PARAMETER;
00356         }
00357 
00358         if (!schannel_auth) {
00359                 return NT_STATUS_INVALID_PARAMETER;
00360         }
00361 
00362         /* Ensure there's enough data for an authenticated response. */
00363         if ((auth_len > RPC_MAX_SIGN_SIZE) ||
00364                         (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
00365                 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
00366                         (unsigned int)auth_len ));
00367                 return NT_STATUS_INVALID_PARAMETER;
00368         }
00369 
00370         data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
00371 
00372         if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
00373                 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
00374                         (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
00375                 return NT_STATUS_BUFFER_TOO_SMALL;
00376         }
00377                                                                                                                              
00378         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
00379                 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
00380                 return NT_STATUS_BUFFER_TOO_SMALL;
00381         }
00382 
00383         if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
00384                 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
00385                         auth_info.auth_type));
00386                 return NT_STATUS_BUFFER_TOO_SMALL;
00387         }
00388 
00389         if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
00390                                 &schannel_chk, current_pdu, 0)) {
00391                 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
00392                 return NT_STATUS_BUFFER_TOO_SMALL;
00393         }
00394 
00395         if (!schannel_decode(schannel_auth,
00396                         cli->auth.auth_level,
00397                         SENDER_IS_ACCEPTOR,
00398                         &schannel_chk,
00399                         prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
00400                         data_len)) {
00401                 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
00402                                 "Connection to remote machine %s "
00403                                 "pipe %s fnum 0x%x.\n",
00404                                 cli->cli->desthost,
00405                                 cli->pipe_name,
00406                                 (unsigned int)cli->fnum ));
00407                 return NT_STATUS_INVALID_PARAMETER;
00408         }
00409 
00410         /* The sequence number gets incremented on both send and receive. */
00411         schannel_auth->seq_num++;
00412 
00413         /*
00414          * Return the current pointer to the data offset.
00415          */
00416 
00417         if(!prs_set_offset(current_pdu, save_offset)) {
00418                 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
00419                         (unsigned int)save_offset ));
00420                 return NT_STATUS_BUFFER_TOO_SMALL;
00421         }
00422 
00423         /*
00424          * Remember the padding length. We must remove it from the real data
00425          * stream once the sign/seal is done.
00426          */
00427 
00428         *p_ss_padding_len = auth_info.auth_pad_len;
00429 
00430         return NT_STATUS_OK;
00431 }
00432 
00433 /****************************************************************************
00434  Do the authentication checks on an incoming pdu. Check sign and unseal etc.
00435  ****************************************************************************/
00436 
00437 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
00438                                 prs_struct *current_pdu,
00439                                 uint8 *p_ss_padding_len)
00440 {
00441         NTSTATUS ret = NT_STATUS_OK;
00442 
00443         /* Paranioa checks for auth_len. */
00444         if (prhdr->auth_len) {
00445                 if (prhdr->auth_len > prhdr->frag_len) {
00446                         return NT_STATUS_INVALID_PARAMETER;
00447                 }
00448 
00449                 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
00450                                 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
00451                         /* Integer wrap attempt. */
00452                         return NT_STATUS_INVALID_PARAMETER;
00453                 }
00454         }
00455 
00456         /*
00457          * Now we have a complete RPC request PDU fragment, try and verify any auth data.
00458          */
00459 
00460         switch(cli->auth.auth_type) {
00461                 case PIPE_AUTH_TYPE_NONE:
00462                         if (prhdr->auth_len) {
00463                                 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
00464                                         "pipe %s fnum 0x%x - got non-zero auth len %u.\n",
00465                                         cli->cli->desthost,
00466                                         cli->pipe_name,
00467                                         (unsigned int)cli->fnum,
00468                                         (unsigned int)prhdr->auth_len ));
00469                                 return NT_STATUS_INVALID_PARAMETER;
00470                         }
00471                         break;
00472 
00473                 case PIPE_AUTH_TYPE_NTLMSSP:
00474                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
00475                         ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
00476                         if (!NT_STATUS_IS_OK(ret)) {
00477                                 return ret;
00478                         }
00479                         break;
00480 
00481                 case PIPE_AUTH_TYPE_SCHANNEL:
00482                         ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
00483                         if (!NT_STATUS_IS_OK(ret)) {
00484                                 return ret;
00485                         }
00486                         break;
00487 
00488                 case PIPE_AUTH_TYPE_KRB5:
00489                 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
00490                 default:
00491                         DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
00492                                 "pipe %s fnum %x - unknown internal auth type %u.\n",
00493                                 cli->cli->desthost,
00494                                 cli->pipe_name,
00495                                 (unsigned int)cli->fnum,
00496                                 cli->auth.auth_type ));
00497                         return NT_STATUS_INVALID_INFO_CLASS;
00498         }
00499 
00500         return NT_STATUS_OK;
00501 }
00502 
00503 /****************************************************************************
00504  Do basic authentication checks on an incoming pdu.
00505  ****************************************************************************/
00506 
00507 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
00508                         prs_struct *current_pdu,
00509                         uint8 expected_pkt_type,
00510                         char **ppdata,
00511                         uint32 *pdata_len,
00512                         prs_struct *return_data)
00513 {
00514 
00515         NTSTATUS ret = NT_STATUS_OK;
00516         uint32 current_pdu_len = prs_data_size(current_pdu);
00517 
00518         if (current_pdu_len != prhdr->frag_len) {
00519                 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
00520                         (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
00521                 return NT_STATUS_INVALID_PARAMETER;
00522         }
00523 
00524         /*
00525          * Point the return values at the real data including the RPC
00526          * header. Just in case the caller wants it.
00527          */
00528         *ppdata = prs_data_p(current_pdu);
00529         *pdata_len = current_pdu_len;
00530 
00531         /* Ensure we have the correct type. */
00532         switch (prhdr->pkt_type) {
00533                 case RPC_ALTCONTRESP:
00534                 case RPC_BINDACK:
00535 
00536                         /* Alter context and bind ack share the same packet definitions. */
00537                         break;
00538 
00539 
00540                 case RPC_RESPONSE:
00541                 {
00542                         RPC_HDR_RESP rhdr_resp;
00543                         uint8 ss_padding_len = 0;
00544 
00545                         if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
00546                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
00547                                 return NT_STATUS_BUFFER_TOO_SMALL;
00548                         }
00549 
00550                         /* Here's where we deal with incoming sign/seal. */
00551                         ret = cli_pipe_validate_rpc_response(cli, prhdr,
00552                                         current_pdu, &ss_padding_len);
00553                         if (!NT_STATUS_IS_OK(ret)) {
00554                                 return ret;
00555                         }
00556 
00557                         /* Point the return values at the NDR data. Remember to remove any ss padding. */
00558                         *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
00559 
00560                         if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
00561                                 return NT_STATUS_BUFFER_TOO_SMALL;
00562                         }
00563 
00564                         *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
00565 
00566                         /* Remember to remove the auth footer. */
00567                         if (prhdr->auth_len) {
00568                                 /* We've already done integer wrap tests on auth_len in
00569                                         cli_pipe_validate_rpc_response(). */
00570                                 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
00571                                         return NT_STATUS_BUFFER_TOO_SMALL;
00572                                 }
00573                                 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
00574                         }
00575 
00576                         DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
00577                                 current_pdu_len, *pdata_len, ss_padding_len ));
00578 
00579                         /*
00580                          * If this is the first reply, and the allocation hint is reasonably, try and
00581                          * set up the return_data parse_struct to the correct size.
00582                          */
00583 
00584                         if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
00585                                 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
00586                                         DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
00587                                                 "too large to allocate\n",
00588                                                 (unsigned int)rhdr_resp.alloc_hint ));
00589                                         return NT_STATUS_NO_MEMORY;
00590                                 }
00591                         }
00592 
00593                         break;
00594                 }
00595 
00596                 case RPC_BINDNACK:
00597                         DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK received from remote machine %s "
00598                                 "pipe %s fnum 0x%x!\n",
00599                                 cli->cli->desthost,
00600                                 cli->pipe_name,
00601                                 (unsigned int)cli->fnum));
00602                         /* Use this for now... */
00603                         return NT_STATUS_NETWORK_ACCESS_DENIED;
00604 
00605                 case RPC_FAULT:
00606                 {
00607                         RPC_HDR_RESP rhdr_resp;
00608                         RPC_HDR_FAULT fault_resp;
00609 
00610                         if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
00611                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
00612                                 return NT_STATUS_BUFFER_TOO_SMALL;
00613                         }
00614 
00615                         if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
00616                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
00617                                 return NT_STATUS_BUFFER_TOO_SMALL;
00618                         }
00619 
00620                         DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault code %s received from remote machine %s "
00621                                 "pipe %s fnum 0x%x!\n",
00622                                 dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
00623                                 cli->cli->desthost,
00624                                 cli->pipe_name,
00625                                 (unsigned int)cli->fnum));
00626                         if (NT_STATUS_IS_OK(fault_resp.status)) {
00627                                 return NT_STATUS_UNSUCCESSFUL;
00628                         } else {
00629                                 return fault_resp.status;
00630                         }
00631                         
00632                 }
00633 
00634                 default:
00635                         DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
00636                                 "from remote machine %s pipe %s fnum 0x%x!\n",
00637                                 (unsigned int)prhdr->pkt_type,
00638                                 cli->cli->desthost,
00639                                 cli->pipe_name,
00640                                 (unsigned int)cli->fnum));
00641                         return NT_STATUS_INVALID_INFO_CLASS;
00642         }
00643 
00644         if (prhdr->pkt_type != expected_pkt_type) {
00645                 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to remote machine %s "
00646                         "pipe %s fnum %x got an unexpected RPC packet "
00647                         "type - %u, not %u\n",
00648                         cli->cli->desthost,
00649                         cli->pipe_name,
00650                         (unsigned int)cli->fnum,
00651                         prhdr->pkt_type,
00652                         expected_pkt_type));
00653                 return NT_STATUS_INVALID_INFO_CLASS;
00654         }
00655 
00656         /* Do this just before return - we don't want to modify any rpc header
00657            data before now as we may have needed to do cryptographic actions on
00658            it before. */
00659 
00660         if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
00661                 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
00662                         "setting fragment first/last ON.\n"));
00663                 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
00664         }
00665 
00666         return NT_STATUS_OK;
00667 }
00668 
00669 /****************************************************************************
00670  Ensure we eat the just processed pdu from the current_pdu prs_struct.
00671  Normally the frag_len and buffer size will match, but on the first trans
00672  reply there is a theoretical chance that buffer size > frag_len, so we must
00673  deal with that.
00674  ****************************************************************************/
00675 
00676 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
00677 {
00678         uint32 current_pdu_len = prs_data_size(current_pdu);
00679 
00680         if (current_pdu_len < prhdr->frag_len) {
00681                 return NT_STATUS_BUFFER_TOO_SMALL;
00682         }
00683 
00684         /* Common case. */
00685         if (current_pdu_len == (uint32)prhdr->frag_len) {
00686                 prs_mem_free(current_pdu);
00687                 prs_init(current_pdu, 0, prs_get_mem_context(current_pdu), UNMARSHALL);
00688                 /* Make current_pdu dynamic with no memory. */
00689                 prs_give_memory(current_pdu, 0, 0, True);
00690                 return NT_STATUS_OK;
00691         }
00692 
00693         /*
00694          * Oh no ! More data in buffer than we processed in current pdu.
00695          * Cheat. Move the data down and shrink the buffer.
00696          */
00697 
00698         memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
00699                         current_pdu_len - prhdr->frag_len);
00700 
00701         /* Remember to set the read offset back to zero. */
00702         prs_set_offset(current_pdu, 0);
00703 
00704         /* Shrink the buffer. */
00705         if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
00706                 return NT_STATUS_BUFFER_TOO_SMALL;
00707         }
00708 
00709         return NT_STATUS_OK;
00710 }
00711 
00712 /****************************************************************************
00713  Send data on an rpc pipe via trans. The prs_struct data must be the last
00714  pdu fragment of an NDR data stream.
00715 
00716  Receive response data from an rpc pipe, which may be large...
00717 
00718  Read the first fragment: unfortunately have to use SMBtrans for the first
00719  bit, then SMBreadX for subsequent bits.
00720 
00721  If first fragment received also wasn't the last fragment, continue
00722  getting fragments until we _do_ receive the last fragment.
00723 
00724  Request/Response PDU's look like the following...
00725 
00726  |<------------------PDU len----------------------------------------------->|
00727  |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
00728 
00729  +------------+-----------------+-------------+---------------+-------------+
00730  | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR      | AUTH DATA   |
00731  +------------+-----------------+-------------+---------------+-------------+
00732 
00733  Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
00734  signing & sealing being negotiated.
00735 
00736  ****************************************************************************/
00737 
00738 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
00739                         prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
00740                         prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
00741                         uint8 expected_pkt_type)
00742 {
00743         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
00744         char *rparam = NULL;
00745         uint32 rparam_len = 0;
00746         uint16 setup[2];
00747         char *pdata = prs_data_p(data);
00748         uint32 data_len = prs_offset(data);
00749         char *prdata = NULL;
00750         uint32 rdata_len = 0;
00751         uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
00752         uint32 current_rbuf_offset = 0;
00753         prs_struct current_pdu;
00754         
00755 #ifdef DEVELOPER
00756         /* Ensure we're not sending too much. */
00757         SMB_ASSERT(data_len <= max_data);
00758 #endif
00759 
00760         /* Set up the current pdu parse struct. */
00761         prs_init(&current_pdu, 0, prs_get_mem_context(rbuf), UNMARSHALL);
00762 
00763         /* Create setup parameters - must be in native byte order. */
00764         setup[0] = TRANSACT_DCERPCCMD; 
00765         setup[1] = cli->fnum; /* Pipe file handle. */
00766 
00767         DEBUG(5,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x\n",
00768                 cli->cli->desthost,
00769                 cli->pipe_name,
00770                 (unsigned int)cli->fnum ));
00771 
00772         /*
00773          * Send the last (or only) fragment of an RPC request. For small
00774          * amounts of data (about 1024 bytes or so) the RPC request and response
00775          * appears in a SMBtrans request and response.
00776          */
00777 
00778         if (!cli_api_pipe(cli->cli, "\\PIPE\\",
00779                   setup, 2, 0,                     /* Setup, length, max */
00780                   NULL, 0, 0,                      /* Params, length, max */
00781                   pdata, data_len, max_data,       /* data, length, max */
00782                   &rparam, &rparam_len,            /* return params, len */
00783                   &prdata, &rdata_len))            /* return data, len */
00784         {
00785                 DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x"
00786                         "returned critical error. Error was %s\n",
00787                         cli->cli->desthost,
00788                         cli->pipe_name,
00789                         (unsigned int)cli->fnum,
00790                         cli_errstr(cli->cli)));
00791                 ret = cli_get_nt_error(cli->cli);
00792                 SAFE_FREE(rparam);
00793                 SAFE_FREE(prdata);
00794                 goto err;
00795         }
00796 
00797         /* Throw away returned params - we know we won't use them. */
00798 
00799         SAFE_FREE(rparam);
00800 
00801         if (prdata == NULL) {
00802                 DEBUG(3,("rpc_api_pipe: Remote machine %s pipe %s "
00803                         "fnum 0x%x failed to return data.\n",
00804                         cli->cli->desthost,
00805                         cli->pipe_name,
00806                         (unsigned int)cli->fnum));
00807                 /* Yes - some calls can truely return no data... */
00808                 prs_mem_free(&current_pdu);
00809                 return NT_STATUS_OK;
00810         }
00811 
00812         /*
00813          * Give this memory as dynamic to the current pdu.
00814          */
00815 
00816         prs_give_memory(&current_pdu, prdata, rdata_len, True);
00817 
00818         /* Ensure we can mess with the return prs_struct. */
00819         SMB_ASSERT(UNMARSHALLING(rbuf));
00820         SMB_ASSERT(prs_data_size(rbuf) == 0);
00821 
00822         /* Make rbuf dynamic with no memory. */
00823         prs_give_memory(rbuf, 0, 0, True);
00824 
00825         while(1) {
00826                 RPC_HDR rhdr;
00827                 char *ret_data;
00828                 uint32 ret_data_len;
00829 
00830                 /* Ensure we have enough data for a pdu. */
00831                 ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
00832                 if (!NT_STATUS_IS_OK(ret)) {
00833                         goto err;
00834                 }
00835 
00836                 /* We pass in rbuf here so if the alloc hint is set correctly 
00837                    we can set the output size and avoid reallocs. */
00838 
00839                 ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
00840                                 &ret_data, &ret_data_len, rbuf);
00841 
00842                 DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
00843                         prs_data_size(&current_pdu), current_rbuf_offset ));
00844 
00845                 if (!NT_STATUS_IS_OK(ret)) {
00846                         goto err;
00847                 }
00848 
00849                 if ((rhdr.flags & RPC_FLG_FIRST)) {
00850                         if (rhdr.pack_type[0] == 0) {
00851                                 /* Set the data type correctly for big-endian data on the first packet. */
00852                                 DEBUG(10,("rpc_api_pipe: On machine %s pipe %s fnum 0x%x "
00853                                         "PDU data format is big-endian.\n",
00854                                         cli->cli->desthost,
00855                                         cli->pipe_name,
00856                                         (unsigned int)cli->fnum));
00857 
00858                                 prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
00859                         } else {
00860                                 /* Check endianness on subsequent packets. */
00861                                 if (current_pdu.bigendian_data != rbuf->bigendian_data) {
00862                                         DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
00863                                                 rbuf->bigendian_data ? "big" : "little",
00864                                                 current_pdu.bigendian_data ? "big" : "little" ));
00865                                         ret = NT_STATUS_INVALID_PARAMETER;
00866                                         goto err;
00867                                 }
00868                         }
00869                 }
00870 
00871                 /* Now copy the data portion out of the pdu into rbuf. */
00872                 if (!prs_force_grow(rbuf, ret_data_len)) {
00873                         ret = NT_STATUS_NO_MEMORY;
00874                         goto err;
00875                 }
00876                 memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
00877                 current_rbuf_offset += ret_data_len;
00878 
00879                 /* See if we've finished with all the data in current_pdu yet ? */
00880                 ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
00881                 if (!NT_STATUS_IS_OK(ret)) {
00882                         goto err;
00883                 }
00884 
00885                 if (rhdr.flags & RPC_FLG_LAST) {
00886                         break; /* We're done. */
00887                 }
00888         }
00889 
00890         DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n",
00891                 cli->cli->desthost,
00892                 cli->pipe_name,
00893                 (unsigned int)cli->fnum,
00894                 (unsigned int)prs_data_size(rbuf) ));
00895 
00896         prs_mem_free(&current_pdu);
00897         return NT_STATUS_OK;
00898 
00899   err:
00900 
00901         prs_mem_free(&current_pdu);
00902         prs_mem_free(rbuf);
00903         return ret;
00904 }
00905 
00906 /*******************************************************************
00907  Creates krb5 auth bind.
00908  ********************************************************************/
00909 
00910 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
00911                                                 enum pipe_auth_level auth_level,
00912                                                 RPC_HDR_AUTH *pauth_out,
00913                                                 prs_struct *auth_data)
00914 {
00915 #ifdef HAVE_KRB5
00916         int ret;
00917         struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth;
00918         DATA_BLOB tkt = data_blob(NULL, 0);
00919         DATA_BLOB tkt_wrapped = data_blob(NULL, 0);
00920 
00921         /* We may change the pad length before marshalling. */
00922         init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
00923 
00924         DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
00925                 a->service_principal ));
00926 
00927         /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
00928 
00929         ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
00930                         &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
00931 
00932         if (ret) {
00933                 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
00934                         "failed with %s\n",
00935                         a->service_principal,
00936                         error_message(ret) ));
00937 
00938                 data_blob_free(&tkt);
00939                 prs_mem_free(auth_data);
00940                 return NT_STATUS_INVALID_PARAMETER;
00941         }
00942 
00943         /* wrap that up in a nice GSS-API wrapping */
00944         tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
00945 
00946         data_blob_free(&tkt);
00947 
00948         /* Auth len in the rpc header doesn't include auth_header. */
00949         if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
00950                 data_blob_free(&tkt_wrapped);
00951                 prs_mem_free(auth_data);
00952                 return NT_STATUS_NO_MEMORY;
00953         }
00954 
00955         DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
00956         dump_data(5, (const char *)tkt_wrapped.data, tkt_wrapped.length);
00957 
00958         data_blob_free(&tkt_wrapped);
00959         return NT_STATUS_OK;
00960 #else
00961         return NT_STATUS_INVALID_PARAMETER;
00962 #endif
00963 }
00964 
00965 /*******************************************************************
00966  Creates SPNEGO NTLMSSP auth bind.
00967  ********************************************************************/
00968 
00969 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
00970                                                 enum pipe_auth_level auth_level,
00971                                                 RPC_HDR_AUTH *pauth_out,
00972                                                 prs_struct *auth_data)
00973 {
00974         NTSTATUS nt_status;
00975         DATA_BLOB null_blob = data_blob(NULL, 0);
00976         DATA_BLOB request = data_blob(NULL, 0);
00977         DATA_BLOB spnego_msg = data_blob(NULL, 0);
00978 
00979         /* We may change the pad length before marshalling. */
00980         init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
00981 
00982         DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
00983         nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
00984                                         null_blob,
00985                                         &request);
00986 
00987         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
00988                 data_blob_free(&request);
00989                 prs_mem_free(auth_data);
00990                 return nt_status;
00991         }
00992 
00993         /* Wrap this in SPNEGO. */
00994         spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
00995 
00996         data_blob_free(&request);
00997 
00998         /* Auth len in the rpc header doesn't include auth_header. */
00999         if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
01000                 data_blob_free(&spnego_msg);
01001                 prs_mem_free(auth_data);
01002                 return NT_STATUS_NO_MEMORY;
01003         }
01004 
01005         DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
01006         dump_data(5, (const char *)spnego_msg.data, spnego_msg.length);
01007 
01008         data_blob_free(&spnego_msg);
01009         return NT_STATUS_OK;
01010 }
01011 
01012 /*******************************************************************
01013  Creates NTLMSSP auth bind.
01014  ********************************************************************/
01015 
01016 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
01017                                                 enum pipe_auth_level auth_level,
01018                                                 RPC_HDR_AUTH *pauth_out,
01019                                                 prs_struct *auth_data)
01020 {
01021         NTSTATUS nt_status;
01022         DATA_BLOB null_blob = data_blob(NULL, 0);
01023         DATA_BLOB request = data_blob(NULL, 0);
01024 
01025         /* We may change the pad length before marshalling. */
01026         init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
01027 
01028         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
01029         nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
01030                                         null_blob,
01031                                         &request);
01032 
01033         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
01034                 data_blob_free(&request);
01035                 prs_mem_free(auth_data);
01036                 return nt_status;
01037         }
01038 
01039         /* Auth len in the rpc header doesn't include auth_header. */
01040         if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
01041                 data_blob_free(&request);
01042                 prs_mem_free(auth_data);
01043                 return NT_STATUS_NO_MEMORY;
01044         }
01045 
01046         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
01047         dump_data(5, (const char *)request.data, request.length);
01048 
01049         data_blob_free(&request);
01050         return NT_STATUS_OK;
01051 }
01052 
01053 /*******************************************************************
01054  Creates schannel auth bind.
01055  ********************************************************************/
01056 
01057 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
01058                                                 enum pipe_auth_level auth_level,
01059                                                 RPC_HDR_AUTH *pauth_out,
01060                                                 prs_struct *auth_data)
01061 {
01062         RPC_AUTH_SCHANNEL_NEG schannel_neg;
01063 
01064         /* We may change the pad length before marshalling. */
01065         init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
01066 
01067         /* Use lp_workgroup() if domain not specified */
01068 
01069         if (!cli->domain || !cli->domain[0]) {
01070                 cli->domain = lp_workgroup();
01071         }
01072 
01073         init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname());
01074 
01075         /*
01076          * Now marshall the data into the auth parse_struct.
01077          */
01078 
01079         if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
01080                                        &schannel_neg, auth_data, 0)) {
01081                 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
01082                 prs_mem_free(auth_data);
01083                 return NT_STATUS_NO_MEMORY;
01084         }
01085 
01086         return NT_STATUS_OK;
01087 }
01088 
01089 /*******************************************************************
01090  Creates the internals of a DCE/RPC bind request or alter context PDU.
01091  ********************************************************************/
01092 
01093 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
01094                                                 prs_struct *rpc_out, 
01095                                                 uint32 rpc_call_id,
01096                                                 RPC_IFACE *abstract,
01097                                                 RPC_IFACE *transfer,
01098                                                 RPC_HDR_AUTH *phdr_auth,
01099                                                 prs_struct *pauth_info)
01100 {
01101         RPC_HDR hdr;
01102         RPC_HDR_RB hdr_rb;
01103         RPC_CONTEXT rpc_ctx;
01104         uint16 auth_len = prs_offset(pauth_info);
01105         uint8 ss_padding_len = 0;
01106         uint16 frag_len = 0;
01107 
01108         /* create the RPC context. */
01109         init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
01110 
01111         /* create the bind request RPC_HDR_RB */
01112         init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
01113 
01114         /* Start building the frag length. */
01115         frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
01116 
01117         /* Do we need to pad ? */
01118         if (auth_len) {
01119                 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
01120                 if (data_len % 8) {
01121                         ss_padding_len = 8 - (data_len % 8);
01122                         phdr_auth->auth_pad_len = ss_padding_len;
01123                 }
01124                 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
01125         }
01126 
01127         /* Create the request RPC_HDR */
01128         init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
01129 
01130         /* Marshall the RPC header */
01131         if(!smb_io_rpc_hdr("hdr"   , &hdr, rpc_out, 0)) {
01132                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
01133                 return NT_STATUS_NO_MEMORY;
01134         }
01135 
01136         /* Marshall the bind request data */
01137         if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
01138                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
01139                 return NT_STATUS_NO_MEMORY;
01140         }
01141 
01142         /*
01143          * Grow the outgoing buffer to store any auth info.
01144          */
01145 
01146         if(auth_len != 0) {
01147                 if (ss_padding_len) {
01148                         char pad[8];
01149                         memset(pad, '\0', 8);
01150                         if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
01151                                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
01152                                 return NT_STATUS_NO_MEMORY;
01153                         }
01154                 }
01155 
01156                 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
01157                         DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
01158                         return NT_STATUS_NO_MEMORY;
01159                 }
01160 
01161 
01162                 if(!prs_append_prs_data( rpc_out, pauth_info)) {
01163                         DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
01164                         return NT_STATUS_NO_MEMORY;
01165                 }
01166         }
01167 
01168         return NT_STATUS_OK;
01169 }
01170 
01171 /*******************************************************************
01172  Creates a DCE/RPC bind request.
01173  ********************************************************************/
01174 
01175 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
01176                                 prs_struct *rpc_out, 
01177                                 uint32 rpc_call_id,
01178                                 RPC_IFACE *abstract, RPC_IFACE *transfer,
01179                                 enum pipe_auth_type auth_type,
01180                                 enum pipe_auth_level auth_level)
01181 {
01182         RPC_HDR_AUTH hdr_auth;
01183         prs_struct auth_info;
01184         NTSTATUS ret = NT_STATUS_OK;
01185 
01186         ZERO_STRUCT(hdr_auth);
01187         prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
01188 
01189         switch (auth_type) {
01190                 case PIPE_AUTH_TYPE_SCHANNEL:
01191                         ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
01192                         if (!NT_STATUS_IS_OK(ret)) {
01193                                 prs_mem_free(&auth_info);
01194                                 return ret;
01195                         }
01196                         break;
01197 
01198                 case PIPE_AUTH_TYPE_NTLMSSP:
01199                         ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
01200                         if (!NT_STATUS_IS_OK(ret)) {
01201                                 prs_mem_free(&auth_info);
01202                                 return ret;
01203                         }
01204                         break;
01205 
01206                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
01207                         ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
01208                         if (!NT_STATUS_IS_OK(ret)) {
01209                                 prs_mem_free(&auth_info);
01210                                 return ret;
01211                         }
01212                         break;
01213 
01214                 case PIPE_AUTH_TYPE_KRB5:
01215                         ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
01216                         if (!NT_STATUS_IS_OK(ret)) {
01217                                 prs_mem_free(&auth_info);
01218                                 return ret;
01219                         }
01220                         break;
01221 
01222                 case PIPE_AUTH_TYPE_NONE:
01223                         break;
01224 
01225                 default:
01226                         /* "Can't" happen. */
01227                         return NT_STATUS_INVALID_INFO_CLASS;
01228         }
01229 
01230         ret = create_bind_or_alt_ctx_internal(RPC_BIND,
01231                                                 rpc_out, 
01232                                                 rpc_call_id,
01233                                                 abstract,
01234                                                 transfer,
01235                                                 &hdr_auth,
01236                                                 &auth_info);
01237 
01238         prs_mem_free(&auth_info);
01239         return ret;
01240 }
01241 
01242 /*******************************************************************
01243  Create and add the NTLMSSP sign/seal auth header and data.
01244  ********************************************************************/
01245 
01246 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
01247                                         RPC_HDR *phdr,
01248                                         uint32 ss_padding_len,
01249                                         prs_struct *outgoing_pdu)
01250 {
01251         RPC_HDR_AUTH auth_info;
01252         NTSTATUS status;
01253         DATA_BLOB auth_blob = data_blob(NULL, 0);
01254         uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
01255 
01256         if (!cli->auth.a_u.ntlmssp_state) {
01257                 return NT_STATUS_INVALID_PARAMETER;
01258         }
01259 
01260         /* Init and marshall the auth header. */
01261         init_rpc_hdr_auth(&auth_info,
01262                         map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
01263                         cli->auth.auth_level,
01264                         ss_padding_len,
01265                         1 /* context id. */);
01266 
01267         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
01268                 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
01269                 data_blob_free(&auth_blob);
01270                 return NT_STATUS_NO_MEMORY;
01271         }
01272 
01273         switch (cli->auth.auth_level) {
01274                 case PIPE_AUTH_LEVEL_PRIVACY:
01275                         /* Data portion is encrypted. */
01276                         status = ntlmssp_seal_packet(cli->auth.a_u.ntlmssp_state,
01277                                         (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
01278                                         data_and_pad_len,
01279                                         (unsigned char *)prs_data_p(outgoing_pdu),
01280                                         (size_t)prs_offset(outgoing_pdu),
01281                                         &auth_blob);
01282                         if (!NT_STATUS_IS_OK(status)) {
01283                                 data_blob_free(&auth_blob);
01284                                 return status;
01285                         }
01286                         break;
01287 
01288                 case PIPE_AUTH_LEVEL_INTEGRITY:
01289                         /* Data is signed. */
01290                         status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state,
01291                                         (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
01292                                         data_and_pad_len,
01293                                         (unsigned char *)prs_data_p(outgoing_pdu),
01294                                         (size_t)prs_offset(outgoing_pdu),
01295                                         &auth_blob);
01296                         if (!NT_STATUS_IS_OK(status)) {
01297                                 data_blob_free(&auth_blob);
01298                                 return status;
01299                         }
01300                         break;
01301 
01302                 default:
01303                         /* Can't happen. */
01304                         smb_panic("bad auth level");
01305                         /* Notreached. */
01306                         return NT_STATUS_INVALID_PARAMETER;
01307         }
01308 
01309         /* Finally marshall the blob. */
01310                                                                                                        
01311         if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
01312                 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
01313                         (unsigned int)NTLMSSP_SIG_SIZE));
01314                 data_blob_free(&auth_blob);
01315                 return NT_STATUS_NO_MEMORY;
01316         }
01317                                                                                                                                 
01318         data_blob_free(&auth_blob);
01319         return NT_STATUS_OK;
01320 }
01321 
01322 /*******************************************************************
01323  Create and add the schannel sign/seal auth header and data.
01324  ********************************************************************/
01325 
01326 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
01327                                         RPC_HDR *phdr,
01328                                         uint32 ss_padding_len,
01329                                         prs_struct *outgoing_pdu)
01330 {
01331         RPC_HDR_AUTH auth_info;
01332         RPC_AUTH_SCHANNEL_CHK verf;
01333         struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth;
01334         char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
01335         size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
01336 
01337         if (!sas) {
01338                 return NT_STATUS_INVALID_PARAMETER;
01339         }
01340 
01341         /* Init and marshall the auth header. */
01342         init_rpc_hdr_auth(&auth_info,
01343                         map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
01344                         cli->auth.auth_level,
01345                         ss_padding_len,
01346                         1 /* context id. */);
01347 
01348         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
01349                 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
01350                 return NT_STATUS_NO_MEMORY;
01351         }
01352 
01353         switch (cli->auth.auth_level) {
01354                 case PIPE_AUTH_LEVEL_PRIVACY:
01355                 case PIPE_AUTH_LEVEL_INTEGRITY:
01356                         DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
01357                                 sas->seq_num));
01358 
01359                         schannel_encode(sas,
01360                                         cli->auth.auth_level,
01361                                         SENDER_IS_INITIATOR,
01362                                         &verf,
01363                                         data_p,
01364                                         data_and_pad_len);
01365 
01366                         sas->seq_num++;
01367                         break;
01368 
01369                 default:
01370                         /* Can't happen. */
01371                         smb_panic("bad auth level");
01372                         /* Notreached. */
01373                         return NT_STATUS_INVALID_PARAMETER;
01374         }
01375 
01376         /* Finally marshall the blob. */
01377         smb_io_rpc_auth_schannel_chk("",
01378                         RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
01379                         &verf,
01380                         outgoing_pdu,
01381                         0);
01382                                                                                                
01383         return NT_STATUS_OK;
01384 }
01385 
01386 /*******************************************************************
01387  Calculate how much data we're going to send in this packet, also
01388  work out any sign/seal padding length.
01389  ********************************************************************/
01390 
01391 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
01392                                         uint32 data_left,
01393                                         uint16 *p_frag_len,
01394                                         uint16 *p_auth_len,
01395                                         uint32 *p_ss_padding)
01396 {
01397         uint32 data_space, data_len;
01398 
01399         switch (cli->auth.auth_level) {
01400                 case PIPE_AUTH_LEVEL_NONE:
01401                 case PIPE_AUTH_LEVEL_CONNECT:
01402                         data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
01403                         data_len = MIN(data_space, data_left);
01404                         *p_ss_padding = 0;
01405                         *p_auth_len = 0;
01406                         *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
01407                         return data_len;
01408 
01409                 case PIPE_AUTH_LEVEL_INTEGRITY:
01410                 case PIPE_AUTH_LEVEL_PRIVACY:
01411                         /* Treat the same for all authenticated rpc requests. */
01412                         switch(cli->auth.auth_type) {
01413                                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
01414                                 case PIPE_AUTH_TYPE_NTLMSSP:
01415                                         *p_auth_len = NTLMSSP_SIG_SIZE;
01416                                         break;
01417                                 case PIPE_AUTH_TYPE_SCHANNEL:
01418                                         *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
01419                                         break;
01420                                 default:
01421                                         smb_panic("bad auth type");
01422                                         break;
01423                         }
01424 
01425                         data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
01426                                                 RPC_HDR_AUTH_LEN - *p_auth_len;
01427 
01428                         data_len = MIN(data_space, data_left);
01429                         if (data_len % 8) {
01430                                 *p_ss_padding = 8 - (data_len % 8);
01431                         }
01432                         *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN +                /* Normal headers. */
01433                                         data_len + *p_ss_padding +              /* data plus padding. */
01434                                         RPC_HDR_AUTH_LEN + *p_auth_len;         /* Auth header and auth data. */
01435                         return data_len;
01436 
01437                 default:
01438                         smb_panic("bad auth level");
01439                         /* Notreached. */
01440                         return 0;
01441         }
01442 }
01443 
01444 /*******************************************************************
01445  External interface.
01446  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
01447  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
01448  and deals with signing/sealing details.
01449  ********************************************************************/
01450 
01451 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
01452                         uint8 op_num,
01453                         prs_struct *in_data,
01454                         prs_struct *out_data)
01455 {
01456         NTSTATUS ret;
01457         uint32 data_left = prs_offset(in_data);
01458         uint32 alloc_hint = prs_offset(in_data);
01459         uint32 data_sent_thistime = 0;
01460         uint32 current_data_offset = 0;
01461         uint32 call_id = get_rpc_call_id();
01462         char pad[8];
01463         prs_struct outgoing_pdu;
01464 
01465         memset(pad, '\0', 8);
01466 
01467         if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
01468                 /* Server is screwed up ! */
01469                 return NT_STATUS_INVALID_PARAMETER;
01470         }
01471 
01472         prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL);
01473 
01474         while (1) {
01475                 RPC_HDR hdr;
01476                 RPC_HDR_REQ hdr_req;
01477                 uint16 auth_len = 0;
01478                 uint16 frag_len = 0;
01479                 uint8 flags = 0;
01480                 uint32 ss_padding = 0;
01481 
01482                 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
01483                                                 &frag_len, &auth_len, &ss_padding);
01484 
01485                 if (current_data_offset == 0) {
01486                         flags = RPC_FLG_FIRST;
01487                 }
01488 
01489                 if (data_sent_thistime == data_left) {
01490                         flags |= RPC_FLG_LAST;
01491                 }
01492 
01493                 /* Create and marshall the header and request header. */
01494                 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
01495 
01496                 if(!smb_io_rpc_hdr("hdr    ", &hdr, &outgoing_pdu, 0)) {
01497                         prs_mem_free(&outgoing_pdu);
01498                         return NT_STATUS_NO_MEMORY;
01499                 }
01500 
01501                 /* Create the rpc request RPC_HDR_REQ */
01502                 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
01503 
01504                 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
01505                         prs_mem_free(&outgoing_pdu);
01506                         return NT_STATUS_NO_MEMORY;
01507                 }
01508 
01509                 /* Copy in the data, plus any ss padding. */
01510                 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
01511                         prs_mem_free(&outgoing_pdu);
01512                         return NT_STATUS_NO_MEMORY;
01513                 }
01514 
01515                 /* Copy the sign/seal padding data. */
01516                 if (ss_padding) {
01517                         if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
01518                                 prs_mem_free(&outgoing_pdu);
01519                                 return NT_STATUS_NO_MEMORY;
01520                         }
01521                 }
01522 
01523                 /* Generate any auth sign/seal and add the auth footer. */
01524                 if (auth_len) {
01525                         switch (cli->auth.auth_type) {
01526                                 case PIPE_AUTH_TYPE_NONE:
01527                                         break;
01528                                 case PIPE_AUTH_TYPE_NTLMSSP:
01529                                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
01530                                         ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
01531                                         if (!NT_STATUS_IS_OK(ret)) {
01532                                                 prs_mem_free(&outgoing_pdu);
01533                                                 return ret;
01534                                         }
01535                                         break;
01536                                 case PIPE_AUTH_TYPE_SCHANNEL:
01537                                         ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
01538                                         if (!NT_STATUS_IS_OK(ret)) {
01539                                                 prs_mem_free(&outgoing_pdu);
01540                                                 return ret;
01541                                         }
01542                                         break;
01543                                 default:
01544                                         smb_panic("bad auth type");
01545                                         break; /* notreached */
01546                         }
01547                 }
01548 
01549                 /* Actually send the packet. */
01550                 if (flags & RPC_FLG_LAST) {
01551                         /* Last packet - send the data, get the reply and return. */
01552                         ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
01553                         prs_mem_free(&outgoing_pdu);
01554 
01555                         
01556                         if (DEBUGLEVEL >= 50) {
01557                                 pstring dump_name;
01558                                 /* Also capture received data */
01559                                 slprintf(dump_name, sizeof(dump_name) - 1, "%s/reply_%s_%d",
01560                                         dyn_LOGFILEBASE, cli->pipe_name, op_num);
01561                                 prs_dump(dump_name, op_num, out_data);
01562                         }
01563 
01564                         return ret;
01565                 } else {
01566                         /* More packets to come - write and continue. */
01567                         ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */
01568                                                         prs_data_p(&outgoing_pdu),
01569                                                         (off_t)0,
01570                                                         (size_t)hdr.frag_len);
01571 
01572                         if (num_written != hdr.frag_len) {
01573                                 prs_mem_free(&outgoing_pdu);
01574                                 return cli_get_nt_error(cli->cli);
01575                         }
01576                 }
01577 
01578                 current_data_offset += data_sent_thistime;
01579                 data_left -= data_sent_thistime;
01580 
01581                 /* Reset the marshalling position back to zero. */
01582                 if (!prs_set_offset(&outgoing_pdu, 0)) {
01583                         prs_mem_free(&outgoing_pdu);
01584                         return NT_STATUS_NO_MEMORY;
01585                 }
01586         }
01587 }
01588 #if 0
01589 /****************************************************************************
01590  Set the handle state.
01591 ****************************************************************************/
01592 
01593 static BOOL rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
01594                                    const char *pipe_name, uint16 device_state)
01595 {
01596         BOOL state_set = False;
01597         char param[2];
01598         uint16 setup[2]; /* only need 2 uint16 setup parameters */
01599         char *rparam = NULL;
01600         char *rdata = NULL;
01601         uint32 rparam_len, rdata_len;
01602 
01603         if (pipe_name == NULL)
01604                 return False;
01605 
01606         DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
01607                  cli->fnum, pipe_name, device_state));
01608 
01609         /* create parameters: device state */
01610         SSVAL(param, 0, device_state);
01611 
01612         /* create setup parameters. */
01613         setup[0] = 0x0001; 
01614         setup[1] = cli->fnum; /* pipe file handle.  got this from an SMBOpenX. */
01615 
01616         /* send the data on \PIPE\ */
01617         if (cli_api_pipe(cli->cli, "\\PIPE\\",
01618                     setup, 2, 0,                /* setup, length, max */
01619                     param, 2, 0,                /* param, length, max */
01620                     NULL, 0, 1024,              /* data, length, max */
01621                     &rparam, &rparam_len,        /* return param, length */
01622                     &rdata, &rdata_len))         /* return data, length */
01623         {
01624                 DEBUG(5, ("Set Handle state: return OK\n"));
01625                 state_set = True;
01626         }
01627 
01628         SAFE_FREE(rparam);
01629         SAFE_FREE(rdata);
01630 
01631         return state_set;
01632 }
01633 #endif
01634 
01635 /****************************************************************************
01636  Check the rpc bind acknowledge response.
01637 ****************************************************************************/
01638 
01639 static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *transfer)
01640 {
01641         if ( pipe_idx >= PI_MAX_PIPES ) {
01642                 DEBUG(0,("valid_pipe_name: Programmer error!  Invalid pipe index [%d]\n",
01643                         pipe_idx));
01644                 return False;
01645         }
01646 
01647         DEBUG(5,("Bind Abstract Syntax: "));    
01648         dump_data(5, (char*)&pipe_names[pipe_idx].abstr_syntax, 
01649                   sizeof(pipe_names[pipe_idx].abstr_syntax));
01650         DEBUG(5,("Bind Transfer Syntax: "));
01651         dump_data(5, (char*)&pipe_names[pipe_idx].trans_syntax,
01652                   sizeof(pipe_names[pipe_idx].trans_syntax));
01653 
01654         /* copy the required syntaxes out so we can do the right bind */
01655         
01656         *transfer = pipe_names[pipe_idx].trans_syntax;
01657         *abstract = pipe_names[pipe_idx].abstr_syntax;
01658 
01659         return True;
01660 }
01661 
01662 /****************************************************************************
01663  Check the rpc bind acknowledge response.
01664 ****************************************************************************/
01665 
01666 static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer)
01667 {
01668         if ( hdr_ba->addr.len == 0) {
01669                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
01670         }
01671 
01672 # if 0  /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
01673         if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&
01674              !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )
01675         {
01676                 DEBUG(4,("bind_rpc_pipe: pipe_name %s != expected pipe %s.  oh well!\n",
01677                          pipe_names[i].server_pipe ,hdr_ba->addr.str));
01678                 return False;
01679         }
01680         
01681         DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n", pipe_names[i].server_pipe ));
01682 
01683         if (pipe_names[pipe_idx].server_pipe == NULL) {
01684                 DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
01685                 return False;
01686         }
01687 #endif  /* JERRY */
01688 
01689         /* check the transfer syntax */
01690         if ((hdr_ba->transfer.version != transfer->version) ||
01691              (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
01692                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
01693                 return False;
01694         }
01695 
01696         if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
01697                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
01698                           hdr_ba->res.num_results, hdr_ba->res.reason));
01699         }
01700 
01701         DEBUG(5,("check_bind_response: accepted!\n"));
01702         return True;
01703 }
01704 
01705 /*******************************************************************
01706  Creates a DCE/RPC bind authentication response.
01707  This is the packet that is sent back to the server once we
01708  have received a BIND-ACK, to finish the third leg of
01709  the authentication handshake.
01710  ********************************************************************/
01711 
01712 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
01713                                 uint32 rpc_call_id,
01714                                 enum pipe_auth_type auth_type,
01715                                 enum pipe_auth_level auth_level,
01716                                 DATA_BLOB *pauth_blob,
01717                                 prs_struct *rpc_out)
01718 {
01719         RPC_HDR hdr;
01720         RPC_HDR_AUTH hdr_auth;
01721         uint32 pad = 0;
01722 
01723         /* Create the request RPC_HDR */
01724         init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
01725                      RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
01726                      pauth_blob->length );
01727         
01728         /* Marshall it. */
01729         if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
01730                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
01731                 return NT_STATUS_NO_MEMORY;
01732         }
01733 
01734         /*
01735                 I'm puzzled about this - seems to violate the DCE RPC auth rules,
01736                 about padding - shouldn't this pad to length 8 ? JRA.
01737         */
01738 
01739         /* 4 bytes padding. */
01740         if (!prs_uint32("pad", rpc_out, 0, &pad)) {
01741                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
01742                 return NT_STATUS_NO_MEMORY;
01743         }
01744 
01745         /* Create the request RPC_HDR_AUTHA */
01746         init_rpc_hdr_auth(&hdr_auth,
01747                         map_pipe_auth_type_to_rpc_auth_type(auth_type),
01748                         auth_level, 0, 1);
01749 
01750         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
01751                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
01752                 return NT_STATUS_NO_MEMORY;
01753         }
01754 
01755         /*
01756          * Append the auth data to the outgoing buffer.
01757          */
01758 
01759         if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
01760                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
01761                 return NT_STATUS_NO_MEMORY;
01762         }
01763 
01764         return NT_STATUS_OK;
01765 }
01766 
01767 /****************************************************************************
01768  Create and send the third packet in an RPC auth.
01769 ****************************************************************************/
01770 
01771 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
01772                                 RPC_HDR *phdr,
01773                                 prs_struct *rbuf,
01774                                 uint32 rpc_call_id,
01775                                 enum pipe_auth_type auth_type,
01776                                 enum pipe_auth_level auth_level)
01777 {
01778         DATA_BLOB server_response = data_blob(NULL,0);
01779         DATA_BLOB client_reply = data_blob(NULL,0);
01780         RPC_HDR_AUTH hdr_auth;
01781         NTSTATUS nt_status;
01782         prs_struct rpc_out;
01783         ssize_t ret;
01784 
01785         if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
01786                 return NT_STATUS_INVALID_PARAMETER;
01787         }
01788 
01789         /* Process the returned NTLMSSP blob first. */
01790         if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
01791                 return NT_STATUS_INVALID_PARAMETER;
01792         }
01793 
01794         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
01795                 return NT_STATUS_INVALID_PARAMETER;
01796         }
01797 
01798         /* TODO - check auth_type/auth_level match. */
01799 
01800         server_response = data_blob(NULL, phdr->auth_len);
01801         prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
01802         
01803         nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
01804                                    server_response,
01805                                    &client_reply);
01806         
01807         if (!NT_STATUS_IS_OK(nt_status)) {
01808                 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
01809                 data_blob_free(&server_response);
01810                 return nt_status;
01811         }
01812 
01813         prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
01814 
01815         nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
01816                                 auth_type, auth_level,
01817                                 &client_reply, &rpc_out);
01818 
01819         if (!NT_STATUS_IS_OK(nt_status)) {
01820                 prs_mem_free(&rpc_out);
01821                 data_blob_free(&client_reply);
01822                 data_blob_free(&server_response);
01823                 return nt_status;
01824         }
01825 
01826         /* 8 here is named pipe message mode. */
01827         ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 0,
01828                                 (size_t)prs_offset(&rpc_out));
01829 
01830         if (ret != (ssize_t)prs_offset(&rpc_out)) {
01831                 DEBUG(0,("rpc_send_auth_auth3: cli_write failed. Return was %d\n", (int)ret));
01832                 prs_mem_free(&rpc_out);
01833                 data_blob_free(&client_reply);
01834                 data_blob_free(&server_response);
01835                 return cli_get_nt_error(cli->cli);
01836         }
01837 
01838         DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s "
01839                 "fnum 0x%x sent auth3 response ok.\n",
01840                 cli->cli->desthost,
01841                 cli->pipe_name,
01842                 (unsigned int)cli->fnum));
01843 
01844         prs_mem_free(&rpc_out);
01845         data_blob_free(&client_reply);
01846         data_blob_free(&server_response);
01847         return NT_STATUS_OK;
01848 }
01849 
01850 /*******************************************************************
01851  Creates a DCE/RPC bind alter context authentication request which
01852  may contain a spnego auth blobl
01853  ********************************************************************/
01854 
01855 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
01856                                         RPC_IFACE *abstract,
01857                                         RPC_IFACE *transfer,
01858                                         enum pipe_auth_level auth_level,
01859                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
01860                                         prs_struct *rpc_out)
01861 {
01862         RPC_HDR_AUTH hdr_auth;
01863         prs_struct auth_info;
01864         NTSTATUS ret = NT_STATUS_OK;
01865 
01866         ZERO_STRUCT(hdr_auth);
01867         prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
01868 
01869         /* We may change the pad length before marshalling. */
01870         init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
01871 
01872         if (pauth_blob->length) {
01873                 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
01874                         prs_mem_free(&auth_info);
01875                         return NT_STATUS_NO_MEMORY;
01876                 }
01877         }
01878 
01879         ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
01880                                                 rpc_out, 
01881                                                 rpc_call_id,
01882                                                 abstract,
01883                                                 transfer,
01884                                                 &hdr_auth,
01885                                                 &auth_info);
01886         prs_mem_free(&auth_info);
01887         return ret;
01888 }
01889 
01890 /*******************************************************************
01891  Third leg of the SPNEGO bind mechanism - sends alter context PDU
01892  and gets a response.
01893  ********************************************************************/
01894 
01895 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
01896                                 RPC_HDR *phdr,
01897                                 prs_struct *rbuf,
01898                                 uint32 rpc_call_id,
01899                                 RPC_IFACE *abstract,
01900                                 RPC_IFACE *transfer,
01901                                 enum pipe_auth_type auth_type,
01902                                 enum pipe_auth_level auth_level)
01903 {
01904         DATA_BLOB server_spnego_response = data_blob(NULL,0);
01905         DATA_BLOB server_ntlm_response = data_blob(NULL,0);
01906         DATA_BLOB client_reply = data_blob(NULL,0);
01907         DATA_BLOB tmp_blob = data_blob(NULL, 0);
01908         RPC_HDR_AUTH hdr_auth;
01909         NTSTATUS nt_status;
01910         prs_struct rpc_out;
01911 
01912         if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
01913                 return NT_STATUS_INVALID_PARAMETER;
01914         }
01915 
01916         /* Process the returned NTLMSSP blob first. */
01917         if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
01918                 return NT_STATUS_INVALID_PARAMETER;
01919         }
01920 
01921         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
01922                 return NT_STATUS_INVALID_PARAMETER;
01923         }
01924 
01925         server_spnego_response = data_blob(NULL, phdr->auth_len);
01926         prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
01927         
01928         /* The server might give us back two challenges - tmp_blob is for the second. */
01929         if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
01930                 data_blob_free(&server_spnego_response);
01931                 data_blob_free(&server_ntlm_response);
01932                 data_blob_free(&tmp_blob);
01933                 return NT_STATUS_INVALID_PARAMETER;
01934         }
01935 
01936         /* We're finished with the server spnego response and the tmp_blob. */
01937         data_blob_free(&server_spnego_response);
01938         data_blob_free(&tmp_blob);
01939 
01940         nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
01941                                    server_ntlm_response,
01942                                    &client_reply);
01943         
01944         /* Finished with the server_ntlm response */
01945         data_blob_free(&server_ntlm_response);
01946 
01947         if (!NT_STATUS_IS_OK(nt_status)) {
01948                 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
01949                 data_blob_free(&client_reply);
01950                 return nt_status;
01951         }
01952 
01953         /* SPNEGO wrap the client reply. */
01954         tmp_blob = spnego_gen_auth(client_reply);
01955         data_blob_free(&client_reply);
01956         client_reply = tmp_blob;
01957         tmp_blob = data_blob(NULL,0); /* Ensure it's safe to free this just in case. */
01958 
01959         /* Now prepare the alter context pdu. */
01960         prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
01961 
01962         nt_status = create_rpc_alter_context(rpc_call_id,
01963                                                 abstract,
01964                                                 transfer,
01965                                                 auth_level,
01966                                                 &client_reply,
01967                                                 &rpc_out);
01968 
01969         data_blob_free(&client_reply);
01970 
01971         if (!NT_STATUS_IS_OK(nt_status)) {
01972                 prs_mem_free(&rpc_out);
01973                 return nt_status;
01974         }
01975 
01976         /* Initialize the returning data struct. */
01977         prs_mem_free(rbuf);
01978         prs_init(rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
01979 
01980         nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
01981         if (!NT_STATUS_IS_OK(nt_status)) {
01982                 prs_mem_free(&rpc_out);
01983                 return nt_status;
01984         }
01985 
01986         prs_mem_free(&rpc_out);
01987 
01988         /* Get the auth blob from the reply. */
01989         if(!smb_io_rpc_hdr("rpc_hdr   ", phdr, rbuf, 0)) {
01990                 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
01991                 return NT_STATUS_BUFFER_TOO_SMALL;
01992         }
01993 
01994         if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
01995                 return NT_STATUS_INVALID_PARAMETER;
01996         }
01997 
01998         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
01999                 return NT_STATUS_INVALID_PARAMETER;
02000         }
02001 
02002         server_spnego_response = data_blob(NULL, phdr->auth_len);
02003         prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
02004 
02005         /* Check we got a valid auth response. */
02006         if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, &tmp_blob)) {
02007                 data_blob_free(&server_spnego_response);
02008                 data_blob_free(&tmp_blob);
02009                 return NT_STATUS_INVALID_PARAMETER;
02010         }
02011 
02012         data_blob_free(&server_spnego_response);
02013         data_blob_free(&tmp_blob);
02014 
02015         DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
02016                 "remote machine %s pipe %s fnum 0x%x.\n",
02017                 cli->cli->desthost,
02018                 cli->pipe_name,
02019                 (unsigned int)cli->fnum));
02020 
02021         return NT_STATUS_OK;
02022 }
02023 
02024 /****************************************************************************
02025  Do an rpc bind.
02026 ****************************************************************************/
02027 
02028 static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
02029                         enum pipe_auth_type auth_type,
02030                         enum pipe_auth_level auth_level)
02031 {
02032         RPC_HDR hdr;
02033         RPC_HDR_BA hdr_ba;
02034         RPC_IFACE abstract;
02035         RPC_IFACE transfer;
02036         prs_struct rpc_out;
02037         prs_struct rbuf;
02038         uint32 rpc_call_id;
02039         NTSTATUS status;
02040 
02041         DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n",
02042                 (unsigned int)cli->fnum,
02043                 cli->pipe_name,
02044                 (unsigned int)auth_type,
02045                 (unsigned int)auth_level ));
02046 
02047         if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer)) {
02048                 return NT_STATUS_INVALID_PARAMETER;
02049         }
02050 
02051         prs_init(&rpc_out, 0, cli->cli->mem_ctx, MARSHALL);
02052 
02053         rpc_call_id = get_rpc_call_id();
02054 
02055         /* Marshall the outgoing data. */
02056         status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
02057                                 &abstract, &transfer,
02058                                 auth_type,
02059                                 auth_level);
02060 
02061         if (!NT_STATUS_IS_OK(status)) {
02062                 prs_mem_free(&rpc_out);
02063                 return status;
02064         }
02065 
02066         /* Initialize the incoming data struct. */
02067         prs_init(&rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
02068 
02069         /* send data on \PIPE\.  receive a response */
02070         status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
02071         if (!NT_STATUS_IS_OK(status)) {
02072                 prs_mem_free(&rpc_out);
02073                 return status;
02074         }
02075 
02076         prs_mem_free(&rpc_out);
02077 
02078         DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s "
02079                 "fnum 0x%x bind request returned ok.\n",
02080                 cli->cli->desthost,
02081                 cli->pipe_name,
02082                 (unsigned int)cli->fnum));
02083 
02084         /* Unmarshall the RPC header */
02085         if(!smb_io_rpc_hdr("hdr"   , &hdr, &rbuf, 0)) {
02086                 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
02087                 prs_mem_free(&rbuf);
02088                 return NT_STATUS_BUFFER_TOO_SMALL;
02089         }
02090 
02091         if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
02092                 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
02093                 prs_mem_free(&rbuf);
02094                 return NT_STATUS_BUFFER_TOO_SMALL;
02095         }
02096 
02097         if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) {
02098                 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
02099                 prs_mem_free(&rbuf);
02100                 return NT_STATUS_BUFFER_TOO_SMALL;
02101         }
02102 
02103         cli->max_xmit_frag = hdr_ba.bba.max_tsize;
02104         cli->max_recv_frag = hdr_ba.bba.max_rsize;
02105 
02106         /* For authenticated binds we may need to do 3 or 4 leg binds. */
02107         switch(auth_type) {
02108 
02109                 case PIPE_AUTH_TYPE_NONE:
02110                 case PIPE_AUTH_TYPE_SCHANNEL:
02111                         /* Bind complete. */
02112                         break;
02113 
02114                 case PIPE_AUTH_TYPE_NTLMSSP:
02115                         /* Need to send AUTH3 packet - no reply. */
02116                         status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id,
02117                                                 auth_type, auth_level);
02118                         if (!NT_STATUS_IS_OK(status)) {
02119                                 prs_mem_free(&rbuf);
02120                                 return status;
02121                         }
02122                         break;
02123 
02124                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
02125                         /* Need to send alter context request and reply. */
02126                         status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,
02127                                                 &abstract, &transfer,
02128                                                 auth_type, auth_level);
02129                         if (!NT_STATUS_IS_OK(status)) {
02130                                 prs_mem_free(&rbuf);
02131                                 return status;
02132                         }
02133                         break;
02134 
02135                 case PIPE_AUTH_TYPE_KRB5:
02136                         /* */
02137 
02138                 default:
02139                         DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
02140                                 (unsigned int)auth_type ));
02141                         prs_mem_free(&rbuf);
02142                         return NT_STATUS_INVALID_INFO_CLASS;
02143         }
02144 
02145         /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
02146         if (auth_type == PIPE_AUTH_TYPE_NTLMSSP || auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
02147                 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
02148                         if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
02149                                 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
02150                                 prs_mem_free(&rbuf);
02151                                 return NT_STATUS_INVALID_PARAMETER;
02152                         }
02153                 }
02154                 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
02155                         if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
02156                                 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
02157                                 prs_mem_free(&rbuf);
02158                                 return NT_STATUS_INVALID_PARAMETER;
02159                         }
02160                 }
02161         }
02162 
02163         /* Pipe is bound - set up auth_type and auth_level data. */
02164 
02165         cli->auth.auth_type = auth_type;
02166         cli->auth.auth_level = auth_level;
02167 
02168         prs_mem_free(&rbuf);
02169         return NT_STATUS_OK;
02170 }
02171 
02172 /****************************************************************************
02173  Open a named pipe over SMB to a remote server.
02174  *
02175  * CAVEAT CALLER OF THIS FUNCTION:
02176  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
02177  *    so be sure that this function is called AFTER any structure (vs pointer)
02178  *    assignment of the cli.  In particular, libsmbclient does structure
02179  *    assignments of cli, which invalidates the data in the returned
02180  *    rpc_pipe_client if this function is called before the structure assignment
02181  *    of cli.
02182  * 
02183  ****************************************************************************/
02184 
02185 static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
02186 {
02187         TALLOC_CTX *mem_ctx;
02188         struct rpc_pipe_client *result;
02189         int fnum;
02190 
02191         *perr = NT_STATUS_NO_MEMORY;
02192 
02193         /* sanity check to protect against crashes */
02194 
02195         if ( !cli ) {
02196                 *perr = NT_STATUS_INVALID_HANDLE;
02197                 return NULL;
02198         }
02199 
02200         /* The pipe name index must fall within our array */
02201         SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
02202 
02203         mem_ctx = talloc_init("struct rpc_pipe_client");
02204         if (mem_ctx == NULL) {
02205                 return NULL;
02206         }
02207 
02208         result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
02209         if (result == NULL) {
02210                 return NULL;
02211         }
02212 
02213         result->mem_ctx = mem_ctx;
02214 
02215         result->pipe_name = cli_get_pipe_name(pipe_idx);
02216 
02217         fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE);
02218 
02219         if (fnum == -1) {
02220                 DEBUG(1,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s "
02221                          "to machine %s.  Error was %s\n",
02222                          result->pipe_name, cli->desthost,
02223                          cli_errstr(cli)));
02224                 *perr = cli_get_nt_error(cli);
02225                 talloc_destroy(result->mem_ctx);
02226                 return NULL;
02227         }
02228 
02229         result->fnum = fnum;
02230         result->cli = cli;
02231         result->pipe_idx = pipe_idx;
02232         result->auth.auth_type = PIPE_AUTH_TYPE_NONE;
02233         result->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
02234 
02235         if (pipe_idx == PI_NETLOGON) {
02236                 /* Set up a netlogon credential chain for a netlogon pipe. */
02237                 result->dc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
02238                 if (result->dc == NULL) {
02239                         talloc_destroy(result->mem_ctx);
02240                         return NULL;
02241                 }
02242         }
02243 
02244         DLIST_ADD(cli->pipe_list, result);
02245         *perr = NT_STATUS_OK;
02246 
02247         return result;
02248 }
02249 
02250 /****************************************************************************
02251  Open a named pipe to an SMB server and bind anonymously.
02252  ****************************************************************************/
02253 
02254 struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
02255 {
02256         struct rpc_pipe_client *result;
02257 
02258         result = cli_rpc_pipe_open(cli, pipe_idx, perr);
02259         if (result == NULL) {
02260                 return NULL;
02261         }
02262 
02263         *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
02264         if (!NT_STATUS_IS_OK(*perr)) {
02265                 int lvl = 0;
02266                 if (pipe_idx == PI_LSARPC_DS) {
02267                         /* non AD domains just don't have this pipe, avoid
02268                          * level 0 statement in that case - gd */
02269                         lvl = 3;
02270                 }
02271                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
02272                         cli_get_pipe_name(pipe_idx), nt_errstr(*perr) ));
02273                 cli_rpc_pipe_close(result);
02274                 return NULL;
02275         }
02276 
02277         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine %s and bound anonymously.\n",
02278                         result->pipe_name, cli->desthost ));
02279 
02280         return result;
02281 }
02282 
02283 /****************************************************************************
02284  Free function for NTLMSSP auth.
02285  ****************************************************************************/
02286 
02287 static void cli_ntlmssp_auth_free(struct cli_pipe_auth_data *auth)
02288 {
02289         if (auth->a_u.ntlmssp_state) {
02290                 ntlmssp_end(&auth->a_u.ntlmssp_state);
02291                 auth->a_u.ntlmssp_state = NULL;
02292         }
02293 }
02294 
02295 /****************************************************************************
02296  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
02297  ****************************************************************************/
02298 
02299 static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
02300                                                 int pipe_idx,
02301                                                 enum pipe_auth_type auth_type,
02302                                                 enum pipe_auth_level auth_level,
02303                                                 const char *domain,
02304                                                 const char *username,
02305                                                 const char *password,
02306                                                 NTSTATUS *perr)
02307 {
02308         struct rpc_pipe_client *result;
02309         NTLMSSP_STATE *ntlmssp_state = NULL;
02310 
02311         result = cli_rpc_pipe_open(cli, pipe_idx, perr);
02312         if (result == NULL) {
02313                 return NULL;
02314         }
02315         
02316         result->auth.cli_auth_data_free_func = cli_ntlmssp_auth_free;
02317 
02318         result->domain = domain;
02319         result->user_name = username;
02320         pwd_set_cleartext(&result->pwd, password);
02321 
02322         *perr = ntlmssp_client_start(&ntlmssp_state);
02323         if (!NT_STATUS_IS_OK(*perr)) {
02324                 goto err;
02325         }
02326 
02327         result->auth.a_u.ntlmssp_state = ntlmssp_state;
02328 
02329         *perr = ntlmssp_set_username(ntlmssp_state, cli->user_name);
02330         if (!NT_STATUS_IS_OK(*perr)) {
02331                 goto err;
02332         }
02333 
02334         *perr = ntlmssp_set_domain(ntlmssp_state, cli->domain); 
02335         if (!NT_STATUS_IS_OK(*perr)) {
02336                 goto err;
02337         }
02338 
02339         if (cli->pwd.null_pwd) {
02340                 *perr = ntlmssp_set_password(ntlmssp_state, NULL);
02341                 if (!NT_STATUS_IS_OK(*perr)) {
02342                         goto err;
02343                 }
02344         } else {
02345                 *perr = ntlmssp_set_password(ntlmssp_state, password);
02346                 if (!NT_STATUS_IS_OK(*perr)) {
02347                         goto err;
02348                 }
02349         }
02350 
02351         /* Turn off sign+seal to allow selected auth level to turn it back on. */
02352         ntlmssp_state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
02353 
02354         if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
02355                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
02356         } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
02357                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
02358         }
02359         
02360         *perr = rpc_pipe_bind(result, auth_type, auth_level);
02361         if (!NT_STATUS_IS_OK(*perr)) {
02362                 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
02363                         nt_errstr(*perr) ));
02364                 goto err;
02365         }
02366 
02367         DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
02368                 "machine %s and bound NTLMSSP as user %s\\%s.\n",
02369                 result->pipe_name, cli->desthost,
02370                 domain, username ));
02371 
02372         return result;
02373 
02374   err:
02375 
02376         cli_rpc_pipe_close(result);
02377         return NULL;
02378 }
02379 
02380 /****************************************************************************
02381  External interface.
02382  Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
02383  ****************************************************************************/
02384 
02385 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
02386                                                 int pipe_idx,
02387                                                 enum pipe_auth_level auth_level,
02388                                                 const char *domain,
02389                                                 const char *username,
02390                                                 const char *password,
02391                                                 NTSTATUS *perr)
02392 {
02393         return cli_rpc_pipe_open_ntlmssp_internal(cli,
02394                                                 pipe_idx,
02395                                                 PIPE_AUTH_TYPE_NTLMSSP,
02396                                                 auth_level,
02397                                                 domain,
02398                                                 username,
02399                                                 password,
02400                                                 perr);
02401 }
02402 
02403 /****************************************************************************
02404  External interface.
02405  Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
02406  ****************************************************************************/
02407 
02408 struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
02409                                                 int pipe_idx,
02410                                                 enum pipe_auth_level auth_level,
02411                                                 const char *domain,
02412                                                 const char *username,
02413                                                 const char *password,
02414                                                 NTSTATUS *perr)
02415 {
02416         return cli_rpc_pipe_open_ntlmssp_internal(cli,
02417                                                 pipe_idx,
02418                                                 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
02419                                                 auth_level,
02420                                                 domain,
02421                                                 username,
02422                                                 password,
02423                                                 perr);
02424 }
02425 
02426 /****************************************************************************
02427   Get a the schannel session key out of an already opened netlogon pipe.
02428  ****************************************************************************/
02429 static BOOL get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
02430                                             struct cli_state *cli,
02431                                             const char *domain,
02432                                             uint32 *pneg_flags,
02433                                             NTSTATUS *perr)
02434 {
02435         uint32 sec_chan_type = 0;
02436         unsigned char machine_pwd[16];
02437         const char *machine_account;
02438 
02439         /* Get the machine account credentials from secrets.tdb. */
02440         if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
02441                                &sec_chan_type))
02442         {
02443                 DEBUG(0, ("get_schannel_session_key: could not fetch "
02444                         "trust account password for domain '%s'\n",
02445                         domain));
02446                 *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
02447                 return False;
02448         }
02449 
02450         *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
02451                                         cli->desthost, /* server name */
02452                                         domain,        /* domain */
02453                                         global_myname(), /* client name */
02454                                         machine_account, /* machine account name */
02455                                         machine_pwd,
02456                                         sec_chan_type,
02457                                         pneg_flags);
02458 
02459         if (!NT_STATUS_IS_OK(*perr)) {
02460                 DEBUG(3,("get_schannel_session_key_common: rpccli_netlogon_setup_creds "
02461                         "failed with result %s to server %s, domain %s, machine account %s.\n",
02462                         nt_errstr(*perr), cli->desthost, domain, machine_account ));
02463                 return False;
02464         }
02465 
02466         if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
02467                 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
02468                         cli->desthost));
02469                 *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
02470                 return False;
02471         }
02472 
02473         return True;
02474 }
02475 
02476 /****************************************************************************
02477  Open a netlogon pipe and get the schannel session key.
02478  Now exposed to external callers.
02479  ****************************************************************************/
02480 
02481 
02482 struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
02483                                                         const char *domain,
02484                                                         uint32 *pneg_flags,
02485                                                         NTSTATUS *perr)
02486 {
02487         struct rpc_pipe_client *netlogon_pipe = NULL;
02488 
02489         netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
02490         if (!netlogon_pipe) {
02491                 return NULL;
02492         }
02493 
02494         if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
02495                                              pneg_flags, perr))
02496         {
02497                 cli_rpc_pipe_close(netlogon_pipe);
02498                 return NULL;
02499         }
02500 
02501         return netlogon_pipe;
02502 }
02503 
02504 /****************************************************************************
02505  External interface.
02506  Open a named pipe to an SMB server and bind using schannel (bind type 68)
02507  using session_key. sign and seal.
02508  ****************************************************************************/
02509 
02510 struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
02511                                         int pipe_idx,
02512                                         enum pipe_auth_level auth_level,
02513                                         const char *domain,
02514                                         const struct dcinfo *pdc,
02515                                         NTSTATUS *perr)
02516 {
02517         struct rpc_pipe_client *result;
02518 
02519         result = cli_rpc_pipe_open(cli, pipe_idx, perr);
02520         if (result == NULL) {
02521                 return NULL;
02522         }
02523 
02524         result->auth.a_u.schannel_auth = TALLOC_ZERO_P(result->mem_ctx, struct schannel_auth_struct);
02525         if (!result->auth.a_u.schannel_auth) {
02526                 cli_rpc_pipe_close(result);
02527                 *perr = NT_STATUS_NO_MEMORY;
02528                 return NULL;
02529         }
02530 
02531         result->domain = domain;
02532         memcpy(result->auth.a_u.schannel_auth->sess_key, pdc->sess_key, 16);
02533 
02534         *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level);
02535         if (!NT_STATUS_IS_OK(*perr)) {
02536                 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
02537                         nt_errstr(*perr) ));
02538                 cli_rpc_pipe_close(result);
02539                 return NULL;
02540         }
02541 
02542         /* The credentials on a new netlogon pipe are the ones we are passed in - copy them over. */
02543         if (result->dc) {
02544                 *result->dc = *pdc;
02545         }
02546 
02547         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
02548                 "for domain %s "
02549                 "and bound using schannel.\n",
02550                 result->pipe_name, cli->desthost, domain ));
02551 
02552         return result;
02553 }
02554 
02555 /****************************************************************************
02556  Open a named pipe to an SMB server and bind using schannel (bind type 68).
02557  Fetch the session key ourselves using a temporary netlogon pipe. This
02558  version uses an ntlmssp auth bound netlogon pipe to get the key.
02559  ****************************************************************************/
02560 
02561 static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
02562                                                         const char *domain,
02563                                                         const char *username,
02564                                                         const char *password,
02565                                                         uint32 *pneg_flags,
02566                                                         NTSTATUS *perr)
02567 {
02568         struct rpc_pipe_client *netlogon_pipe = NULL;
02569 
02570         netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr);
02571         if (!netlogon_pipe) {
02572                 return NULL;
02573         }
02574 
02575         if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
02576                                              pneg_flags, perr))
02577         {
02578                 cli_rpc_pipe_close(netlogon_pipe);
02579                 return NULL;
02580         }
02581 
02582         return netlogon_pipe;
02583 }
02584 
02585 /****************************************************************************
02586  Open a named pipe to an SMB server and bind using schannel (bind type 68).
02587  Fetch the session key ourselves using a temporary netlogon pipe. This version
02588  uses an ntlmssp bind to get the session key.
02589  ****************************************************************************/
02590 
02591 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
02592                                                 int pipe_idx,
02593                                                 enum pipe_auth_level auth_level,
02594                                                 const char *domain,
02595                                                 const char *username,
02596                                                 const char *password,
02597                                                 NTSTATUS *perr)
02598 {
02599         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
02600         struct rpc_pipe_client *netlogon_pipe = NULL;
02601         struct rpc_pipe_client *result = NULL;
02602 
02603         netlogon_pipe = get_schannel_session_key_auth_ntlmssp(cli, domain, username,
02604                                                         password, &neg_flags, perr);
02605         if (!netlogon_pipe) {
02606                 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
02607                         "key from server %s for domain %s.\n",
02608                         cli->desthost, domain ));
02609                 return NULL;
02610         }
02611 
02612         result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
02613                                 auth_level,
02614                                 domain, netlogon_pipe->dc, perr);
02615 
02616         /* Now we've bound using the session key we can close the netlog pipe. */
02617         cli_rpc_pipe_close(netlogon_pipe);
02618 
02619         return result;
02620 }
02621 
02622 /****************************************************************************
02623  Open a named pipe to an SMB server and bind using schannel (bind type 68).
02624  Fetch the session key ourselves using a temporary netlogon pipe.
02625  ****************************************************************************/
02626 
02627 struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
02628                                                 int pipe_idx,
02629                                                 enum pipe_auth_level auth_level,
02630                                                 const char *domain,
02631                                                 NTSTATUS *perr)
02632 {
02633         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
02634         struct rpc_pipe_client *netlogon_pipe = NULL;
02635         struct rpc_pipe_client *result = NULL;
02636 
02637         netlogon_pipe = get_schannel_session_key(cli, domain, &neg_flags, perr);
02638         if (!netlogon_pipe) {
02639                 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
02640                         "key from server %s for domain %s.\n",
02641                         cli->desthost, domain ));
02642                 return NULL;
02643         }
02644 
02645         result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
02646                                 auth_level,
02647                                 domain, netlogon_pipe->dc, perr);
02648 
02649         /* Now we've bound using the session key we can close the netlog pipe. */
02650         cli_rpc_pipe_close(netlogon_pipe);
02651 
02652         return result;
02653 }
02654 
02655 #ifdef HAVE_KRB5
02656 
02657 /****************************************************************************
02658  Free function for the kerberos spcific data.
02659  ****************************************************************************/
02660 
02661 static void kerberos_auth_struct_free(struct cli_pipe_auth_data *a)
02662 {
02663         data_blob_free(&a->a_u.kerberos_auth->session_key);
02664 }
02665 
02666 #endif
02667 
02668 /****************************************************************************
02669  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
02670  The idea is this can be called with service_princ, username and password all
02671  NULL so long as the caller has a TGT.
02672  ****************************************************************************/
02673 
02674 struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
02675                                                 int pipe_idx,
02676                                                 enum pipe_auth_level auth_level,
02677                                                 const char *service_princ,
02678                                                 const char *username,
02679                                                 const char *password,
02680                                                 NTSTATUS *perr)
02681 {
02682 #ifdef HAVE_KRB5
02683         struct rpc_pipe_client *result;
02684 
02685         result = cli_rpc_pipe_open(cli, pipe_idx, perr);
02686         if (result == NULL) {
02687                 return NULL;
02688         }
02689 
02690         /* Default service principal is "desthost$@realm" */
02691         if (!service_princ) {
02692                 service_princ = talloc_asprintf(result->mem_ctx, "%s$@%s",
02693                         cli->desthost, lp_realm() );
02694                 if (!service_princ) {
02695                         cli_rpc_pipe_close(result);
02696                         return NULL;
02697                 }
02698         }
02699 
02700         /* Only get a new TGT if username/password are given. */
02701         if (username && password) {
02702                 int ret = kerberos_kinit_password(username, password, 0, NULL);
02703                 if (ret) {
02704                         cli_rpc_pipe_close(result);
02705                         return NULL;
02706                 }
02707         }
02708 
02709         result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(cli->mem_ctx, struct kerberos_auth_struct);
02710         if (!result->auth.a_u.kerberos_auth) {
02711                 cli_rpc_pipe_close(result);
02712                 *perr = NT_STATUS_NO_MEMORY;
02713                 return NULL;
02714         }
02715 
02716         result->auth.a_u.kerberos_auth->service_principal = service_princ;
02717         result->auth.cli_auth_data_free_func = kerberos_auth_struct_free;
02718 
02719         *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_KRB5, auth_level);
02720         if (!NT_STATUS_IS_OK(*perr)) {
02721                 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
02722                         nt_errstr(*perr) ));
02723                 cli_rpc_pipe_close(result);
02724                 return NULL;
02725         }
02726 
02727         return result;
02728 #else
02729         DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
02730         return NULL;
02731 #endif
02732 }
02733 
02734 #if 0 /* Moved to libsmb/clientgen.c */
02735 /****************************************************************************
02736  External interface.
02737  Close an open named pipe over SMB. Free any authentication data.
02738  ****************************************************************************/
02739 
02740  void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
02741 {
02742         if (!cli_close(cli->cli, cli->fnum)) {
02743                 DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s "
02744                          "to machine %s.  Error was %s\n",
02745                          cli->pipe_name),
02746                          cli->cli->desthost,
02747                          cli_errstr(cli->cli)));
02748         }
02749 
02750         if (cli->auth.cli_auth_data_free_func) {
02751                 (*cli->auth.cli_auth_data_free_func)(&cli->auth);
02752         }
02753         DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n",
02754                 cli->pipe_name, cli->cli->desthost ));
02755 
02756         DLIST_REMOVE(cli->cli->pipe_list, cli);
02757         talloc_destroy(cli->mem_ctx);   
02758 }
02759 #endif

Sambaに対してSat Aug 29 21:23:15 2009に生成されました。  doxygen 1.4.7