123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791 |
- From 8716bb5e03cc4f10e2d4edc704d8defe7e8045f1 Mon Sep 17 00:00:00 2001
- From: Stefan Metzmacher <metze@samba.org>
- Date: Thu, 16 Jul 2015 22:46:05 +0200
- Subject: [PATCH 01/40] CVE-2015-5370: dcerpc.idl: add
- DCERPC_{NCACN_PAYLOAD,FRAG}_MAX_SIZE defines
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- BUG: https://bugzilla.samba.org/show_bug.cgi?id=11344
- Signed-off-by: Stefan Metzmacher <metze@samba.org>
- Reviewed-by: Günther Deschner <gd@samba.org>
- ---
- librpc/idl/dcerpc.idl | 2 ++
- 1 file changed, 2 insertions(+)
- --- a/librpc/idl/dcerpc.idl
- +++ b/librpc/idl/dcerpc.idl
- @@ -475,9 +475,11 @@ interface dcerpc
- const uint8 DCERPC_PFC_OFFSET = 3;
- const uint8 DCERPC_DREP_OFFSET = 4;
- const uint8 DCERPC_FRAG_LEN_OFFSET = 8;
- + const uint32 DCERPC_FRAG_MAX_SIZE = 5840;
- const uint8 DCERPC_AUTH_LEN_OFFSET = 10;
- const uint8 DCERPC_CALL_ID_OFFSET = 12;
- const uint8 DCERPC_NCACN_PAYLOAD_OFFSET = 16;
- + const uint32 DCERPC_NCACN_PAYLOAD_MAX_SIZE = 0x400000; /* 4 MByte */
-
- /* little-endian flag */
- const uint8 DCERPC_DREP_LE = 0x10;
- --- a/librpc/rpc/dcerpc_util.c
- +++ b/librpc/rpc/dcerpc_util.c
- @@ -92,31 +92,49 @@ uint8_t dcerpc_get_endian_flag(DATA_BLOB
- *
- * @return - A NTSTATUS error code.
- */
- -NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
- +NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
- TALLOC_CTX *mem_ctx,
- - DATA_BLOB *pkt_trailer,
- + const DATA_BLOB *pkt_trailer,
- struct dcerpc_auth *auth,
- - uint32_t *auth_length,
- + uint32_t *_auth_length,
- bool auth_data_only)
- {
- struct ndr_pull *ndr;
- enum ndr_err_code ndr_err;
- - uint32_t data_and_pad;
- + uint16_t data_and_pad;
- + uint16_t auth_length;
- + uint32_t tmp_length;
-
- - data_and_pad = pkt_trailer->length
- - - (DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length);
- + ZERO_STRUCTP(auth);
- + if (_auth_length != NULL) {
- + *_auth_length = 0;
- + }
- +
- + /* Paranoia checks for auth_length. The caller should check this... */
- + if (pkt->auth_length == 0) {
- + return NT_STATUS_INTERNAL_ERROR;
- + }
- +
- + /* Paranoia checks for auth_length. The caller should check this... */
- + if (pkt->auth_length > pkt->frag_length) {
- + return NT_STATUS_INTERNAL_ERROR;
- + }
- + tmp_length = DCERPC_NCACN_PAYLOAD_OFFSET;
- + tmp_length += DCERPC_AUTH_TRAILER_LENGTH;
- + tmp_length += pkt->auth_length;
- + if (tmp_length > pkt->frag_length) {
- + return NT_STATUS_INTERNAL_ERROR;
- + }
- + if (pkt_trailer->length > UINT16_MAX) {
- + return NT_STATUS_INTERNAL_ERROR;
- + }
-
- - /* paranoia check for pad size. This would be caught anyway by
- - the ndr_pull_advance() a few lines down, but it scared
- - Jeremy enough for him to call me, so we might as well check
- - it now, just to prevent someone posting a bogus YouTube
- - video in the future.
- - */
- - if (data_and_pad > pkt_trailer->length) {
- - return NT_STATUS_INFO_LENGTH_MISMATCH;
- + auth_length = DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length;
- + if (pkt_trailer->length < auth_length) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- }
-
- - *auth_length = pkt_trailer->length - data_and_pad;
- + data_and_pad = pkt_trailer->length - auth_length;
-
- ndr = ndr_pull_init_blob(pkt_trailer, mem_ctx);
- if (!ndr) {
- @@ -136,14 +154,28 @@ NTSTATUS dcerpc_pull_auth_trailer(struct
- ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- talloc_free(ndr);
- + ZERO_STRUCTP(auth);
- return ndr_map_error2ntstatus(ndr_err);
- }
-
- + if (data_and_pad < auth->auth_pad_length) {
- + DEBUG(1, (__location__ ": ERROR: pad length mismatch. "
- + "Calculated %u got %u\n",
- + (unsigned)data_and_pad,
- + (unsigned)auth->auth_pad_length));
- + talloc_free(ndr);
- + ZERO_STRUCTP(auth);
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- +
- if (auth_data_only && data_and_pad != auth->auth_pad_length) {
- - DEBUG(1, (__location__ ": WARNING: pad length mismatch. "
- + DEBUG(1, (__location__ ": ERROR: pad length mismatch. "
- "Calculated %u got %u\n",
- (unsigned)data_and_pad,
- (unsigned)auth->auth_pad_length));
- + talloc_free(ndr);
- + ZERO_STRUCTP(auth);
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- }
-
- DEBUG(6,(__location__ ": auth_pad_length %u\n",
- @@ -152,6 +184,83 @@ NTSTATUS dcerpc_pull_auth_trailer(struct
- talloc_steal(mem_ctx, auth->credentials.data);
- talloc_free(ndr);
-
- + if (_auth_length != NULL) {
- + *_auth_length = auth_length;
- + }
- +
- + return NT_STATUS_OK;
- +}
- +
- +/**
- +* @brief Verify the fields in ncacn_packet header.
- +*
- +* @param pkt - The ncacn_packet strcuture
- +* @param ptype - The expected PDU type
- +* @param max_auth_info - The maximum size of a possible auth trailer
- +* @param required_flags - The required flags for the pdu.
- +* @param optional_flags - The possible optional flags for the pdu.
- +*
- +* @return - A NTSTATUS error code.
- +*/
- +NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
- + enum dcerpc_pkt_type ptype,
- + size_t max_auth_info,
- + uint8_t required_flags,
- + uint8_t optional_flags)
- +{
- + if (pkt->rpc_vers != 5) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- +
- + if (pkt->rpc_vers_minor != 0) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- +
- + if (pkt->auth_length > pkt->frag_length) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- +
- + if (pkt->ptype != ptype) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- +
- + if (max_auth_info > UINT16_MAX) {
- + return NT_STATUS_INTERNAL_ERROR;
- + }
- +
- + if (pkt->auth_length > 0) {
- + size_t max_auth_length;
- +
- + if (max_auth_info <= DCERPC_AUTH_TRAILER_LENGTH) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- + max_auth_length = max_auth_info - DCERPC_AUTH_TRAILER_LENGTH;
- +
- + if (pkt->auth_length > max_auth_length) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- + }
- +
- + if ((pkt->pfc_flags & required_flags) != required_flags) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- + if (pkt->pfc_flags & ~(optional_flags|required_flags)) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- +
- + if (pkt->drep[0] & ~DCERPC_DREP_LE) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- + if (pkt->drep[1] != 0) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- + if (pkt->drep[2] != 0) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- + if (pkt->drep[3] != 0) {
- + return NT_STATUS_RPC_PROTOCOL_ERROR;
- + }
- +
- return NT_STATUS_OK;
- }
-
- --- a/librpc/rpc/rpc_common.h
- +++ b/librpc/rpc/rpc_common.h
- @@ -158,12 +158,17 @@ uint8_t dcerpc_get_endian_flag(DATA_BLOB
- *
- * @return - A NTSTATUS error code.
- */
- -NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
- +NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
- TALLOC_CTX *mem_ctx,
- - DATA_BLOB *pkt_trailer,
- + const DATA_BLOB *pkt_trailer,
- struct dcerpc_auth *auth,
- uint32_t *auth_length,
- bool auth_data_only);
- +NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
- + enum dcerpc_pkt_type ptype,
- + size_t max_auth_info,
- + uint8_t required_flags,
- + uint8_t optional_flags);
- struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct tstream_context *stream);
- --- a/source3/librpc/rpc/dcerpc_helpers.c
- +++ b/source3/librpc/rpc/dcerpc_helpers.c
- @@ -210,47 +210,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_
- }
-
- /**
- -* @brief Decodes a dcerpc_auth blob
- -*
- -* @param mem_ctx The memory context on which to allocate the packet
- -* elements
- -* @param blob The blob of data to decode
- -* @param r An empty dcerpc_auth structure, must not be NULL
- -*
- -* @return a NTSTATUS error code
- -*/
- -NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
- - const DATA_BLOB *blob,
- - struct dcerpc_auth *r,
- - bool bigendian)
- -{
- - enum ndr_err_code ndr_err;
- - struct ndr_pull *ndr;
- -
- - ndr = ndr_pull_init_blob(blob, mem_ctx);
- - if (!ndr) {
- - return NT_STATUS_NO_MEMORY;
- - }
- - if (bigendian) {
- - ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
- - }
- -
- - ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r);
- -
- - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- - talloc_free(ndr);
- - return ndr_map_error2ntstatus(ndr_err);
- - }
- - talloc_free(ndr);
- -
- - if (DEBUGLEVEL >= 10) {
- - NDR_PRINT_DEBUG(dcerpc_auth, r);
- - }
- -
- - return NT_STATUS_OK;
- -}
- -
- -/**
- * @brief Calculate how much data we can in a packet, including calculating
- * auth token and pad lengths.
- *
- @@ -782,7 +741,7 @@ NTSTATUS dcerpc_add_auth_footer(struct p
- auth->auth_type,
- auth->auth_level,
- pad_len,
- - 1 /* context id. */,
- + auth->auth_context_id,
- &auth_blob,
- &auth_info);
- if (!NT_STATUS_IS_OK(status)) {
- @@ -844,19 +803,18 @@ NTSTATUS dcerpc_add_auth_footer(struct p
- *
- * @param auth The auth data for the connection
- * @param pkt The actual ncacn_packet
- -* @param pkt_trailer The stub_and_verifier part of the packet
- +* @param pkt_trailer [in][out] The stub_and_verifier part of the packet,
- +* the auth_trailer and padding will be removed.
- * @param header_size The header size
- * @param raw_pkt The whole raw packet data blob
- -* @param pad_len [out] The padding length used in the packet
- *
- * @return A NTSTATUS error code
- */
- NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
- struct ncacn_packet *pkt,
- DATA_BLOB *pkt_trailer,
- - size_t header_size,
- - DATA_BLOB *raw_pkt,
- - size_t *pad_len)
- + uint8_t header_size,
- + DATA_BLOB *raw_pkt)
- {
- struct schannel_state *schannel_auth;
- struct auth_ntlmssp_state *ntlmssp_ctx;
- @@ -868,6 +826,14 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
- DATA_BLOB full_pkt;
- DATA_BLOB data;
-
- + /*
- + * These check should be done in the caller.
- + */
- + SMB_ASSERT(raw_pkt->length == pkt->frag_length);
- + SMB_ASSERT(header_size <= pkt->frag_length);
- + SMB_ASSERT(pkt_trailer->length < pkt->frag_length);
- + SMB_ASSERT((pkt_trailer->length + header_size) <= pkt->frag_length);
- +
- switch (auth->auth_level) {
- case DCERPC_AUTH_LEVEL_PRIVACY:
- DEBUG(10, ("Requested Privacy.\n"));
- @@ -881,7 +847,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
- if (pkt->auth_length != 0) {
- break;
- }
- - *pad_len = 0;
- return NT_STATUS_OK;
-
- case DCERPC_AUTH_LEVEL_NONE:
- @@ -890,7 +855,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
- "authenticated connection!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
- - *pad_len = 0;
- return NT_STATUS_OK;
-
- default:
- @@ -899,16 +863,8 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- - /* Paranioa checks for auth_length. */
- - if (pkt->auth_length > pkt->frag_length) {
- - return NT_STATUS_INFO_LENGTH_MISMATCH;
- - }
- - if (((unsigned int)pkt->auth_length
- - + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
- - ((unsigned int)pkt->auth_length
- - + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
- - /* Integer wrap attempt. */
- - return NT_STATUS_INFO_LENGTH_MISMATCH;
- + if (pkt->auth_length == 0) {
- + return NT_STATUS_INVALID_PARAMETER;
- }
-
- status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
- @@ -917,10 +873,23 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
- return status;
- }
-
- + if (auth_info.auth_type != auth->auth_type) {
- + return NT_STATUS_INVALID_PARAMETER;
- + }
- +
- + if (auth_info.auth_level != auth->auth_level) {
- + return NT_STATUS_INVALID_PARAMETER;
- + }
- +
- + if (auth_info.auth_context_id != auth->auth_context_id) {
- + return NT_STATUS_INVALID_PARAMETER;
- + }
- +
- + pkt_trailer->length -= auth_length;
- data = data_blob_const(raw_pkt->data + header_size,
- - pkt_trailer->length - auth_length);
- - full_pkt = data_blob_const(raw_pkt->data,
- - raw_pkt->length - auth_info.credentials.length);
- + pkt_trailer->length);
- + full_pkt = data_blob_const(raw_pkt->data, raw_pkt->length);
- + full_pkt.length -= auth_info.credentials.length;
-
- switch (auth->auth_type) {
- case DCERPC_AUTH_TYPE_NONE:
- @@ -996,10 +965,13 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
- * pkt_trailer actually has a copy of the raw data, and they
- * are still both used in later calls */
- if (auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
- + if (pkt_trailer->length != data.length) {
- + return NT_STATUS_INVALID_PARAMETER;
- + }
- memcpy(pkt_trailer->data, data.data, data.length);
- }
-
- - *pad_len = auth_info.auth_pad_length;
- + pkt_trailer->length -= auth_info.auth_pad_length;
- data_blob_free(&auth_info.credentials);
- return NT_STATUS_OK;
- }
- --- a/source3/rpc_client/cli_pipe.c
- +++ b/source3/rpc_client/cli_pipe.c
- @@ -404,9 +404,9 @@ static NTSTATUS cli_pipe_validate_curren
- DATA_BLOB *rdata,
- DATA_BLOB *reply_pdu)
- {
- - struct dcerpc_response *r;
- + const struct dcerpc_response *r = NULL;
- + DATA_BLOB tmp_stub = data_blob_null;
- NTSTATUS ret = NT_STATUS_OK;
- - size_t pad_len = 0;
-
- /*
- * Point the return values at the real data including the RPC
- @@ -414,50 +414,128 @@ static NTSTATUS cli_pipe_validate_curren
- */
- *rdata = *pdu;
-
- + if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
- + !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
- + /*
- + * TODO: do we still need this hack which was introduced
- + * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
- + *
- + * I don't even know what AS/U might be...
- + */
- + DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
- + "fragment first/last ON.\n"));
- + pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
- + }
- +
- /* Ensure we have the correct type. */
- switch (pkt->ptype) {
- - case DCERPC_PKT_ALTER_RESP:
- + case DCERPC_PKT_BIND_NAK:
- + DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
- + rpccli_pipe_txt(talloc_tos(), cli)));
- +
- + ret = dcerpc_verify_ncacn_packet_header(pkt,
- + DCERPC_PKT_BIND_NAK,
- + 0, /* max_auth_info */
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST,
- + 0); /* optional flags */
- + if (!NT_STATUS_IS_OK(ret)) {
- + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
- + "RPC packet type - %u, expected %u: %s\n",
- + rpccli_pipe_txt(talloc_tos(), cli),
- + pkt->ptype, expected_pkt_type,
- + nt_errstr(ret)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + return ret;
- + }
- +
- + /* Use this for now... */
- + return NT_STATUS_NETWORK_ACCESS_DENIED;
- +
- case DCERPC_PKT_BIND_ACK:
- + ret = dcerpc_verify_ncacn_packet_header(pkt,
- + expected_pkt_type,
- + pkt->u.bind_ack.auth_info.length,
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST,
- + DCERPC_PFC_FLAG_CONC_MPX |
- + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
- + if (!NT_STATUS_IS_OK(ret)) {
- + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
- + "RPC packet type - %u, expected %u: %s\n",
- + rpccli_pipe_txt(talloc_tos(), cli),
- + pkt->ptype, expected_pkt_type,
- + nt_errstr(ret)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + return ret;
- + }
-
- - /* Client code never receives this kind of packets */
- break;
-
- + case DCERPC_PKT_ALTER_RESP:
- + ret = dcerpc_verify_ncacn_packet_header(pkt,
- + expected_pkt_type,
- + pkt->u.alter_resp.auth_info.length,
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST,
- + DCERPC_PFC_FLAG_CONC_MPX |
- + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
- + if (!NT_STATUS_IS_OK(ret)) {
- + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
- + "RPC packet type - %u, expected %u: %s\n",
- + rpccli_pipe_txt(talloc_tos(), cli),
- + pkt->ptype, expected_pkt_type,
- + nt_errstr(ret)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + return ret;
- + }
- +
- + break;
-
- case DCERPC_PKT_RESPONSE:
-
- r = &pkt->u.response;
-
- + ret = dcerpc_verify_ncacn_packet_header(pkt,
- + expected_pkt_type,
- + r->stub_and_verifier.length,
- + 0, /* required_flags */
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST);
- + if (!NT_STATUS_IS_OK(ret)) {
- + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
- + "RPC packet type - %u, expected %u: %s\n",
- + rpccli_pipe_txt(talloc_tos(), cli),
- + pkt->ptype, expected_pkt_type,
- + nt_errstr(ret)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + return ret;
- + }
- +
- + tmp_stub.data = r->stub_and_verifier.data;
- + tmp_stub.length = r->stub_and_verifier.length;
- +
- /* Here's where we deal with incoming sign/seal. */
- ret = dcerpc_check_auth(cli->auth, pkt,
- - &r->stub_and_verifier,
- + &tmp_stub,
- DCERPC_RESPONSE_LENGTH,
- - pdu, &pad_len);
- + pdu);
- if (!NT_STATUS_IS_OK(ret)) {
- + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
- + "RPC packet type - %u, expected %u: %s\n",
- + rpccli_pipe_txt(talloc_tos(), cli),
- + pkt->ptype, expected_pkt_type,
- + nt_errstr(ret)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- return ret;
- }
-
- - if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
- - return NT_STATUS_BUFFER_TOO_SMALL;
- - }
- -
- /* Point the return values at the NDR data. */
- - rdata->data = r->stub_and_verifier.data;
- + *rdata = tmp_stub;
-
- - if (pkt->auth_length) {
- - /* We've already done integer wrap tests in
- - * dcerpc_check_auth(). */
- - rdata->length = r->stub_and_verifier.length
- - - pad_len
- - - DCERPC_AUTH_TRAILER_LENGTH
- - - pkt->auth_length;
- - } else {
- - rdata->length = r->stub_and_verifier.length;
- - }
- -
- - DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
- + DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
- (long unsigned int)pdu->length,
- - (long unsigned int)rdata->length,
- - (unsigned int)pad_len));
- + (long unsigned int)rdata->length));
-
- /*
- * If this is the first reply, and the allocation hint is
- @@ -478,14 +556,24 @@ static NTSTATUS cli_pipe_validate_curren
-
- break;
-
- - case DCERPC_PKT_BIND_NAK:
- - DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
- - rpccli_pipe_txt(talloc_tos(), cli)));
- - /* Use this for now... */
- - return NT_STATUS_NETWORK_ACCESS_DENIED;
- -
- case DCERPC_PKT_FAULT:
-
- + ret = dcerpc_verify_ncacn_packet_header(pkt,
- + DCERPC_PKT_FAULT,
- + 0, /* max_auth_info */
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST,
- + DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
- + if (!NT_STATUS_IS_OK(ret)) {
- + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
- + "RPC packet type - %u, expected %u: %s\n",
- + rpccli_pipe_txt(talloc_tos(), cli),
- + pkt->ptype, expected_pkt_type,
- + nt_errstr(ret)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + return ret;
- + }
- +
- DEBUG(1, (__location__ ": RPC fault code %s received "
- "from %s!\n",
- dcerpc_errstr(talloc_tos(),
- @@ -502,13 +590,6 @@ static NTSTATUS cli_pipe_validate_curren
- return NT_STATUS_RPC_PROTOCOL_ERROR;
- }
-
- - if (pkt->ptype != expected_pkt_type) {
- - DEBUG(3, (__location__ ": Connection to %s got an unexpected "
- - "RPC packet type - %u, not %u\n",
- - rpccli_pipe_txt(talloc_tos(), cli),
- - pkt->ptype, expected_pkt_type));
- - return NT_STATUS_RPC_PROTOCOL_ERROR;
- - }
-
- if (pkt->call_id != call_id) {
- DEBUG(3, (__location__ ": Connection to %s got an unexpected "
- @@ -518,17 +599,6 @@ static NTSTATUS cli_pipe_validate_curren
- return NT_STATUS_RPC_PROTOCOL_ERROR;
- }
-
- - /* Do this just before return - we don't want to modify any rpc header
- - data before now as we may have needed to do cryptographic actions on
- - it before. */
- -
- - if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
- - !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
- - DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
- - "fragment first/last ON.\n"));
- - pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
- - }
- -
- return NT_STATUS_OK;
- }
-
- @@ -883,6 +953,12 @@ static void rpc_api_pipe_got_pdu(struct
-
- state->pkt = talloc(state, struct ncacn_packet);
- if (!state->pkt) {
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
- @@ -892,18 +968,16 @@ static void rpc_api_pipe_got_pdu(struct
- state->pkt,
- !state->endianess);
- if (!NT_STATUS_IS_OK(status)) {
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- tevent_req_nterror(req, status);
- return;
- }
-
- - if (state->incoming_frag.length != state->pkt->frag_length) {
- - DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
- - (unsigned int)state->incoming_frag.length,
- - (unsigned int)state->pkt->frag_length));
- - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- - return;
- - }
- -
- status = cli_pipe_validate_current_pdu(state,
- state->cli, state->pkt,
- &state->incoming_frag,
- @@ -917,6 +991,28 @@ static void rpc_api_pipe_got_pdu(struct
- (unsigned)state->reply_pdu_offset,
- nt_errstr(status)));
-
- + if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- + } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- + } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- + }
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- @@ -941,7 +1037,24 @@ static void rpc_api_pipe_got_pdu(struct
- "%s\n",
- state->endianess?"little":"big",
- state->pkt->drep[0]?"little":"big"));
- - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
- + return;
- + }
- +
- + if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
- return;
- }
-
- @@ -949,6 +1062,12 @@ static void rpc_api_pipe_got_pdu(struct
- if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
- if (!data_blob_realloc(NULL, &state->reply_pdu,
- state->reply_pdu_offset + rdata.length)) {
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
- @@ -978,6 +1097,14 @@ static void rpc_api_pipe_got_pdu(struct
- subreq = get_complete_frag_send(state, state->ev, state->cli,
- state->call_id,
- &state->incoming_frag);
- + if (subreq == NULL) {
- + /*
- + * TODO: do a real async disconnect ...
- + *
- + * For now do it sync...
- + */
- + TALLOC_FREE(state->cli->transport);
- + }
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- @@ -1247,7 +1374,7 @@ static NTSTATUS create_rpc_bind_req(TALL
- auth->auth_type,
- auth->auth_level,
- 0, /* auth_pad_length */
- - 1, /* auth_context_id */
- + auth->auth_context_id,
- &auth_token,
- &auth_info);
- if (!NT_STATUS_IS_OK(ret)) {
- @@ -1749,9 +1876,8 @@ static bool check_bind_response(const st
-
- static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
- struct rpc_pipe_client *cli,
- - uint32 rpc_call_id,
- - enum dcerpc_AuthType auth_type,
- - enum dcerpc_AuthLevel auth_level,
- + struct pipe_auth_data *auth,
- + uint32_t rpc_call_id,
- DATA_BLOB *pauth_blob,
- DATA_BLOB *rpc_out)
- {
- @@ -1761,10 +1887,10 @@ static NTSTATUS create_rpc_bind_auth3(TA
- u.auth3._pad = 0;
-
- status = dcerpc_push_dcerpc_auth(mem_ctx,
- - auth_type,
- - auth_level,
- + auth->auth_type,
- + auth->auth_level,
- 0, /* auth_pad_length */
- - 1, /* auth_context_id */
- + auth->auth_context_id,
- pauth_blob,
- &u.auth3.auth_info);
- if (!NT_STATUS_IS_OK(status)) {
- @@ -1794,9 +1920,8 @@ static NTSTATUS create_rpc_bind_auth3(TA
- ********************************************************************/
-
- static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
- - enum dcerpc_AuthType auth_type,
- - enum dcerpc_AuthLevel auth_level,
- - uint32 rpc_call_id,
- + struct pipe_auth_data *auth,
- + uint32_t rpc_call_id,
- const struct ndr_syntax_id *abstract,
- const struct ndr_syntax_id *transfer,
- const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
- @@ -1806,10 +1931,10 @@ static NTSTATUS create_rpc_alter_context
- NTSTATUS status;
-
- status = dcerpc_push_dcerpc_auth(mem_ctx,
- - auth_type,
- - auth_level,
- + auth->auth_type,
- + auth->auth_level,
- 0, /* auth_pad_length */
- - 1, /* auth_context_id */
- + auth->auth_context_id,
- pauth_blob,
- &auth_info);
- if (!NT_STATUS_IS_OK(status)) {
- @@ -1957,30 +2082,45 @@ static void rpc_pipe_bind_step_one_done(
- rpc_pipe_bind_step_two_trigger(req);
- return;
-
- - case DCERPC_AUTH_TYPE_NTLMSSP:
- - case DCERPC_AUTH_TYPE_SPNEGO:
- - case DCERPC_AUTH_TYPE_KRB5:
- - /* Paranoid lenght checks */
- - if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
- - + pkt->auth_length) {
- - tevent_req_nterror(req,
- - NT_STATUS_INFO_LENGTH_MISMATCH);
- + default:
- + if (pkt->auth_length == 0) {
- + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
- return;
- }
- /* get auth credentials */
- - status = dcerpc_pull_dcerpc_auth(talloc_tos(),
- - &pkt->u.bind_ack.auth_info,
- - &auth, false);
- + status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
- + &pkt->u.bind_ack.auth_info,
- + &auth, NULL, true);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
- nt_errstr(status)));
- tevent_req_nterror(req, status);
- return;
- }
- - break;
-
- - default:
- - goto err_out;
- + if (auth.auth_type != pauth->auth_type) {
- + DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
- + auth.auth_type, pauth->auth_type));
- + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
- + return;
- + }
- +
- + if (auth.auth_level != pauth->auth_level) {
- + DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
- + auth.auth_level, pauth->auth_level));
- + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
- + return;
- + }
- +
- + if (auth.auth_context_id != pauth->auth_context_id) {
- + DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
- + (unsigned)auth.auth_context_id,
- + (unsigned)pauth->auth_context_id));
- + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
- + return;
- + }
- +
- + break;
- }
-
- /*
- @@ -2226,9 +2366,7 @@ static NTSTATUS rpc_bind_next_send(struc
- /* Now prepare the alter context pdu. */
- data_blob_free(&state->rpc_out);
-
- - status = create_rpc_alter_context(state,
- - auth->auth_type,
- - auth->auth_level,
- + status = create_rpc_alter_context(state, auth,
- state->rpc_call_id,
- &state->cli->abstract_syntax,
- &state->cli->transfer_syntax,
- @@ -2261,10 +2399,8 @@ static NTSTATUS rpc_bind_finish_send(str
- /* Now prepare the auth3 context pdu. */
- data_blob_free(&state->rpc_out);
-
- - status = create_rpc_bind_auth3(state, state->cli,
- + status = create_rpc_bind_auth3(state, state->cli, auth,
- state->rpc_call_id,
- - auth->auth_type,
- - auth->auth_level,
- auth_token,
- &state->rpc_out);
- if (!NT_STATUS_IS_OK(status)) {
- @@ -2498,8 +2634,9 @@ static struct tevent_req *rpccli_bh_disc
- /*
- * TODO: do a real async disconnect ...
- *
- - * For now the caller needs to free rpc_cli
- + * For now we do it sync...
- */
- + TALLOC_FREE(hs->rpc_cli->transport);
- hs->rpc_cli = NULL;
-
- tevent_req_done(req);
- @@ -2636,6 +2773,7 @@ NTSTATUS rpccli_ncalrpc_bind_data(TALLOC
-
- result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
- result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
- + result->auth_context_id = 1;
-
- result->user_name = talloc_strdup(result, "");
- result->domain = talloc_strdup(result, "");
- @@ -2660,6 +2798,7 @@ NTSTATUS rpccli_anon_bind_data(TALLOC_CT
-
- result->auth_type = DCERPC_AUTH_TYPE_NONE;
- result->auth_level = DCERPC_AUTH_LEVEL_NONE;
- + result->auth_context_id = 0;
-
- result->user_name = talloc_strdup(result, "");
- result->domain = talloc_strdup(result, "");
- @@ -2697,6 +2836,7 @@ static NTSTATUS rpccli_ntlmssp_bind_data
-
- result->auth_type = auth_type;
- result->auth_level = auth_level;
- + result->auth_context_id = 1;
-
- result->user_name = talloc_strdup(result, username);
- result->domain = talloc_strdup(result, domain);
- @@ -2768,6 +2908,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLO
-
- result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
- result->auth_level = auth_level;
- + result->auth_context_id = 1;
-
- result->user_name = talloc_strdup(result, "");
- result->domain = talloc_strdup(result, domain);
- @@ -3432,6 +3573,7 @@ NTSTATUS cli_rpc_pipe_open_krb5(struct c
- }
- auth->auth_type = DCERPC_AUTH_TYPE_KRB5;
- auth->auth_level = auth_level;
- + auth->auth_context_id = 1;
-
- if (!username) {
- username = "";
- @@ -3502,6 +3644,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_krb5(s
- }
- auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
- auth->auth_level = auth_level;
- + auth->auth_context_id = 1;
-
- if (!username) {
- username = "";
- @@ -3576,6 +3719,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_ntlmss
- }
- auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
- auth->auth_level = auth_level;
- + auth->auth_context_id = 1;
-
- if (!username) {
- username = "";
- --- a/source4/rpc_server/dcesrv_auth.c
- +++ b/source4/rpc_server/dcesrv_auth.c
- @@ -46,7 +46,7 @@ bool dcesrv_auth_bind(struct dcesrv_call
- NTSTATUS status;
- uint32_t auth_length;
-
- - if (pkt->u.bind.auth_info.length == 0) {
- + if (pkt->auth_length == 0) {
- dce_conn->auth_state.auth_info = NULL;
- return true;
- }
- @@ -108,7 +108,7 @@ NTSTATUS dcesrv_auth_bind_ack(struct dce
- struct dcesrv_connection *dce_conn = call->conn;
- NTSTATUS status;
-
- - if (!call->conn->auth_state.gensec_security) {
- + if (call->pkt.auth_length == 0) {
- return NT_STATUS_OK;
- }
-
- @@ -155,10 +155,16 @@ bool dcesrv_auth_auth3(struct dcesrv_cal
- NTSTATUS status;
- uint32_t auth_length;
-
- - /* We can't work without an existing gensec state, and an new blob to feed it */
- - if (!dce_conn->auth_state.auth_info ||
- - !dce_conn->auth_state.gensec_security ||
- - pkt->u.auth3.auth_info.length == 0) {
- + if (pkt->auth_length == 0) {
- + return false;
- + }
- +
- + if (!dce_conn->auth_state.auth_info) {
- + return false;
- + }
- +
- + /* We can't work without an existing gensec state */
- + if (!dce_conn->auth_state.gensec_security) {
- return false;
- }
-
- @@ -203,7 +209,7 @@ bool dcesrv_auth_alter(struct dcesrv_cal
- uint32_t auth_length;
-
- /* on a pure interface change there is no auth blob */
- - if (pkt->u.alter.auth_info.length == 0) {
- + if (pkt->auth_length == 0) {
- return true;
- }
-
- @@ -238,8 +244,7 @@ NTSTATUS dcesrv_auth_alter_ack(struct dc
-
- /* on a pure interface change there is no auth_info structure
- setup */
- - if (!call->conn->auth_state.auth_info ||
- - dce_conn->auth_state.auth_info->credentials.length == 0) {
- + if (call->pkt.auth_length == 0) {
- return NT_STATUS_OK;
- }
-
- @@ -315,6 +320,11 @@ bool dcesrv_auth_request(struct dcesrv_c
- return false;
- }
-
- + if (pkt->auth_length == 0) {
- + DEBUG(1,("dcesrv_auth_request: unexpected auth_length of 0\n"));
- + return false;
- + }
- +
- status = dcerpc_pull_auth_trailer(pkt, call,
- &pkt->u.request.stub_and_verifier,
- &auth, &auth_length, false);
- --- a/source4/librpc/rpc/dcerpc.c
- +++ b/source4/librpc/rpc/dcerpc.c
- @@ -701,6 +701,14 @@ static NTSTATUS ncacn_pull_request_auth(
- return NT_STATUS_INVALID_LEVEL;
- }
-
- + if (pkt->auth_length == 0) {
- + return NT_STATUS_INVALID_NETWORK_RESPONSE;
- + }
- +
- + if (c->security_state.generic_state == NULL) {
- + return NT_STATUS_INTERNAL_ERROR;
- + }
- +
- status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
- &pkt->u.response.stub_and_verifier,
- &auth, &auth_length, false);
- @@ -1074,7 +1082,7 @@ static void dcerpc_bind_recv_handler(str
- }
-
- /* the bind_ack might contain a reply set of credentials */
- - if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
- + if (conn->security_state.auth_info && pkt->auth_length) {
- NTSTATUS status;
- uint32_t auth_length;
- status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
- @@ -1847,8 +1855,7 @@ static void dcerpc_alter_recv_handler(st
- }
-
- /* the alter_resp might contain a reply set of credentials */
- - if (recv_pipe->conn->security_state.auth_info &&
- - pkt->u.alter_resp.auth_info.length) {
- + if (recv_pipe->conn->security_state.auth_info && pkt->auth_length) {
- struct dcecli_connection *conn = recv_pipe->conn;
- NTSTATUS status;
- uint32_t auth_length;
- --- a/source3/librpc/rpc/dcerpc.h
- +++ b/source3/librpc/rpc/dcerpc.h
- @@ -42,6 +42,7 @@ struct pipe_auth_data {
- bool verified_bitmask1;
-
- void *auth_ctx;
- + uint32_t auth_context_id;
-
- /* Only the client code uses these 3 for now */
- char *domain;
- @@ -71,10 +72,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_
- uint32_t auth_context_id,
- const DATA_BLOB *credentials,
- DATA_BLOB *blob);
- -NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
- - const DATA_BLOB *blob,
- - struct dcerpc_auth *r,
- - bool bigendian);
- NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth,
- size_t header_len, size_t data_left,
- size_t max_xmit_frag, size_t pad_alignment,
- @@ -85,9 +82,8 @@ NTSTATUS dcerpc_add_auth_footer(struct p
- NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
- struct ncacn_packet *pkt,
- DATA_BLOB *pkt_trailer,
- - size_t header_size,
- - DATA_BLOB *raw_pkt,
- - size_t *pad_len);
- + uint8_t header_size,
- + DATA_BLOB *raw_pkt);
-
- /* The following definitions come from librpc/rpc/rpc_common.c */
-
- --- a/source3/rpc_server/srv_pipe.c
- +++ b/source3/rpc_server/srv_pipe.c
- @@ -42,6 +42,7 @@
- #include "auth.h"
- #include "ntdomain.h"
- #include "rpc_server/srv_pipe.h"
- +#include "../librpc/gen_ndr/ndr_dcerpc.h"
- #include "../librpc/ndr/ndr_dcerpc.h"
-
- #undef DBGC_CLASS
- @@ -270,10 +271,14 @@ static bool setup_bind_nak(struct pipes_
- p->out_data.data_sent_length = 0;
- p->out_data.current_pdu_sent = 0;
-
- + set_incoming_fault(p);
- TALLOC_FREE(p->auth.auth_ctx);
- p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
- p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
- p->pipe_bound = False;
- + p->allow_bind = false;
- + p->allow_alter = false;
- + p->allow_auth3 = false;
-
- return True;
- }
- @@ -339,16 +344,46 @@ static bool check_bind_req(struct pipes_
- DEBUG(3,("check_bind_req for %s\n",
- get_pipe_name_from_syntax(talloc_tos(), abstract)));
-
- + ok = ndr_syntax_id_equal(transfer, &ndr_transfer_syntax);
- + if (!ok) {
- + DEBUG(1,("check_bind_req unknown transfer syntax for "
- + "%s context_id=%u\n",
- + get_pipe_name_from_syntax(talloc_tos(), abstract),
- + (unsigned)context_id));
- + return false;
- + }
- +
- + for (context_fns = p->contexts;
- + context_fns != NULL;
- + context_fns = context_fns->next)
- + {
- + if (context_fns->context_id != context_id) {
- + continue;
- + }
- +
- + ok = ndr_syntax_id_equal(&context_fns->syntax,
- + abstract);
- + if (ok) {
- + return true;
- + }
- +
- + DEBUG(1,("check_bind_req: changing abstract syntax for "
- + "%s context_id=%u into %s not supported\n",
- + get_pipe_name_from_syntax(talloc_tos(), &context_fns->syntax),
- + (unsigned)context_id,
- + get_pipe_name_from_syntax(talloc_tos(), abstract)));
- + return false;
- + }
- +
- /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */
- - if (rpc_srv_pipe_exists_by_id(abstract) &&
- - ndr_syntax_id_equal(transfer, &ndr_transfer_syntax)) {
- - DEBUG(3, ("check_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
- - rpc_srv_get_pipe_cli_name(abstract),
- - rpc_srv_get_pipe_srv_name(abstract)));
- - } else {
- + if (!rpc_srv_pipe_exists_by_id(abstract)) {
- return false;
- }
-
- + DEBUG(3, ("check_bind_req: %s -> %s rpc service\n",
- + rpc_srv_get_pipe_cli_name(abstract),
- + rpc_srv_get_pipe_srv_name(abstract)));
- +
- context_fns = SMB_MALLOC_P(struct pipe_rpc_fns);
- if (context_fns == NULL) {
- DEBUG(0,("check_bind_req: malloc() failed!\n"));
- @@ -447,6 +482,7 @@ static bool pipe_spnego_auth_bind(struct
-
- p->auth.auth_ctx = spnego_ctx;
- p->auth.auth_type = DCERPC_AUTH_TYPE_SPNEGO;
- + p->auth.auth_context_id = auth_info->auth_context_id;
-
- DEBUG(10, ("SPNEGO auth started\n"));
-
- @@ -557,6 +593,7 @@ static bool pipe_schannel_auth_bind(stru
- /* We're finished with this bind - no more packets. */
- p->auth.auth_ctx = schannel_auth;
- p->auth.auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
- + p->auth.auth_context_id = auth_info->auth_context_id;
-
- p->pipe_bound = True;
-
- @@ -601,6 +638,7 @@ static bool pipe_ntlmssp_auth_bind(struc
-
- p->auth.auth_ctx = ntlmssp_state;
- p->auth.auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
- + p->auth.auth_context_id = auth_info->auth_context_id;
-
- DEBUG(10, (__location__ ": NTLMSSP auth started\n"));
-
- @@ -776,6 +814,11 @@ static NTSTATUS pipe_auth_verify_final(s
- void *mech_ctx;
- NTSTATUS status;
-
- + if (p->auth.auth_type == DCERPC_AUTH_TYPE_NONE) {
- + p->pipe_bound = true;
- + return NT_STATUS_OK;
- + }
- +
- switch (p->auth.auth_type) {
- case DCERPC_AUTH_TYPE_NTLMSSP:
- ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx,
- @@ -867,16 +910,38 @@ static bool api_pipe_bind_req(struct pip
- DATA_BLOB auth_resp = data_blob_null;
- DATA_BLOB auth_blob = data_blob_null;
-
- - /* No rebinds on a bound pipe - use alter context. */
- - if (p->pipe_bound) {
- - DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound "
- - "pipe %s.\n",
- - get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
- + if (!p->allow_bind) {
- + DEBUG(2,("Pipe not in allow bind state\n"));
- return setup_bind_nak(p, pkt);
- }
- + p->allow_bind = false;
- +
- + status = dcerpc_verify_ncacn_packet_header(pkt,
- + DCERPC_PKT_BIND,
- + pkt->u.bind.auth_info.length,
- + 0, /* required flags */
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST |
- + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
- + 0x08 | /* this is not defined, but should be ignored */
- + DCERPC_PFC_FLAG_CONC_MPX |
- + DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
- + DCERPC_PFC_FLAG_MAYBE |
- + DCERPC_PFC_FLAG_OBJECT_UUID);
- + if (!NT_STATUS_IS_OK(status)) {
- + DEBUG(1, ("api_pipe_bind_req: invalid pdu: %s\n",
- + nt_errstr(status)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + goto err_exit;
- + }
-
- if (pkt->u.bind.num_contexts == 0) {
- - DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n"));
- + DEBUG(1, ("api_pipe_bind_req: no rpc contexts around\n"));
- + goto err_exit;
- + }
- +
- + if (pkt->u.bind.ctx_list[0].num_transfer_syntaxes == 0) {
- + DEBUG(1, ("api_pipe_bind_req: no transfer syntaxes around\n"));
- goto err_exit;
- }
-
- @@ -960,25 +1025,12 @@ static bool api_pipe_bind_req(struct pip
- * Check if this is an authenticated bind request.
- */
- if (pkt->auth_length) {
- - /* Quick length check. Won't catch a bad auth footer,
- - * prevents overrun. */
- -
- - if (pkt->frag_length < RPC_HEADER_LEN +
- - DCERPC_AUTH_TRAILER_LENGTH +
- - pkt->auth_length) {
- - DEBUG(0,("api_pipe_bind_req: auth_len (%u) "
- - "too long for fragment %u.\n",
- - (unsigned int)pkt->auth_length,
- - (unsigned int)pkt->frag_length));
- - goto err_exit;
- - }
- -
- /*
- * Decode the authentication verifier.
- */
- - status = dcerpc_pull_dcerpc_auth(pkt,
- - &pkt->u.bind.auth_info,
- - &auth_info, p->endian);
- + status = dcerpc_pull_auth_trailer(pkt, pkt,
- + &pkt->u.bind.auth_info,
- + &auth_info, NULL, true);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
- goto err_exit;
- @@ -1072,6 +1124,7 @@ static bool api_pipe_bind_req(struct pip
- p->pipe_bound = True;
- /* The session key was initialized from the SMB
- * session in make_internal_rpc_pipe_p */
- + p->auth.auth_context_id = 0;
- }
-
- ZERO_STRUCT(u.bind_ack);
- @@ -1113,15 +1166,15 @@ static bool api_pipe_bind_req(struct pip
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
- nt_errstr(status)));
- + goto err_exit;
- }
-
- if (auth_resp.length) {
- -
- status = dcerpc_push_dcerpc_auth(pkt,
- auth_type,
- auth_info.auth_level,
- - 0,
- - 1, /* auth_context_id */
- + 0, /* pad_len */
- + p->auth.auth_context_id,
- &auth_resp,
- &auth_blob);
- if (!NT_STATUS_IS_OK(status)) {
- @@ -1152,6 +1205,22 @@ static bool api_pipe_bind_req(struct pip
- p->out_data.current_pdu_sent = 0;
-
- TALLOC_FREE(auth_blob.data);
- +
- + if (bind_ack_ctx.result == 0) {
- + p->allow_alter = true;
- + p->allow_auth3 = true;
- + if (p->auth.auth_type == DCERPC_AUTH_TYPE_NONE) {
- + status = pipe_auth_verify_final(p);
- + if (!NT_STATUS_IS_OK(status)) {
- + DEBUG(0, ("pipe_auth_verify_final failed: %s\n",
- + nt_errstr(status)));
- + goto err_exit;
- + }
- + }
- + } else {
- + goto err_exit;
- + }
- +
- return True;
-
- err_exit:
- @@ -1176,18 +1245,39 @@ bool api_pipe_bind_auth3(struct pipes_st
-
- DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__));
-
- - if (pkt->auth_length == 0) {
- - DEBUG(0, ("No auth field sent for bind request!\n"));
- + if (!p->allow_auth3) {
- + DEBUG(1, ("Pipe not in allow auth3 state.\n"));
- goto err;
- }
-
- - /* Ensure there's enough data for an authenticated request. */
- - if (pkt->frag_length < RPC_HEADER_LEN
- - + DCERPC_AUTH_TRAILER_LENGTH
- - + pkt->auth_length) {
- - DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len "
- - "%u is too large.\n",
- - (unsigned int)pkt->auth_length));
- + status = dcerpc_verify_ncacn_packet_header(pkt,
- + DCERPC_PKT_AUTH3,
- + pkt->u.auth3.auth_info.length,
- + 0, /* required flags */
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST |
- + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
- + 0x08 | /* this is not defined, but should be ignored */
- + DCERPC_PFC_FLAG_CONC_MPX |
- + DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
- + DCERPC_PFC_FLAG_MAYBE |
- + DCERPC_PFC_FLAG_OBJECT_UUID);
- + if (!NT_STATUS_IS_OK(status)) {
- + DEBUG(1, ("api_pipe_bind_auth3: invalid pdu: %s\n",
- + nt_errstr(status)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + goto err;
- + }
- +
- + /* We can only finish if the pipe is unbound for now */
- + if (p->pipe_bound) {
- + DEBUG(0, (__location__ ": Pipe already bound, "
- + "AUTH3 not supported!\n"));
- + goto err;
- + }
- +
- + if (pkt->auth_length == 0) {
- + DEBUG(1, ("No auth field sent for auth3 request!\n"));
- goto err;
- }
-
- @@ -1195,9 +1285,9 @@ bool api_pipe_bind_auth3(struct pipes_st
- * Decode the authentication verifier response.
- */
-
- - status = dcerpc_pull_dcerpc_auth(pkt,
- - &pkt->u.auth3.auth_info,
- - &auth_info, p->endian);
- + status = dcerpc_pull_auth_trailer(pkt, pkt,
- + &pkt->u.auth3.auth_info,
- + &auth_info, NULL, true);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
- goto err;
- @@ -1215,6 +1305,21 @@ bool api_pipe_bind_auth3(struct pipes_st
- goto err;
- }
-
- + if (auth_info.auth_level != p->auth.auth_level) {
- + DEBUG(1, ("Auth level mismatch! Client sent %d, "
- + "but auth was started as level %d!\n",
- + auth_info.auth_level, p->auth.auth_level));
- + goto err;
- + }
- +
- + if (auth_info.auth_context_id != p->auth.auth_context_id) {
- + DEBUG(0, ("Auth context id mismatch! Client sent %u, "
- + "but auth was started as level %u!\n",
- + (unsigned)auth_info.auth_context_id,
- + (unsigned)p->auth.auth_context_id));
- + goto err;
- + }
- +
- switch (auth_info.auth_type) {
- case DCERPC_AUTH_TYPE_NTLMSSP:
- ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx,
- @@ -1267,6 +1372,10 @@ bool api_pipe_bind_auth3(struct pipes_st
- return true;
-
- err:
- + p->pipe_bound = false;
- + p->allow_bind = false;
- + p->allow_alter = false;
- + p->allow_auth3 = false;
-
- TALLOC_FREE(p->auth.auth_ctx);
- return false;
- @@ -1284,7 +1393,7 @@ static bool api_pipe_alter_context(struc
- uint16 assoc_gid;
- NTSTATUS status;
- union dcerpc_payload u;
- - struct dcerpc_ack_ctx bind_ack_ctx;
- + struct dcerpc_ack_ctx alter_ack_ctx;
- DATA_BLOB auth_resp = data_blob_null;
- DATA_BLOB auth_blob = data_blob_null;
- int pad_len = 0;
- @@ -1294,8 +1403,42 @@ static bool api_pipe_alter_context(struc
-
- DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__));
-
- - if (pkt->u.bind.assoc_group_id != 0) {
- - assoc_gid = pkt->u.bind.assoc_group_id;
- + if (!p->allow_alter) {
- + DEBUG(1, ("Pipe not in allow alter state.\n"));
- + goto err_exit;
- + }
- +
- + status = dcerpc_verify_ncacn_packet_header(pkt,
- + DCERPC_PKT_ALTER,
- + pkt->u.alter.auth_info.length,
- + 0, /* required flags */
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST |
- + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
- + 0x08 | /* this is not defined, but should be ignored */
- + DCERPC_PFC_FLAG_CONC_MPX |
- + DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
- + DCERPC_PFC_FLAG_MAYBE |
- + DCERPC_PFC_FLAG_OBJECT_UUID);
- + if (!NT_STATUS_IS_OK(status)) {
- + DEBUG(1, ("api_pipe_alter_context: invalid pdu: %s\n",
- + nt_errstr(status)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + goto err_exit;
- + }
- +
- + if (pkt->u.alter.num_contexts == 0) {
- + DEBUG(1, ("api_pipe_alter_context: no rpc contexts around\n"));
- + goto err_exit;
- + }
- +
- + if (pkt->u.alter.ctx_list[0].num_transfer_syntaxes == 0) {
- + DEBUG(1, ("api_pipe_alter_context: no transfer syntaxes around\n"));
- + goto err_exit;
- + }
- +
- + if (pkt->u.alter.assoc_group_id != 0) {
- + assoc_gid = pkt->u.alter.assoc_group_id;
- } else {
- assoc_gid = 0x53f0;
- }
- @@ -1305,59 +1448,45 @@ static bool api_pipe_alter_context(struc
- */
-
- /* If the requested abstract synt uuid doesn't match our client pipe,
- - reject the bind_ack & set the transfer interface synt to all 0's,
- + reject the alter_ack & set the transfer interface synt to all 0's,
- ver 0 (observed when NT5 attempts to bind to abstract interfaces
- unknown to NT4)
- Needed when adding entries to a DACL from NT5 - SK */
-
- if (check_bind_req(p,
- - &pkt->u.bind.ctx_list[0].abstract_syntax,
- - &pkt->u.bind.ctx_list[0].transfer_syntaxes[0],
- - pkt->u.bind.ctx_list[0].context_id)) {
- -
- - bind_ack_ctx.result = 0;
- - bind_ack_ctx.reason = 0;
- - bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
- + &pkt->u.alter.ctx_list[0].abstract_syntax,
- + &pkt->u.alter.ctx_list[0].transfer_syntaxes[0],
- + pkt->u.alter.ctx_list[0].context_id)) {
- +
- + alter_ack_ctx.result = 0;
- + alter_ack_ctx.reason = 0;
- + alter_ack_ctx.syntax = pkt->u.alter.ctx_list[0].transfer_syntaxes[0];
- } else {
- - p->pipe_bound = False;
- /* Rejection reason: abstract syntax not supported */
- - bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
- - bind_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX;
- - bind_ack_ctx.syntax = null_ndr_syntax_id;
- + alter_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
- + alter_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX;
- + alter_ack_ctx.syntax = null_ndr_syntax_id;
- }
-
- /*
- * Check if this is an authenticated alter context request.
- */
- if (pkt->auth_length) {
- - /* Quick length check. Won't catch a bad auth footer,
- - * prevents overrun. */
- -
- - if (pkt->frag_length < RPC_HEADER_LEN +
- - DCERPC_AUTH_TRAILER_LENGTH +
- - pkt->auth_length) {
- - DEBUG(0,("api_pipe_alter_context: auth_len (%u) "
- - "too long for fragment %u.\n",
- - (unsigned int)pkt->auth_length,
- - (unsigned int)pkt->frag_length ));
- + /* We can only finish if the pipe is unbound for now */
- + if (p->pipe_bound) {
- + DEBUG(0, (__location__ ": Pipe already bound, "
- + "Altering Context not yet supported!\n"));
- goto err_exit;
- }
-
- - status = dcerpc_pull_dcerpc_auth(pkt,
- - &pkt->u.bind.auth_info,
- - &auth_info, p->endian);
- + status = dcerpc_pull_auth_trailer(pkt, pkt,
- + &pkt->u.alter.auth_info,
- + &auth_info, NULL, true);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
- goto err_exit;
- }
-
- - /* We can only finish if the pipe is unbound for now */
- - if (p->pipe_bound) {
- - DEBUG(0, (__location__ ": Pipe already bound, "
- - "Altering Context not yet supported!\n"));
- - goto err_exit;
- - }
- -
- if (auth_info.auth_type != p->auth.auth_type) {
- DEBUG(0, ("Auth type mismatch! Client sent %d, "
- "but auth was started as type %d!\n",
- @@ -1365,6 +1494,20 @@ static bool api_pipe_alter_context(struc
- goto err_exit;
- }
-
- + if (auth_info.auth_level != p->auth.auth_level) {
- + DEBUG(0, ("Auth level mismatch! Client sent %d, "
- + "but auth was started as level %d!\n",
- + auth_info.auth_level, p->auth.auth_level));
- + goto err_exit;
- + }
- +
- + if (auth_info.auth_context_id != p->auth.auth_context_id) {
- + DEBUG(0, ("Auth context id mismatch! Client sent %u, "
- + "but auth was started as level %u!\n",
- + (unsigned)auth_info.auth_context_id,
- + (unsigned)p->auth.auth_context_id));
- + goto err_exit;
- + }
-
- switch (auth_info.auth_type) {
- case DCERPC_AUTH_TYPE_SPNEGO:
- @@ -1431,7 +1574,7 @@ static bool api_pipe_alter_context(struc
- u.alter_resp.secondary_address_size = 1;
-
- u.alter_resp.num_results = 1;
- - u.alter_resp.ctx_list = &bind_ack_ctx;
- + u.alter_resp.ctx_list = &alter_ack_ctx;
-
- /* NOTE: We leave the auth_info empty so we can calculate the padding
- * later and then append the auth_info --simo */
- @@ -1451,8 +1594,9 @@ static bool api_pipe_alter_context(struc
- &u,
- &p->out_data.frag);
- if (!NT_STATUS_IS_OK(status)) {
- - DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
- + DEBUG(0, ("Failed to marshall alter_resp packet. (%s)\n",
- nt_errstr(status)));
- + goto err_exit;
- }
-
- if (auth_resp.length) {
- @@ -1469,7 +1613,7 @@ static bool api_pipe_alter_context(struc
- auth_info.auth_type,
- auth_info.auth_level,
- pad_len,
- - 1, /* auth_context_id */
- + p->auth.auth_context_id,
- &auth_resp,
- &auth_blob);
- if (!NT_STATUS_IS_OK(status)) {
- @@ -1618,6 +1762,7 @@ static bool api_pipe_request(struct pipe
-
- if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) {
- DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n"));
- + set_incoming_fault(p);
- setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED));
- data_blob_free(&p->out_data.rdata);
- TALLOC_FREE(frame);
- @@ -1756,7 +1901,11 @@ void set_incoming_fault(struct pipes_str
- data_blob_free(&p->in_data.data);
- p->in_data.pdu_needed_len = 0;
- p->in_data.pdu.length = 0;
- - p->fault_state = DCERPC_FAULT_CANT_PERFORM;
- + p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
- +
- + p->allow_alter = false;
- + p->allow_auth3 = false;
- + p->pipe_bound = false;
-
- DEBUG(10, ("Setting fault state\n"));
- }
- @@ -1767,7 +1916,6 @@ static NTSTATUS dcesrv_auth_request(stru
- {
- NTSTATUS status;
- size_t hdr_size = DCERPC_REQUEST_LENGTH;
- - size_t pad_len;
-
- DEBUG(10, ("Checking request auth.\n"));
-
- @@ -1778,25 +1926,11 @@ static NTSTATUS dcesrv_auth_request(stru
- /* in case of sealing this function will unseal the data in place */
- status = dcerpc_check_auth(auth, pkt,
- &pkt->u.request.stub_and_verifier,
- - hdr_size, raw_pkt,
- - &pad_len);
- + hdr_size, raw_pkt);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- -
- - /* remove padding and auth trailer,
- - * this way the caller will get just the data */
- - if (pkt->auth_length) {
- - size_t trail_len = pad_len
- - + DCERPC_AUTH_TRAILER_LENGTH
- - + pkt->auth_length;
- - if (pkt->u.request.stub_and_verifier.length < trail_len) {
- - return NT_STATUS_INFO_LENGTH_MISMATCH;
- - }
- - pkt->u.request.stub_and_verifier.length -= trail_len;
- - }
- -
- return NT_STATUS_OK;
- }
-
- @@ -1816,6 +1950,29 @@ static bool process_request_pdu(struct p
- return False;
- }
-
- + /*
- + * We don't ignore DCERPC_PFC_FLAG_PENDING_CANCEL.
- + * TODO: we can reject it with DCERPC_FAULT_NO_CALL_ACTIVE later.
- + */
- + status = dcerpc_verify_ncacn_packet_header(pkt,
- + DCERPC_PKT_REQUEST,
- + pkt->u.request.stub_and_verifier.length,
- + 0, /* required_flags */
- + DCERPC_PFC_FLAG_FIRST |
- + DCERPC_PFC_FLAG_LAST |
- + 0x08 | /* this is not defined, but should be ignored */
- + DCERPC_PFC_FLAG_CONC_MPX |
- + DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
- + DCERPC_PFC_FLAG_MAYBE |
- + DCERPC_PFC_FLAG_OBJECT_UUID);
- + if (!NT_STATUS_IS_OK(status)) {
- + DEBUG(1, ("process_request_pdu: invalid pdu: %s\n",
- + nt_errstr(status)));
- + NDR_PRINT_DEBUG(ncacn_packet, pkt);
- + set_incoming_fault(p);
- + return false;
- + }
- +
- /* Store the opnum */
- p->opnum = pkt->u.request.opnum;
-
- @@ -2065,7 +2222,7 @@ done:
- "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(),
- &p->syntax)));
- set_incoming_fault(p);
- - setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
- + setup_fault_pdu(p, NT_STATUS(DCERPC_NCA_S_PROTO_ERROR));
- TALLOC_FREE(pkt);
- } else {
- /*
- --- a/source3/include/ntdomain.h
- +++ b/source3/include/ntdomain.h
- @@ -135,6 +135,13 @@ struct pipes_struct {
- bool pipe_bound;
-
- /*
- + * States we can be in.
- + */
- + bool allow_alter;
- + bool allow_bind;
- + bool allow_auth3;
- +
- + /*
- * Set the DCERPC_FAULT to return.
- */
-
- --- a/source3/rpc_server/rpc_ncacn_np.c
- +++ b/source3/rpc_server/rpc_ncacn_np.c
- @@ -171,6 +171,7 @@ struct pipes_struct *make_internal_rpc_p
-
- p->syntax = *syntax;
- p->transport = NCALRPC;
- + p->allow_bind = true;
-
- DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n",
- get_pipe_name_from_syntax(talloc_tos(), syntax), pipes_open));
- @@ -780,6 +781,7 @@ static NTSTATUS rpc_pipe_open_external(T
- }
- result->auth->auth_type = DCERPC_AUTH_TYPE_NONE;
- result->auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
- + result->auth->auth_context_id = 0;
-
- status = rpccli_anon_bind_data(result, &auth);
- if (!NT_STATUS_IS_OK(status)) {
- --- a/source3/rpc_server/rpc_server.c
- +++ b/source3/rpc_server/rpc_server.c
- @@ -102,6 +102,7 @@ static int make_server_pipes_struct(TALL
- p->syntax = id;
- p->transport = transport;
- p->ncalrpc_as_system = ncalrpc_as_system;
- + p->allow_bind = true;
-
- p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
- if (!p->mem_ctx) {
- @@ -663,6 +664,12 @@ static void named_pipe_packet_done(struc
- goto fail;
- }
-
- + if (npc->p->fault_state != 0) {
- + DEBUG(2, ("Disconnect after fault\n"));
- + sys_errno = EINVAL;
- + goto fail;
- + }
- +
- /* clear out any data that may have been left around */
- npc->count = 0;
- TALLOC_FREE(npc->iov);
- @@ -1391,6 +1398,12 @@ static void dcerpc_ncacn_packet_done(str
- goto fail;
- }
-
- + if (ncacn_conn->p->fault_state != 0) {
- + DEBUG(2, ("Disconnect after fault\n"));
- + sys_errno = EINVAL;
- + goto fail;
- + }
- +
- /* clear out any data that may have been left around */
- ncacn_conn->count = 0;
- TALLOC_FREE(ncacn_conn->iov);
|