1
0

022-CVE-2015-5370-v3-6.patch 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791
  1. From 8716bb5e03cc4f10e2d4edc704d8defe7e8045f1 Mon Sep 17 00:00:00 2001
  2. From: Stefan Metzmacher <metze@samba.org>
  3. Date: Thu, 16 Jul 2015 22:46:05 +0200
  4. Subject: [PATCH 01/40] CVE-2015-5370: dcerpc.idl: add
  5. DCERPC_{NCACN_PAYLOAD,FRAG}_MAX_SIZE defines
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11344
  10. Signed-off-by: Stefan Metzmacher <metze@samba.org>
  11. Reviewed-by: Günther Deschner <gd@samba.org>
  12. ---
  13. librpc/idl/dcerpc.idl | 2 ++
  14. 1 file changed, 2 insertions(+)
  15. --- a/librpc/idl/dcerpc.idl
  16. +++ b/librpc/idl/dcerpc.idl
  17. @@ -475,9 +475,11 @@ interface dcerpc
  18. const uint8 DCERPC_PFC_OFFSET = 3;
  19. const uint8 DCERPC_DREP_OFFSET = 4;
  20. const uint8 DCERPC_FRAG_LEN_OFFSET = 8;
  21. + const uint32 DCERPC_FRAG_MAX_SIZE = 5840;
  22. const uint8 DCERPC_AUTH_LEN_OFFSET = 10;
  23. const uint8 DCERPC_CALL_ID_OFFSET = 12;
  24. const uint8 DCERPC_NCACN_PAYLOAD_OFFSET = 16;
  25. + const uint32 DCERPC_NCACN_PAYLOAD_MAX_SIZE = 0x400000; /* 4 MByte */
  26. /* little-endian flag */
  27. const uint8 DCERPC_DREP_LE = 0x10;
  28. --- a/librpc/rpc/dcerpc_util.c
  29. +++ b/librpc/rpc/dcerpc_util.c
  30. @@ -92,31 +92,49 @@ uint8_t dcerpc_get_endian_flag(DATA_BLOB
  31. *
  32. * @return - A NTSTATUS error code.
  33. */
  34. -NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
  35. +NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
  36. TALLOC_CTX *mem_ctx,
  37. - DATA_BLOB *pkt_trailer,
  38. + const DATA_BLOB *pkt_trailer,
  39. struct dcerpc_auth *auth,
  40. - uint32_t *auth_length,
  41. + uint32_t *_auth_length,
  42. bool auth_data_only)
  43. {
  44. struct ndr_pull *ndr;
  45. enum ndr_err_code ndr_err;
  46. - uint32_t data_and_pad;
  47. + uint16_t data_and_pad;
  48. + uint16_t auth_length;
  49. + uint32_t tmp_length;
  50. - data_and_pad = pkt_trailer->length
  51. - - (DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length);
  52. + ZERO_STRUCTP(auth);
  53. + if (_auth_length != NULL) {
  54. + *_auth_length = 0;
  55. + }
  56. +
  57. + /* Paranoia checks for auth_length. The caller should check this... */
  58. + if (pkt->auth_length == 0) {
  59. + return NT_STATUS_INTERNAL_ERROR;
  60. + }
  61. +
  62. + /* Paranoia checks for auth_length. The caller should check this... */
  63. + if (pkt->auth_length > pkt->frag_length) {
  64. + return NT_STATUS_INTERNAL_ERROR;
  65. + }
  66. + tmp_length = DCERPC_NCACN_PAYLOAD_OFFSET;
  67. + tmp_length += DCERPC_AUTH_TRAILER_LENGTH;
  68. + tmp_length += pkt->auth_length;
  69. + if (tmp_length > pkt->frag_length) {
  70. + return NT_STATUS_INTERNAL_ERROR;
  71. + }
  72. + if (pkt_trailer->length > UINT16_MAX) {
  73. + return NT_STATUS_INTERNAL_ERROR;
  74. + }
  75. - /* paranoia check for pad size. This would be caught anyway by
  76. - the ndr_pull_advance() a few lines down, but it scared
  77. - Jeremy enough for him to call me, so we might as well check
  78. - it now, just to prevent someone posting a bogus YouTube
  79. - video in the future.
  80. - */
  81. - if (data_and_pad > pkt_trailer->length) {
  82. - return NT_STATUS_INFO_LENGTH_MISMATCH;
  83. + auth_length = DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length;
  84. + if (pkt_trailer->length < auth_length) {
  85. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  86. }
  87. - *auth_length = pkt_trailer->length - data_and_pad;
  88. + data_and_pad = pkt_trailer->length - auth_length;
  89. ndr = ndr_pull_init_blob(pkt_trailer, mem_ctx);
  90. if (!ndr) {
  91. @@ -136,14 +154,28 @@ NTSTATUS dcerpc_pull_auth_trailer(struct
  92. ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth);
  93. if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
  94. talloc_free(ndr);
  95. + ZERO_STRUCTP(auth);
  96. return ndr_map_error2ntstatus(ndr_err);
  97. }
  98. + if (data_and_pad < auth->auth_pad_length) {
  99. + DEBUG(1, (__location__ ": ERROR: pad length mismatch. "
  100. + "Calculated %u got %u\n",
  101. + (unsigned)data_and_pad,
  102. + (unsigned)auth->auth_pad_length));
  103. + talloc_free(ndr);
  104. + ZERO_STRUCTP(auth);
  105. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  106. + }
  107. +
  108. if (auth_data_only && data_and_pad != auth->auth_pad_length) {
  109. - DEBUG(1, (__location__ ": WARNING: pad length mismatch. "
  110. + DEBUG(1, (__location__ ": ERROR: pad length mismatch. "
  111. "Calculated %u got %u\n",
  112. (unsigned)data_and_pad,
  113. (unsigned)auth->auth_pad_length));
  114. + talloc_free(ndr);
  115. + ZERO_STRUCTP(auth);
  116. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  117. }
  118. DEBUG(6,(__location__ ": auth_pad_length %u\n",
  119. @@ -152,6 +184,83 @@ NTSTATUS dcerpc_pull_auth_trailer(struct
  120. talloc_steal(mem_ctx, auth->credentials.data);
  121. talloc_free(ndr);
  122. + if (_auth_length != NULL) {
  123. + *_auth_length = auth_length;
  124. + }
  125. +
  126. + return NT_STATUS_OK;
  127. +}
  128. +
  129. +/**
  130. +* @brief Verify the fields in ncacn_packet header.
  131. +*
  132. +* @param pkt - The ncacn_packet strcuture
  133. +* @param ptype - The expected PDU type
  134. +* @param max_auth_info - The maximum size of a possible auth trailer
  135. +* @param required_flags - The required flags for the pdu.
  136. +* @param optional_flags - The possible optional flags for the pdu.
  137. +*
  138. +* @return - A NTSTATUS error code.
  139. +*/
  140. +NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
  141. + enum dcerpc_pkt_type ptype,
  142. + size_t max_auth_info,
  143. + uint8_t required_flags,
  144. + uint8_t optional_flags)
  145. +{
  146. + if (pkt->rpc_vers != 5) {
  147. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  148. + }
  149. +
  150. + if (pkt->rpc_vers_minor != 0) {
  151. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  152. + }
  153. +
  154. + if (pkt->auth_length > pkt->frag_length) {
  155. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  156. + }
  157. +
  158. + if (pkt->ptype != ptype) {
  159. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  160. + }
  161. +
  162. + if (max_auth_info > UINT16_MAX) {
  163. + return NT_STATUS_INTERNAL_ERROR;
  164. + }
  165. +
  166. + if (pkt->auth_length > 0) {
  167. + size_t max_auth_length;
  168. +
  169. + if (max_auth_info <= DCERPC_AUTH_TRAILER_LENGTH) {
  170. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  171. + }
  172. + max_auth_length = max_auth_info - DCERPC_AUTH_TRAILER_LENGTH;
  173. +
  174. + if (pkt->auth_length > max_auth_length) {
  175. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  176. + }
  177. + }
  178. +
  179. + if ((pkt->pfc_flags & required_flags) != required_flags) {
  180. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  181. + }
  182. + if (pkt->pfc_flags & ~(optional_flags|required_flags)) {
  183. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  184. + }
  185. +
  186. + if (pkt->drep[0] & ~DCERPC_DREP_LE) {
  187. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  188. + }
  189. + if (pkt->drep[1] != 0) {
  190. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  191. + }
  192. + if (pkt->drep[2] != 0) {
  193. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  194. + }
  195. + if (pkt->drep[3] != 0) {
  196. + return NT_STATUS_RPC_PROTOCOL_ERROR;
  197. + }
  198. +
  199. return NT_STATUS_OK;
  200. }
  201. --- a/librpc/rpc/rpc_common.h
  202. +++ b/librpc/rpc/rpc_common.h
  203. @@ -158,12 +158,17 @@ uint8_t dcerpc_get_endian_flag(DATA_BLOB
  204. *
  205. * @return - A NTSTATUS error code.
  206. */
  207. -NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
  208. +NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
  209. TALLOC_CTX *mem_ctx,
  210. - DATA_BLOB *pkt_trailer,
  211. + const DATA_BLOB *pkt_trailer,
  212. struct dcerpc_auth *auth,
  213. uint32_t *auth_length,
  214. bool auth_data_only);
  215. +NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
  216. + enum dcerpc_pkt_type ptype,
  217. + size_t max_auth_info,
  218. + uint8_t required_flags,
  219. + uint8_t optional_flags);
  220. struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
  221. struct tevent_context *ev,
  222. struct tstream_context *stream);
  223. --- a/source3/librpc/rpc/dcerpc_helpers.c
  224. +++ b/source3/librpc/rpc/dcerpc_helpers.c
  225. @@ -210,47 +210,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_
  226. }
  227. /**
  228. -* @brief Decodes a dcerpc_auth blob
  229. -*
  230. -* @param mem_ctx The memory context on which to allocate the packet
  231. -* elements
  232. -* @param blob The blob of data to decode
  233. -* @param r An empty dcerpc_auth structure, must not be NULL
  234. -*
  235. -* @return a NTSTATUS error code
  236. -*/
  237. -NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
  238. - const DATA_BLOB *blob,
  239. - struct dcerpc_auth *r,
  240. - bool bigendian)
  241. -{
  242. - enum ndr_err_code ndr_err;
  243. - struct ndr_pull *ndr;
  244. -
  245. - ndr = ndr_pull_init_blob(blob, mem_ctx);
  246. - if (!ndr) {
  247. - return NT_STATUS_NO_MEMORY;
  248. - }
  249. - if (bigendian) {
  250. - ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
  251. - }
  252. -
  253. - ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r);
  254. -
  255. - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
  256. - talloc_free(ndr);
  257. - return ndr_map_error2ntstatus(ndr_err);
  258. - }
  259. - talloc_free(ndr);
  260. -
  261. - if (DEBUGLEVEL >= 10) {
  262. - NDR_PRINT_DEBUG(dcerpc_auth, r);
  263. - }
  264. -
  265. - return NT_STATUS_OK;
  266. -}
  267. -
  268. -/**
  269. * @brief Calculate how much data we can in a packet, including calculating
  270. * auth token and pad lengths.
  271. *
  272. @@ -782,7 +741,7 @@ NTSTATUS dcerpc_add_auth_footer(struct p
  273. auth->auth_type,
  274. auth->auth_level,
  275. pad_len,
  276. - 1 /* context id. */,
  277. + auth->auth_context_id,
  278. &auth_blob,
  279. &auth_info);
  280. if (!NT_STATUS_IS_OK(status)) {
  281. @@ -844,19 +803,18 @@ NTSTATUS dcerpc_add_auth_footer(struct p
  282. *
  283. * @param auth The auth data for the connection
  284. * @param pkt The actual ncacn_packet
  285. -* @param pkt_trailer The stub_and_verifier part of the packet
  286. +* @param pkt_trailer [in][out] The stub_and_verifier part of the packet,
  287. +* the auth_trailer and padding will be removed.
  288. * @param header_size The header size
  289. * @param raw_pkt The whole raw packet data blob
  290. -* @param pad_len [out] The padding length used in the packet
  291. *
  292. * @return A NTSTATUS error code
  293. */
  294. NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
  295. struct ncacn_packet *pkt,
  296. DATA_BLOB *pkt_trailer,
  297. - size_t header_size,
  298. - DATA_BLOB *raw_pkt,
  299. - size_t *pad_len)
  300. + uint8_t header_size,
  301. + DATA_BLOB *raw_pkt)
  302. {
  303. struct schannel_state *schannel_auth;
  304. struct auth_ntlmssp_state *ntlmssp_ctx;
  305. @@ -868,6 +826,14 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
  306. DATA_BLOB full_pkt;
  307. DATA_BLOB data;
  308. + /*
  309. + * These check should be done in the caller.
  310. + */
  311. + SMB_ASSERT(raw_pkt->length == pkt->frag_length);
  312. + SMB_ASSERT(header_size <= pkt->frag_length);
  313. + SMB_ASSERT(pkt_trailer->length < pkt->frag_length);
  314. + SMB_ASSERT((pkt_trailer->length + header_size) <= pkt->frag_length);
  315. +
  316. switch (auth->auth_level) {
  317. case DCERPC_AUTH_LEVEL_PRIVACY:
  318. DEBUG(10, ("Requested Privacy.\n"));
  319. @@ -881,7 +847,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
  320. if (pkt->auth_length != 0) {
  321. break;
  322. }
  323. - *pad_len = 0;
  324. return NT_STATUS_OK;
  325. case DCERPC_AUTH_LEVEL_NONE:
  326. @@ -890,7 +855,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
  327. "authenticated connection!\n"));
  328. return NT_STATUS_INVALID_PARAMETER;
  329. }
  330. - *pad_len = 0;
  331. return NT_STATUS_OK;
  332. default:
  333. @@ -899,16 +863,8 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
  334. return NT_STATUS_INVALID_PARAMETER;
  335. }
  336. - /* Paranioa checks for auth_length. */
  337. - if (pkt->auth_length > pkt->frag_length) {
  338. - return NT_STATUS_INFO_LENGTH_MISMATCH;
  339. - }
  340. - if (((unsigned int)pkt->auth_length
  341. - + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
  342. - ((unsigned int)pkt->auth_length
  343. - + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
  344. - /* Integer wrap attempt. */
  345. - return NT_STATUS_INFO_LENGTH_MISMATCH;
  346. + if (pkt->auth_length == 0) {
  347. + return NT_STATUS_INVALID_PARAMETER;
  348. }
  349. status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
  350. @@ -917,10 +873,23 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
  351. return status;
  352. }
  353. + if (auth_info.auth_type != auth->auth_type) {
  354. + return NT_STATUS_INVALID_PARAMETER;
  355. + }
  356. +
  357. + if (auth_info.auth_level != auth->auth_level) {
  358. + return NT_STATUS_INVALID_PARAMETER;
  359. + }
  360. +
  361. + if (auth_info.auth_context_id != auth->auth_context_id) {
  362. + return NT_STATUS_INVALID_PARAMETER;
  363. + }
  364. +
  365. + pkt_trailer->length -= auth_length;
  366. data = data_blob_const(raw_pkt->data + header_size,
  367. - pkt_trailer->length - auth_length);
  368. - full_pkt = data_blob_const(raw_pkt->data,
  369. - raw_pkt->length - auth_info.credentials.length);
  370. + pkt_trailer->length);
  371. + full_pkt = data_blob_const(raw_pkt->data, raw_pkt->length);
  372. + full_pkt.length -= auth_info.credentials.length;
  373. switch (auth->auth_type) {
  374. case DCERPC_AUTH_TYPE_NONE:
  375. @@ -996,10 +965,13 @@ NTSTATUS dcerpc_check_auth(struct pipe_a
  376. * pkt_trailer actually has a copy of the raw data, and they
  377. * are still both used in later calls */
  378. if (auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
  379. + if (pkt_trailer->length != data.length) {
  380. + return NT_STATUS_INVALID_PARAMETER;
  381. + }
  382. memcpy(pkt_trailer->data, data.data, data.length);
  383. }
  384. - *pad_len = auth_info.auth_pad_length;
  385. + pkt_trailer->length -= auth_info.auth_pad_length;
  386. data_blob_free(&auth_info.credentials);
  387. return NT_STATUS_OK;
  388. }
  389. --- a/source3/rpc_client/cli_pipe.c
  390. +++ b/source3/rpc_client/cli_pipe.c
  391. @@ -404,9 +404,9 @@ static NTSTATUS cli_pipe_validate_curren
  392. DATA_BLOB *rdata,
  393. DATA_BLOB *reply_pdu)
  394. {
  395. - struct dcerpc_response *r;
  396. + const struct dcerpc_response *r = NULL;
  397. + DATA_BLOB tmp_stub = data_blob_null;
  398. NTSTATUS ret = NT_STATUS_OK;
  399. - size_t pad_len = 0;
  400. /*
  401. * Point the return values at the real data including the RPC
  402. @@ -414,50 +414,128 @@ static NTSTATUS cli_pipe_validate_curren
  403. */
  404. *rdata = *pdu;
  405. + if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
  406. + !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
  407. + /*
  408. + * TODO: do we still need this hack which was introduced
  409. + * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
  410. + *
  411. + * I don't even know what AS/U might be...
  412. + */
  413. + DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
  414. + "fragment first/last ON.\n"));
  415. + pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
  416. + }
  417. +
  418. /* Ensure we have the correct type. */
  419. switch (pkt->ptype) {
  420. - case DCERPC_PKT_ALTER_RESP:
  421. + case DCERPC_PKT_BIND_NAK:
  422. + DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
  423. + rpccli_pipe_txt(talloc_tos(), cli)));
  424. +
  425. + ret = dcerpc_verify_ncacn_packet_header(pkt,
  426. + DCERPC_PKT_BIND_NAK,
  427. + 0, /* max_auth_info */
  428. + DCERPC_PFC_FLAG_FIRST |
  429. + DCERPC_PFC_FLAG_LAST,
  430. + 0); /* optional flags */
  431. + if (!NT_STATUS_IS_OK(ret)) {
  432. + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
  433. + "RPC packet type - %u, expected %u: %s\n",
  434. + rpccli_pipe_txt(talloc_tos(), cli),
  435. + pkt->ptype, expected_pkt_type,
  436. + nt_errstr(ret)));
  437. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  438. + return ret;
  439. + }
  440. +
  441. + /* Use this for now... */
  442. + return NT_STATUS_NETWORK_ACCESS_DENIED;
  443. +
  444. case DCERPC_PKT_BIND_ACK:
  445. + ret = dcerpc_verify_ncacn_packet_header(pkt,
  446. + expected_pkt_type,
  447. + pkt->u.bind_ack.auth_info.length,
  448. + DCERPC_PFC_FLAG_FIRST |
  449. + DCERPC_PFC_FLAG_LAST,
  450. + DCERPC_PFC_FLAG_CONC_MPX |
  451. + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
  452. + if (!NT_STATUS_IS_OK(ret)) {
  453. + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
  454. + "RPC packet type - %u, expected %u: %s\n",
  455. + rpccli_pipe_txt(talloc_tos(), cli),
  456. + pkt->ptype, expected_pkt_type,
  457. + nt_errstr(ret)));
  458. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  459. + return ret;
  460. + }
  461. - /* Client code never receives this kind of packets */
  462. break;
  463. + case DCERPC_PKT_ALTER_RESP:
  464. + ret = dcerpc_verify_ncacn_packet_header(pkt,
  465. + expected_pkt_type,
  466. + pkt->u.alter_resp.auth_info.length,
  467. + DCERPC_PFC_FLAG_FIRST |
  468. + DCERPC_PFC_FLAG_LAST,
  469. + DCERPC_PFC_FLAG_CONC_MPX |
  470. + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
  471. + if (!NT_STATUS_IS_OK(ret)) {
  472. + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
  473. + "RPC packet type - %u, expected %u: %s\n",
  474. + rpccli_pipe_txt(talloc_tos(), cli),
  475. + pkt->ptype, expected_pkt_type,
  476. + nt_errstr(ret)));
  477. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  478. + return ret;
  479. + }
  480. +
  481. + break;
  482. case DCERPC_PKT_RESPONSE:
  483. r = &pkt->u.response;
  484. + ret = dcerpc_verify_ncacn_packet_header(pkt,
  485. + expected_pkt_type,
  486. + r->stub_and_verifier.length,
  487. + 0, /* required_flags */
  488. + DCERPC_PFC_FLAG_FIRST |
  489. + DCERPC_PFC_FLAG_LAST);
  490. + if (!NT_STATUS_IS_OK(ret)) {
  491. + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
  492. + "RPC packet type - %u, expected %u: %s\n",
  493. + rpccli_pipe_txt(talloc_tos(), cli),
  494. + pkt->ptype, expected_pkt_type,
  495. + nt_errstr(ret)));
  496. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  497. + return ret;
  498. + }
  499. +
  500. + tmp_stub.data = r->stub_and_verifier.data;
  501. + tmp_stub.length = r->stub_and_verifier.length;
  502. +
  503. /* Here's where we deal with incoming sign/seal. */
  504. ret = dcerpc_check_auth(cli->auth, pkt,
  505. - &r->stub_and_verifier,
  506. + &tmp_stub,
  507. DCERPC_RESPONSE_LENGTH,
  508. - pdu, &pad_len);
  509. + pdu);
  510. if (!NT_STATUS_IS_OK(ret)) {
  511. + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
  512. + "RPC packet type - %u, expected %u: %s\n",
  513. + rpccli_pipe_txt(talloc_tos(), cli),
  514. + pkt->ptype, expected_pkt_type,
  515. + nt_errstr(ret)));
  516. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  517. return ret;
  518. }
  519. - if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
  520. - return NT_STATUS_BUFFER_TOO_SMALL;
  521. - }
  522. -
  523. /* Point the return values at the NDR data. */
  524. - rdata->data = r->stub_and_verifier.data;
  525. + *rdata = tmp_stub;
  526. - if (pkt->auth_length) {
  527. - /* We've already done integer wrap tests in
  528. - * dcerpc_check_auth(). */
  529. - rdata->length = r->stub_and_verifier.length
  530. - - pad_len
  531. - - DCERPC_AUTH_TRAILER_LENGTH
  532. - - pkt->auth_length;
  533. - } else {
  534. - rdata->length = r->stub_and_verifier.length;
  535. - }
  536. -
  537. - DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
  538. + DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
  539. (long unsigned int)pdu->length,
  540. - (long unsigned int)rdata->length,
  541. - (unsigned int)pad_len));
  542. + (long unsigned int)rdata->length));
  543. /*
  544. * If this is the first reply, and the allocation hint is
  545. @@ -478,14 +556,24 @@ static NTSTATUS cli_pipe_validate_curren
  546. break;
  547. - case DCERPC_PKT_BIND_NAK:
  548. - DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
  549. - rpccli_pipe_txt(talloc_tos(), cli)));
  550. - /* Use this for now... */
  551. - return NT_STATUS_NETWORK_ACCESS_DENIED;
  552. -
  553. case DCERPC_PKT_FAULT:
  554. + ret = dcerpc_verify_ncacn_packet_header(pkt,
  555. + DCERPC_PKT_FAULT,
  556. + 0, /* max_auth_info */
  557. + DCERPC_PFC_FLAG_FIRST |
  558. + DCERPC_PFC_FLAG_LAST,
  559. + DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
  560. + if (!NT_STATUS_IS_OK(ret)) {
  561. + DEBUG(1, (__location__ ": Connection to %s got an unexpected "
  562. + "RPC packet type - %u, expected %u: %s\n",
  563. + rpccli_pipe_txt(talloc_tos(), cli),
  564. + pkt->ptype, expected_pkt_type,
  565. + nt_errstr(ret)));
  566. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  567. + return ret;
  568. + }
  569. +
  570. DEBUG(1, (__location__ ": RPC fault code %s received "
  571. "from %s!\n",
  572. dcerpc_errstr(talloc_tos(),
  573. @@ -502,13 +590,6 @@ static NTSTATUS cli_pipe_validate_curren
  574. return NT_STATUS_RPC_PROTOCOL_ERROR;
  575. }
  576. - if (pkt->ptype != expected_pkt_type) {
  577. - DEBUG(3, (__location__ ": Connection to %s got an unexpected "
  578. - "RPC packet type - %u, not %u\n",
  579. - rpccli_pipe_txt(talloc_tos(), cli),
  580. - pkt->ptype, expected_pkt_type));
  581. - return NT_STATUS_RPC_PROTOCOL_ERROR;
  582. - }
  583. if (pkt->call_id != call_id) {
  584. DEBUG(3, (__location__ ": Connection to %s got an unexpected "
  585. @@ -518,17 +599,6 @@ static NTSTATUS cli_pipe_validate_curren
  586. return NT_STATUS_RPC_PROTOCOL_ERROR;
  587. }
  588. - /* Do this just before return - we don't want to modify any rpc header
  589. - data before now as we may have needed to do cryptographic actions on
  590. - it before. */
  591. -
  592. - if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
  593. - !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
  594. - DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
  595. - "fragment first/last ON.\n"));
  596. - pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
  597. - }
  598. -
  599. return NT_STATUS_OK;
  600. }
  601. @@ -883,6 +953,12 @@ static void rpc_api_pipe_got_pdu(struct
  602. state->pkt = talloc(state, struct ncacn_packet);
  603. if (!state->pkt) {
  604. + /*
  605. + * TODO: do a real async disconnect ...
  606. + *
  607. + * For now do it sync...
  608. + */
  609. + TALLOC_FREE(state->cli->transport);
  610. tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
  611. return;
  612. }
  613. @@ -892,18 +968,16 @@ static void rpc_api_pipe_got_pdu(struct
  614. state->pkt,
  615. !state->endianess);
  616. if (!NT_STATUS_IS_OK(status)) {
  617. + /*
  618. + * TODO: do a real async disconnect ...
  619. + *
  620. + * For now do it sync...
  621. + */
  622. + TALLOC_FREE(state->cli->transport);
  623. tevent_req_nterror(req, status);
  624. return;
  625. }
  626. - if (state->incoming_frag.length != state->pkt->frag_length) {
  627. - DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
  628. - (unsigned int)state->incoming_frag.length,
  629. - (unsigned int)state->pkt->frag_length));
  630. - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
  631. - return;
  632. - }
  633. -
  634. status = cli_pipe_validate_current_pdu(state,
  635. state->cli, state->pkt,
  636. &state->incoming_frag,
  637. @@ -917,6 +991,28 @@ static void rpc_api_pipe_got_pdu(struct
  638. (unsigned)state->reply_pdu_offset,
  639. nt_errstr(status)));
  640. + if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
  641. + /*
  642. + * TODO: do a real async disconnect ...
  643. + *
  644. + * For now do it sync...
  645. + */
  646. + TALLOC_FREE(state->cli->transport);
  647. + } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
  648. + /*
  649. + * TODO: do a real async disconnect ...
  650. + *
  651. + * For now do it sync...
  652. + */
  653. + TALLOC_FREE(state->cli->transport);
  654. + } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
  655. + /*
  656. + * TODO: do a real async disconnect ...
  657. + *
  658. + * For now do it sync...
  659. + */
  660. + TALLOC_FREE(state->cli->transport);
  661. + }
  662. if (!NT_STATUS_IS_OK(status)) {
  663. tevent_req_nterror(req, status);
  664. return;
  665. @@ -941,7 +1037,24 @@ static void rpc_api_pipe_got_pdu(struct
  666. "%s\n",
  667. state->endianess?"little":"big",
  668. state->pkt->drep[0]?"little":"big"));
  669. - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
  670. + /*
  671. + * TODO: do a real async disconnect ...
  672. + *
  673. + * For now do it sync...
  674. + */
  675. + TALLOC_FREE(state->cli->transport);
  676. + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
  677. + return;
  678. + }
  679. +
  680. + if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
  681. + /*
  682. + * TODO: do a real async disconnect ...
  683. + *
  684. + * For now do it sync...
  685. + */
  686. + TALLOC_FREE(state->cli->transport);
  687. + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
  688. return;
  689. }
  690. @@ -949,6 +1062,12 @@ static void rpc_api_pipe_got_pdu(struct
  691. if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
  692. if (!data_blob_realloc(NULL, &state->reply_pdu,
  693. state->reply_pdu_offset + rdata.length)) {
  694. + /*
  695. + * TODO: do a real async disconnect ...
  696. + *
  697. + * For now do it sync...
  698. + */
  699. + TALLOC_FREE(state->cli->transport);
  700. tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
  701. return;
  702. }
  703. @@ -978,6 +1097,14 @@ static void rpc_api_pipe_got_pdu(struct
  704. subreq = get_complete_frag_send(state, state->ev, state->cli,
  705. state->call_id,
  706. &state->incoming_frag);
  707. + if (subreq == NULL) {
  708. + /*
  709. + * TODO: do a real async disconnect ...
  710. + *
  711. + * For now do it sync...
  712. + */
  713. + TALLOC_FREE(state->cli->transport);
  714. + }
  715. if (tevent_req_nomem(subreq, req)) {
  716. return;
  717. }
  718. @@ -1247,7 +1374,7 @@ static NTSTATUS create_rpc_bind_req(TALL
  719. auth->auth_type,
  720. auth->auth_level,
  721. 0, /* auth_pad_length */
  722. - 1, /* auth_context_id */
  723. + auth->auth_context_id,
  724. &auth_token,
  725. &auth_info);
  726. if (!NT_STATUS_IS_OK(ret)) {
  727. @@ -1749,9 +1876,8 @@ static bool check_bind_response(const st
  728. static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
  729. struct rpc_pipe_client *cli,
  730. - uint32 rpc_call_id,
  731. - enum dcerpc_AuthType auth_type,
  732. - enum dcerpc_AuthLevel auth_level,
  733. + struct pipe_auth_data *auth,
  734. + uint32_t rpc_call_id,
  735. DATA_BLOB *pauth_blob,
  736. DATA_BLOB *rpc_out)
  737. {
  738. @@ -1761,10 +1887,10 @@ static NTSTATUS create_rpc_bind_auth3(TA
  739. u.auth3._pad = 0;
  740. status = dcerpc_push_dcerpc_auth(mem_ctx,
  741. - auth_type,
  742. - auth_level,
  743. + auth->auth_type,
  744. + auth->auth_level,
  745. 0, /* auth_pad_length */
  746. - 1, /* auth_context_id */
  747. + auth->auth_context_id,
  748. pauth_blob,
  749. &u.auth3.auth_info);
  750. if (!NT_STATUS_IS_OK(status)) {
  751. @@ -1794,9 +1920,8 @@ static NTSTATUS create_rpc_bind_auth3(TA
  752. ********************************************************************/
  753. static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
  754. - enum dcerpc_AuthType auth_type,
  755. - enum dcerpc_AuthLevel auth_level,
  756. - uint32 rpc_call_id,
  757. + struct pipe_auth_data *auth,
  758. + uint32_t rpc_call_id,
  759. const struct ndr_syntax_id *abstract,
  760. const struct ndr_syntax_id *transfer,
  761. const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
  762. @@ -1806,10 +1931,10 @@ static NTSTATUS create_rpc_alter_context
  763. NTSTATUS status;
  764. status = dcerpc_push_dcerpc_auth(mem_ctx,
  765. - auth_type,
  766. - auth_level,
  767. + auth->auth_type,
  768. + auth->auth_level,
  769. 0, /* auth_pad_length */
  770. - 1, /* auth_context_id */
  771. + auth->auth_context_id,
  772. pauth_blob,
  773. &auth_info);
  774. if (!NT_STATUS_IS_OK(status)) {
  775. @@ -1957,30 +2082,45 @@ static void rpc_pipe_bind_step_one_done(
  776. rpc_pipe_bind_step_two_trigger(req);
  777. return;
  778. - case DCERPC_AUTH_TYPE_NTLMSSP:
  779. - case DCERPC_AUTH_TYPE_SPNEGO:
  780. - case DCERPC_AUTH_TYPE_KRB5:
  781. - /* Paranoid lenght checks */
  782. - if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
  783. - + pkt->auth_length) {
  784. - tevent_req_nterror(req,
  785. - NT_STATUS_INFO_LENGTH_MISMATCH);
  786. + default:
  787. + if (pkt->auth_length == 0) {
  788. + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
  789. return;
  790. }
  791. /* get auth credentials */
  792. - status = dcerpc_pull_dcerpc_auth(talloc_tos(),
  793. - &pkt->u.bind_ack.auth_info,
  794. - &auth, false);
  795. + status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
  796. + &pkt->u.bind_ack.auth_info,
  797. + &auth, NULL, true);
  798. if (!NT_STATUS_IS_OK(status)) {
  799. DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
  800. nt_errstr(status)));
  801. tevent_req_nterror(req, status);
  802. return;
  803. }
  804. - break;
  805. - default:
  806. - goto err_out;
  807. + if (auth.auth_type != pauth->auth_type) {
  808. + DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
  809. + auth.auth_type, pauth->auth_type));
  810. + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
  811. + return;
  812. + }
  813. +
  814. + if (auth.auth_level != pauth->auth_level) {
  815. + DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
  816. + auth.auth_level, pauth->auth_level));
  817. + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
  818. + return;
  819. + }
  820. +
  821. + if (auth.auth_context_id != pauth->auth_context_id) {
  822. + DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
  823. + (unsigned)auth.auth_context_id,
  824. + (unsigned)pauth->auth_context_id));
  825. + tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
  826. + return;
  827. + }
  828. +
  829. + break;
  830. }
  831. /*
  832. @@ -2226,9 +2366,7 @@ static NTSTATUS rpc_bind_next_send(struc
  833. /* Now prepare the alter context pdu. */
  834. data_blob_free(&state->rpc_out);
  835. - status = create_rpc_alter_context(state,
  836. - auth->auth_type,
  837. - auth->auth_level,
  838. + status = create_rpc_alter_context(state, auth,
  839. state->rpc_call_id,
  840. &state->cli->abstract_syntax,
  841. &state->cli->transfer_syntax,
  842. @@ -2261,10 +2399,8 @@ static NTSTATUS rpc_bind_finish_send(str
  843. /* Now prepare the auth3 context pdu. */
  844. data_blob_free(&state->rpc_out);
  845. - status = create_rpc_bind_auth3(state, state->cli,
  846. + status = create_rpc_bind_auth3(state, state->cli, auth,
  847. state->rpc_call_id,
  848. - auth->auth_type,
  849. - auth->auth_level,
  850. auth_token,
  851. &state->rpc_out);
  852. if (!NT_STATUS_IS_OK(status)) {
  853. @@ -2498,8 +2634,9 @@ static struct tevent_req *rpccli_bh_disc
  854. /*
  855. * TODO: do a real async disconnect ...
  856. *
  857. - * For now the caller needs to free rpc_cli
  858. + * For now we do it sync...
  859. */
  860. + TALLOC_FREE(hs->rpc_cli->transport);
  861. hs->rpc_cli = NULL;
  862. tevent_req_done(req);
  863. @@ -2636,6 +2773,7 @@ NTSTATUS rpccli_ncalrpc_bind_data(TALLOC
  864. result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
  865. result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
  866. + result->auth_context_id = 1;
  867. result->user_name = talloc_strdup(result, "");
  868. result->domain = talloc_strdup(result, "");
  869. @@ -2660,6 +2798,7 @@ NTSTATUS rpccli_anon_bind_data(TALLOC_CT
  870. result->auth_type = DCERPC_AUTH_TYPE_NONE;
  871. result->auth_level = DCERPC_AUTH_LEVEL_NONE;
  872. + result->auth_context_id = 0;
  873. result->user_name = talloc_strdup(result, "");
  874. result->domain = talloc_strdup(result, "");
  875. @@ -2697,6 +2836,7 @@ static NTSTATUS rpccli_ntlmssp_bind_data
  876. result->auth_type = auth_type;
  877. result->auth_level = auth_level;
  878. + result->auth_context_id = 1;
  879. result->user_name = talloc_strdup(result, username);
  880. result->domain = talloc_strdup(result, domain);
  881. @@ -2768,6 +2908,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLO
  882. result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
  883. result->auth_level = auth_level;
  884. + result->auth_context_id = 1;
  885. result->user_name = talloc_strdup(result, "");
  886. result->domain = talloc_strdup(result, domain);
  887. @@ -3432,6 +3573,7 @@ NTSTATUS cli_rpc_pipe_open_krb5(struct c
  888. }
  889. auth->auth_type = DCERPC_AUTH_TYPE_KRB5;
  890. auth->auth_level = auth_level;
  891. + auth->auth_context_id = 1;
  892. if (!username) {
  893. username = "";
  894. @@ -3502,6 +3644,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_krb5(s
  895. }
  896. auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
  897. auth->auth_level = auth_level;
  898. + auth->auth_context_id = 1;
  899. if (!username) {
  900. username = "";
  901. @@ -3576,6 +3719,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_ntlmss
  902. }
  903. auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
  904. auth->auth_level = auth_level;
  905. + auth->auth_context_id = 1;
  906. if (!username) {
  907. username = "";
  908. --- a/source4/rpc_server/dcesrv_auth.c
  909. +++ b/source4/rpc_server/dcesrv_auth.c
  910. @@ -46,7 +46,7 @@ bool dcesrv_auth_bind(struct dcesrv_call
  911. NTSTATUS status;
  912. uint32_t auth_length;
  913. - if (pkt->u.bind.auth_info.length == 0) {
  914. + if (pkt->auth_length == 0) {
  915. dce_conn->auth_state.auth_info = NULL;
  916. return true;
  917. }
  918. @@ -108,7 +108,7 @@ NTSTATUS dcesrv_auth_bind_ack(struct dce
  919. struct dcesrv_connection *dce_conn = call->conn;
  920. NTSTATUS status;
  921. - if (!call->conn->auth_state.gensec_security) {
  922. + if (call->pkt.auth_length == 0) {
  923. return NT_STATUS_OK;
  924. }
  925. @@ -155,10 +155,16 @@ bool dcesrv_auth_auth3(struct dcesrv_cal
  926. NTSTATUS status;
  927. uint32_t auth_length;
  928. - /* We can't work without an existing gensec state, and an new blob to feed it */
  929. - if (!dce_conn->auth_state.auth_info ||
  930. - !dce_conn->auth_state.gensec_security ||
  931. - pkt->u.auth3.auth_info.length == 0) {
  932. + if (pkt->auth_length == 0) {
  933. + return false;
  934. + }
  935. +
  936. + if (!dce_conn->auth_state.auth_info) {
  937. + return false;
  938. + }
  939. +
  940. + /* We can't work without an existing gensec state */
  941. + if (!dce_conn->auth_state.gensec_security) {
  942. return false;
  943. }
  944. @@ -203,7 +209,7 @@ bool dcesrv_auth_alter(struct dcesrv_cal
  945. uint32_t auth_length;
  946. /* on a pure interface change there is no auth blob */
  947. - if (pkt->u.alter.auth_info.length == 0) {
  948. + if (pkt->auth_length == 0) {
  949. return true;
  950. }
  951. @@ -238,8 +244,7 @@ NTSTATUS dcesrv_auth_alter_ack(struct dc
  952. /* on a pure interface change there is no auth_info structure
  953. setup */
  954. - if (!call->conn->auth_state.auth_info ||
  955. - dce_conn->auth_state.auth_info->credentials.length == 0) {
  956. + if (call->pkt.auth_length == 0) {
  957. return NT_STATUS_OK;
  958. }
  959. @@ -315,6 +320,11 @@ bool dcesrv_auth_request(struct dcesrv_c
  960. return false;
  961. }
  962. + if (pkt->auth_length == 0) {
  963. + DEBUG(1,("dcesrv_auth_request: unexpected auth_length of 0\n"));
  964. + return false;
  965. + }
  966. +
  967. status = dcerpc_pull_auth_trailer(pkt, call,
  968. &pkt->u.request.stub_and_verifier,
  969. &auth, &auth_length, false);
  970. --- a/source4/librpc/rpc/dcerpc.c
  971. +++ b/source4/librpc/rpc/dcerpc.c
  972. @@ -701,6 +701,14 @@ static NTSTATUS ncacn_pull_request_auth(
  973. return NT_STATUS_INVALID_LEVEL;
  974. }
  975. + if (pkt->auth_length == 0) {
  976. + return NT_STATUS_INVALID_NETWORK_RESPONSE;
  977. + }
  978. +
  979. + if (c->security_state.generic_state == NULL) {
  980. + return NT_STATUS_INTERNAL_ERROR;
  981. + }
  982. +
  983. status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
  984. &pkt->u.response.stub_and_verifier,
  985. &auth, &auth_length, false);
  986. @@ -1074,7 +1082,7 @@ static void dcerpc_bind_recv_handler(str
  987. }
  988. /* the bind_ack might contain a reply set of credentials */
  989. - if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
  990. + if (conn->security_state.auth_info && pkt->auth_length) {
  991. NTSTATUS status;
  992. uint32_t auth_length;
  993. status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
  994. @@ -1847,8 +1855,7 @@ static void dcerpc_alter_recv_handler(st
  995. }
  996. /* the alter_resp might contain a reply set of credentials */
  997. - if (recv_pipe->conn->security_state.auth_info &&
  998. - pkt->u.alter_resp.auth_info.length) {
  999. + if (recv_pipe->conn->security_state.auth_info && pkt->auth_length) {
  1000. struct dcecli_connection *conn = recv_pipe->conn;
  1001. NTSTATUS status;
  1002. uint32_t auth_length;
  1003. --- a/source3/librpc/rpc/dcerpc.h
  1004. +++ b/source3/librpc/rpc/dcerpc.h
  1005. @@ -42,6 +42,7 @@ struct pipe_auth_data {
  1006. bool verified_bitmask1;
  1007. void *auth_ctx;
  1008. + uint32_t auth_context_id;
  1009. /* Only the client code uses these 3 for now */
  1010. char *domain;
  1011. @@ -71,10 +72,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_
  1012. uint32_t auth_context_id,
  1013. const DATA_BLOB *credentials,
  1014. DATA_BLOB *blob);
  1015. -NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
  1016. - const DATA_BLOB *blob,
  1017. - struct dcerpc_auth *r,
  1018. - bool bigendian);
  1019. NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth,
  1020. size_t header_len, size_t data_left,
  1021. size_t max_xmit_frag, size_t pad_alignment,
  1022. @@ -85,9 +82,8 @@ NTSTATUS dcerpc_add_auth_footer(struct p
  1023. NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
  1024. struct ncacn_packet *pkt,
  1025. DATA_BLOB *pkt_trailer,
  1026. - size_t header_size,
  1027. - DATA_BLOB *raw_pkt,
  1028. - size_t *pad_len);
  1029. + uint8_t header_size,
  1030. + DATA_BLOB *raw_pkt);
  1031. /* The following definitions come from librpc/rpc/rpc_common.c */
  1032. --- a/source3/rpc_server/srv_pipe.c
  1033. +++ b/source3/rpc_server/srv_pipe.c
  1034. @@ -42,6 +42,7 @@
  1035. #include "auth.h"
  1036. #include "ntdomain.h"
  1037. #include "rpc_server/srv_pipe.h"
  1038. +#include "../librpc/gen_ndr/ndr_dcerpc.h"
  1039. #include "../librpc/ndr/ndr_dcerpc.h"
  1040. #undef DBGC_CLASS
  1041. @@ -270,10 +271,14 @@ static bool setup_bind_nak(struct pipes_
  1042. p->out_data.data_sent_length = 0;
  1043. p->out_data.current_pdu_sent = 0;
  1044. + set_incoming_fault(p);
  1045. TALLOC_FREE(p->auth.auth_ctx);
  1046. p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
  1047. p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
  1048. p->pipe_bound = False;
  1049. + p->allow_bind = false;
  1050. + p->allow_alter = false;
  1051. + p->allow_auth3 = false;
  1052. return True;
  1053. }
  1054. @@ -339,16 +344,46 @@ static bool check_bind_req(struct pipes_
  1055. DEBUG(3,("check_bind_req for %s\n",
  1056. get_pipe_name_from_syntax(talloc_tos(), abstract)));
  1057. + ok = ndr_syntax_id_equal(transfer, &ndr_transfer_syntax);
  1058. + if (!ok) {
  1059. + DEBUG(1,("check_bind_req unknown transfer syntax for "
  1060. + "%s context_id=%u\n",
  1061. + get_pipe_name_from_syntax(talloc_tos(), abstract),
  1062. + (unsigned)context_id));
  1063. + return false;
  1064. + }
  1065. +
  1066. + for (context_fns = p->contexts;
  1067. + context_fns != NULL;
  1068. + context_fns = context_fns->next)
  1069. + {
  1070. + if (context_fns->context_id != context_id) {
  1071. + continue;
  1072. + }
  1073. +
  1074. + ok = ndr_syntax_id_equal(&context_fns->syntax,
  1075. + abstract);
  1076. + if (ok) {
  1077. + return true;
  1078. + }
  1079. +
  1080. + DEBUG(1,("check_bind_req: changing abstract syntax for "
  1081. + "%s context_id=%u into %s not supported\n",
  1082. + get_pipe_name_from_syntax(talloc_tos(), &context_fns->syntax),
  1083. + (unsigned)context_id,
  1084. + get_pipe_name_from_syntax(talloc_tos(), abstract)));
  1085. + return false;
  1086. + }
  1087. +
  1088. /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */
  1089. - if (rpc_srv_pipe_exists_by_id(abstract) &&
  1090. - ndr_syntax_id_equal(transfer, &ndr_transfer_syntax)) {
  1091. - DEBUG(3, ("check_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
  1092. - rpc_srv_get_pipe_cli_name(abstract),
  1093. - rpc_srv_get_pipe_srv_name(abstract)));
  1094. - } else {
  1095. + if (!rpc_srv_pipe_exists_by_id(abstract)) {
  1096. return false;
  1097. }
  1098. + DEBUG(3, ("check_bind_req: %s -> %s rpc service\n",
  1099. + rpc_srv_get_pipe_cli_name(abstract),
  1100. + rpc_srv_get_pipe_srv_name(abstract)));
  1101. +
  1102. context_fns = SMB_MALLOC_P(struct pipe_rpc_fns);
  1103. if (context_fns == NULL) {
  1104. DEBUG(0,("check_bind_req: malloc() failed!\n"));
  1105. @@ -447,6 +482,7 @@ static bool pipe_spnego_auth_bind(struct
  1106. p->auth.auth_ctx = spnego_ctx;
  1107. p->auth.auth_type = DCERPC_AUTH_TYPE_SPNEGO;
  1108. + p->auth.auth_context_id = auth_info->auth_context_id;
  1109. DEBUG(10, ("SPNEGO auth started\n"));
  1110. @@ -557,6 +593,7 @@ static bool pipe_schannel_auth_bind(stru
  1111. /* We're finished with this bind - no more packets. */
  1112. p->auth.auth_ctx = schannel_auth;
  1113. p->auth.auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
  1114. + p->auth.auth_context_id = auth_info->auth_context_id;
  1115. p->pipe_bound = True;
  1116. @@ -601,6 +638,7 @@ static bool pipe_ntlmssp_auth_bind(struc
  1117. p->auth.auth_ctx = ntlmssp_state;
  1118. p->auth.auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
  1119. + p->auth.auth_context_id = auth_info->auth_context_id;
  1120. DEBUG(10, (__location__ ": NTLMSSP auth started\n"));
  1121. @@ -776,6 +814,11 @@ static NTSTATUS pipe_auth_verify_final(s
  1122. void *mech_ctx;
  1123. NTSTATUS status;
  1124. + if (p->auth.auth_type == DCERPC_AUTH_TYPE_NONE) {
  1125. + p->pipe_bound = true;
  1126. + return NT_STATUS_OK;
  1127. + }
  1128. +
  1129. switch (p->auth.auth_type) {
  1130. case DCERPC_AUTH_TYPE_NTLMSSP:
  1131. ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx,
  1132. @@ -867,16 +910,38 @@ static bool api_pipe_bind_req(struct pip
  1133. DATA_BLOB auth_resp = data_blob_null;
  1134. DATA_BLOB auth_blob = data_blob_null;
  1135. - /* No rebinds on a bound pipe - use alter context. */
  1136. - if (p->pipe_bound) {
  1137. - DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound "
  1138. - "pipe %s.\n",
  1139. - get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
  1140. + if (!p->allow_bind) {
  1141. + DEBUG(2,("Pipe not in allow bind state\n"));
  1142. return setup_bind_nak(p, pkt);
  1143. }
  1144. + p->allow_bind = false;
  1145. +
  1146. + status = dcerpc_verify_ncacn_packet_header(pkt,
  1147. + DCERPC_PKT_BIND,
  1148. + pkt->u.bind.auth_info.length,
  1149. + 0, /* required flags */
  1150. + DCERPC_PFC_FLAG_FIRST |
  1151. + DCERPC_PFC_FLAG_LAST |
  1152. + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
  1153. + 0x08 | /* this is not defined, but should be ignored */
  1154. + DCERPC_PFC_FLAG_CONC_MPX |
  1155. + DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
  1156. + DCERPC_PFC_FLAG_MAYBE |
  1157. + DCERPC_PFC_FLAG_OBJECT_UUID);
  1158. + if (!NT_STATUS_IS_OK(status)) {
  1159. + DEBUG(1, ("api_pipe_bind_req: invalid pdu: %s\n",
  1160. + nt_errstr(status)));
  1161. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  1162. + goto err_exit;
  1163. + }
  1164. if (pkt->u.bind.num_contexts == 0) {
  1165. - DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n"));
  1166. + DEBUG(1, ("api_pipe_bind_req: no rpc contexts around\n"));
  1167. + goto err_exit;
  1168. + }
  1169. +
  1170. + if (pkt->u.bind.ctx_list[0].num_transfer_syntaxes == 0) {
  1171. + DEBUG(1, ("api_pipe_bind_req: no transfer syntaxes around\n"));
  1172. goto err_exit;
  1173. }
  1174. @@ -960,25 +1025,12 @@ static bool api_pipe_bind_req(struct pip
  1175. * Check if this is an authenticated bind request.
  1176. */
  1177. if (pkt->auth_length) {
  1178. - /* Quick length check. Won't catch a bad auth footer,
  1179. - * prevents overrun. */
  1180. -
  1181. - if (pkt->frag_length < RPC_HEADER_LEN +
  1182. - DCERPC_AUTH_TRAILER_LENGTH +
  1183. - pkt->auth_length) {
  1184. - DEBUG(0,("api_pipe_bind_req: auth_len (%u) "
  1185. - "too long for fragment %u.\n",
  1186. - (unsigned int)pkt->auth_length,
  1187. - (unsigned int)pkt->frag_length));
  1188. - goto err_exit;
  1189. - }
  1190. -
  1191. /*
  1192. * Decode the authentication verifier.
  1193. */
  1194. - status = dcerpc_pull_dcerpc_auth(pkt,
  1195. - &pkt->u.bind.auth_info,
  1196. - &auth_info, p->endian);
  1197. + status = dcerpc_pull_auth_trailer(pkt, pkt,
  1198. + &pkt->u.bind.auth_info,
  1199. + &auth_info, NULL, true);
  1200. if (!NT_STATUS_IS_OK(status)) {
  1201. DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
  1202. goto err_exit;
  1203. @@ -1072,6 +1124,7 @@ static bool api_pipe_bind_req(struct pip
  1204. p->pipe_bound = True;
  1205. /* The session key was initialized from the SMB
  1206. * session in make_internal_rpc_pipe_p */
  1207. + p->auth.auth_context_id = 0;
  1208. }
  1209. ZERO_STRUCT(u.bind_ack);
  1210. @@ -1113,15 +1166,15 @@ static bool api_pipe_bind_req(struct pip
  1211. if (!NT_STATUS_IS_OK(status)) {
  1212. DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
  1213. nt_errstr(status)));
  1214. + goto err_exit;
  1215. }
  1216. if (auth_resp.length) {
  1217. -
  1218. status = dcerpc_push_dcerpc_auth(pkt,
  1219. auth_type,
  1220. auth_info.auth_level,
  1221. - 0,
  1222. - 1, /* auth_context_id */
  1223. + 0, /* pad_len */
  1224. + p->auth.auth_context_id,
  1225. &auth_resp,
  1226. &auth_blob);
  1227. if (!NT_STATUS_IS_OK(status)) {
  1228. @@ -1152,6 +1205,22 @@ static bool api_pipe_bind_req(struct pip
  1229. p->out_data.current_pdu_sent = 0;
  1230. TALLOC_FREE(auth_blob.data);
  1231. +
  1232. + if (bind_ack_ctx.result == 0) {
  1233. + p->allow_alter = true;
  1234. + p->allow_auth3 = true;
  1235. + if (p->auth.auth_type == DCERPC_AUTH_TYPE_NONE) {
  1236. + status = pipe_auth_verify_final(p);
  1237. + if (!NT_STATUS_IS_OK(status)) {
  1238. + DEBUG(0, ("pipe_auth_verify_final failed: %s\n",
  1239. + nt_errstr(status)));
  1240. + goto err_exit;
  1241. + }
  1242. + }
  1243. + } else {
  1244. + goto err_exit;
  1245. + }
  1246. +
  1247. return True;
  1248. err_exit:
  1249. @@ -1176,18 +1245,39 @@ bool api_pipe_bind_auth3(struct pipes_st
  1250. DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__));
  1251. - if (pkt->auth_length == 0) {
  1252. - DEBUG(0, ("No auth field sent for bind request!\n"));
  1253. + if (!p->allow_auth3) {
  1254. + DEBUG(1, ("Pipe not in allow auth3 state.\n"));
  1255. goto err;
  1256. }
  1257. - /* Ensure there's enough data for an authenticated request. */
  1258. - if (pkt->frag_length < RPC_HEADER_LEN
  1259. - + DCERPC_AUTH_TRAILER_LENGTH
  1260. - + pkt->auth_length) {
  1261. - DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len "
  1262. - "%u is too large.\n",
  1263. - (unsigned int)pkt->auth_length));
  1264. + status = dcerpc_verify_ncacn_packet_header(pkt,
  1265. + DCERPC_PKT_AUTH3,
  1266. + pkt->u.auth3.auth_info.length,
  1267. + 0, /* required flags */
  1268. + DCERPC_PFC_FLAG_FIRST |
  1269. + DCERPC_PFC_FLAG_LAST |
  1270. + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
  1271. + 0x08 | /* this is not defined, but should be ignored */
  1272. + DCERPC_PFC_FLAG_CONC_MPX |
  1273. + DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
  1274. + DCERPC_PFC_FLAG_MAYBE |
  1275. + DCERPC_PFC_FLAG_OBJECT_UUID);
  1276. + if (!NT_STATUS_IS_OK(status)) {
  1277. + DEBUG(1, ("api_pipe_bind_auth3: invalid pdu: %s\n",
  1278. + nt_errstr(status)));
  1279. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  1280. + goto err;
  1281. + }
  1282. +
  1283. + /* We can only finish if the pipe is unbound for now */
  1284. + if (p->pipe_bound) {
  1285. + DEBUG(0, (__location__ ": Pipe already bound, "
  1286. + "AUTH3 not supported!\n"));
  1287. + goto err;
  1288. + }
  1289. +
  1290. + if (pkt->auth_length == 0) {
  1291. + DEBUG(1, ("No auth field sent for auth3 request!\n"));
  1292. goto err;
  1293. }
  1294. @@ -1195,9 +1285,9 @@ bool api_pipe_bind_auth3(struct pipes_st
  1295. * Decode the authentication verifier response.
  1296. */
  1297. - status = dcerpc_pull_dcerpc_auth(pkt,
  1298. - &pkt->u.auth3.auth_info,
  1299. - &auth_info, p->endian);
  1300. + status = dcerpc_pull_auth_trailer(pkt, pkt,
  1301. + &pkt->u.auth3.auth_info,
  1302. + &auth_info, NULL, true);
  1303. if (!NT_STATUS_IS_OK(status)) {
  1304. DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
  1305. goto err;
  1306. @@ -1215,6 +1305,21 @@ bool api_pipe_bind_auth3(struct pipes_st
  1307. goto err;
  1308. }
  1309. + if (auth_info.auth_level != p->auth.auth_level) {
  1310. + DEBUG(1, ("Auth level mismatch! Client sent %d, "
  1311. + "but auth was started as level %d!\n",
  1312. + auth_info.auth_level, p->auth.auth_level));
  1313. + goto err;
  1314. + }
  1315. +
  1316. + if (auth_info.auth_context_id != p->auth.auth_context_id) {
  1317. + DEBUG(0, ("Auth context id mismatch! Client sent %u, "
  1318. + "but auth was started as level %u!\n",
  1319. + (unsigned)auth_info.auth_context_id,
  1320. + (unsigned)p->auth.auth_context_id));
  1321. + goto err;
  1322. + }
  1323. +
  1324. switch (auth_info.auth_type) {
  1325. case DCERPC_AUTH_TYPE_NTLMSSP:
  1326. ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx,
  1327. @@ -1267,6 +1372,10 @@ bool api_pipe_bind_auth3(struct pipes_st
  1328. return true;
  1329. err:
  1330. + p->pipe_bound = false;
  1331. + p->allow_bind = false;
  1332. + p->allow_alter = false;
  1333. + p->allow_auth3 = false;
  1334. TALLOC_FREE(p->auth.auth_ctx);
  1335. return false;
  1336. @@ -1284,7 +1393,7 @@ static bool api_pipe_alter_context(struc
  1337. uint16 assoc_gid;
  1338. NTSTATUS status;
  1339. union dcerpc_payload u;
  1340. - struct dcerpc_ack_ctx bind_ack_ctx;
  1341. + struct dcerpc_ack_ctx alter_ack_ctx;
  1342. DATA_BLOB auth_resp = data_blob_null;
  1343. DATA_BLOB auth_blob = data_blob_null;
  1344. int pad_len = 0;
  1345. @@ -1294,8 +1403,42 @@ static bool api_pipe_alter_context(struc
  1346. DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__));
  1347. - if (pkt->u.bind.assoc_group_id != 0) {
  1348. - assoc_gid = pkt->u.bind.assoc_group_id;
  1349. + if (!p->allow_alter) {
  1350. + DEBUG(1, ("Pipe not in allow alter state.\n"));
  1351. + goto err_exit;
  1352. + }
  1353. +
  1354. + status = dcerpc_verify_ncacn_packet_header(pkt,
  1355. + DCERPC_PKT_ALTER,
  1356. + pkt->u.alter.auth_info.length,
  1357. + 0, /* required flags */
  1358. + DCERPC_PFC_FLAG_FIRST |
  1359. + DCERPC_PFC_FLAG_LAST |
  1360. + DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
  1361. + 0x08 | /* this is not defined, but should be ignored */
  1362. + DCERPC_PFC_FLAG_CONC_MPX |
  1363. + DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
  1364. + DCERPC_PFC_FLAG_MAYBE |
  1365. + DCERPC_PFC_FLAG_OBJECT_UUID);
  1366. + if (!NT_STATUS_IS_OK(status)) {
  1367. + DEBUG(1, ("api_pipe_alter_context: invalid pdu: %s\n",
  1368. + nt_errstr(status)));
  1369. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  1370. + goto err_exit;
  1371. + }
  1372. +
  1373. + if (pkt->u.alter.num_contexts == 0) {
  1374. + DEBUG(1, ("api_pipe_alter_context: no rpc contexts around\n"));
  1375. + goto err_exit;
  1376. + }
  1377. +
  1378. + if (pkt->u.alter.ctx_list[0].num_transfer_syntaxes == 0) {
  1379. + DEBUG(1, ("api_pipe_alter_context: no transfer syntaxes around\n"));
  1380. + goto err_exit;
  1381. + }
  1382. +
  1383. + if (pkt->u.alter.assoc_group_id != 0) {
  1384. + assoc_gid = pkt->u.alter.assoc_group_id;
  1385. } else {
  1386. assoc_gid = 0x53f0;
  1387. }
  1388. @@ -1305,59 +1448,45 @@ static bool api_pipe_alter_context(struc
  1389. */
  1390. /* If the requested abstract synt uuid doesn't match our client pipe,
  1391. - reject the bind_ack & set the transfer interface synt to all 0's,
  1392. + reject the alter_ack & set the transfer interface synt to all 0's,
  1393. ver 0 (observed when NT5 attempts to bind to abstract interfaces
  1394. unknown to NT4)
  1395. Needed when adding entries to a DACL from NT5 - SK */
  1396. if (check_bind_req(p,
  1397. - &pkt->u.bind.ctx_list[0].abstract_syntax,
  1398. - &pkt->u.bind.ctx_list[0].transfer_syntaxes[0],
  1399. - pkt->u.bind.ctx_list[0].context_id)) {
  1400. -
  1401. - bind_ack_ctx.result = 0;
  1402. - bind_ack_ctx.reason = 0;
  1403. - bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
  1404. + &pkt->u.alter.ctx_list[0].abstract_syntax,
  1405. + &pkt->u.alter.ctx_list[0].transfer_syntaxes[0],
  1406. + pkt->u.alter.ctx_list[0].context_id)) {
  1407. +
  1408. + alter_ack_ctx.result = 0;
  1409. + alter_ack_ctx.reason = 0;
  1410. + alter_ack_ctx.syntax = pkt->u.alter.ctx_list[0].transfer_syntaxes[0];
  1411. } else {
  1412. - p->pipe_bound = False;
  1413. /* Rejection reason: abstract syntax not supported */
  1414. - bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
  1415. - bind_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX;
  1416. - bind_ack_ctx.syntax = null_ndr_syntax_id;
  1417. + alter_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
  1418. + alter_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX;
  1419. + alter_ack_ctx.syntax = null_ndr_syntax_id;
  1420. }
  1421. /*
  1422. * Check if this is an authenticated alter context request.
  1423. */
  1424. if (pkt->auth_length) {
  1425. - /* Quick length check. Won't catch a bad auth footer,
  1426. - * prevents overrun. */
  1427. -
  1428. - if (pkt->frag_length < RPC_HEADER_LEN +
  1429. - DCERPC_AUTH_TRAILER_LENGTH +
  1430. - pkt->auth_length) {
  1431. - DEBUG(0,("api_pipe_alter_context: auth_len (%u) "
  1432. - "too long for fragment %u.\n",
  1433. - (unsigned int)pkt->auth_length,
  1434. - (unsigned int)pkt->frag_length ));
  1435. + /* We can only finish if the pipe is unbound for now */
  1436. + if (p->pipe_bound) {
  1437. + DEBUG(0, (__location__ ": Pipe already bound, "
  1438. + "Altering Context not yet supported!\n"));
  1439. goto err_exit;
  1440. }
  1441. - status = dcerpc_pull_dcerpc_auth(pkt,
  1442. - &pkt->u.bind.auth_info,
  1443. - &auth_info, p->endian);
  1444. + status = dcerpc_pull_auth_trailer(pkt, pkt,
  1445. + &pkt->u.alter.auth_info,
  1446. + &auth_info, NULL, true);
  1447. if (!NT_STATUS_IS_OK(status)) {
  1448. DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
  1449. goto err_exit;
  1450. }
  1451. - /* We can only finish if the pipe is unbound for now */
  1452. - if (p->pipe_bound) {
  1453. - DEBUG(0, (__location__ ": Pipe already bound, "
  1454. - "Altering Context not yet supported!\n"));
  1455. - goto err_exit;
  1456. - }
  1457. -
  1458. if (auth_info.auth_type != p->auth.auth_type) {
  1459. DEBUG(0, ("Auth type mismatch! Client sent %d, "
  1460. "but auth was started as type %d!\n",
  1461. @@ -1365,6 +1494,20 @@ static bool api_pipe_alter_context(struc
  1462. goto err_exit;
  1463. }
  1464. + if (auth_info.auth_level != p->auth.auth_level) {
  1465. + DEBUG(0, ("Auth level mismatch! Client sent %d, "
  1466. + "but auth was started as level %d!\n",
  1467. + auth_info.auth_level, p->auth.auth_level));
  1468. + goto err_exit;
  1469. + }
  1470. +
  1471. + if (auth_info.auth_context_id != p->auth.auth_context_id) {
  1472. + DEBUG(0, ("Auth context id mismatch! Client sent %u, "
  1473. + "but auth was started as level %u!\n",
  1474. + (unsigned)auth_info.auth_context_id,
  1475. + (unsigned)p->auth.auth_context_id));
  1476. + goto err_exit;
  1477. + }
  1478. switch (auth_info.auth_type) {
  1479. case DCERPC_AUTH_TYPE_SPNEGO:
  1480. @@ -1431,7 +1574,7 @@ static bool api_pipe_alter_context(struc
  1481. u.alter_resp.secondary_address_size = 1;
  1482. u.alter_resp.num_results = 1;
  1483. - u.alter_resp.ctx_list = &bind_ack_ctx;
  1484. + u.alter_resp.ctx_list = &alter_ack_ctx;
  1485. /* NOTE: We leave the auth_info empty so we can calculate the padding
  1486. * later and then append the auth_info --simo */
  1487. @@ -1451,8 +1594,9 @@ static bool api_pipe_alter_context(struc
  1488. &u,
  1489. &p->out_data.frag);
  1490. if (!NT_STATUS_IS_OK(status)) {
  1491. - DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
  1492. + DEBUG(0, ("Failed to marshall alter_resp packet. (%s)\n",
  1493. nt_errstr(status)));
  1494. + goto err_exit;
  1495. }
  1496. if (auth_resp.length) {
  1497. @@ -1469,7 +1613,7 @@ static bool api_pipe_alter_context(struc
  1498. auth_info.auth_type,
  1499. auth_info.auth_level,
  1500. pad_len,
  1501. - 1, /* auth_context_id */
  1502. + p->auth.auth_context_id,
  1503. &auth_resp,
  1504. &auth_blob);
  1505. if (!NT_STATUS_IS_OK(status)) {
  1506. @@ -1618,6 +1762,7 @@ static bool api_pipe_request(struct pipe
  1507. if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) {
  1508. DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n"));
  1509. + set_incoming_fault(p);
  1510. setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED));
  1511. data_blob_free(&p->out_data.rdata);
  1512. TALLOC_FREE(frame);
  1513. @@ -1756,7 +1901,11 @@ void set_incoming_fault(struct pipes_str
  1514. data_blob_free(&p->in_data.data);
  1515. p->in_data.pdu_needed_len = 0;
  1516. p->in_data.pdu.length = 0;
  1517. - p->fault_state = DCERPC_FAULT_CANT_PERFORM;
  1518. + p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
  1519. +
  1520. + p->allow_alter = false;
  1521. + p->allow_auth3 = false;
  1522. + p->pipe_bound = false;
  1523. DEBUG(10, ("Setting fault state\n"));
  1524. }
  1525. @@ -1767,7 +1916,6 @@ static NTSTATUS dcesrv_auth_request(stru
  1526. {
  1527. NTSTATUS status;
  1528. size_t hdr_size = DCERPC_REQUEST_LENGTH;
  1529. - size_t pad_len;
  1530. DEBUG(10, ("Checking request auth.\n"));
  1531. @@ -1778,25 +1926,11 @@ static NTSTATUS dcesrv_auth_request(stru
  1532. /* in case of sealing this function will unseal the data in place */
  1533. status = dcerpc_check_auth(auth, pkt,
  1534. &pkt->u.request.stub_and_verifier,
  1535. - hdr_size, raw_pkt,
  1536. - &pad_len);
  1537. + hdr_size, raw_pkt);
  1538. if (!NT_STATUS_IS_OK(status)) {
  1539. return status;
  1540. }
  1541. -
  1542. - /* remove padding and auth trailer,
  1543. - * this way the caller will get just the data */
  1544. - if (pkt->auth_length) {
  1545. - size_t trail_len = pad_len
  1546. - + DCERPC_AUTH_TRAILER_LENGTH
  1547. - + pkt->auth_length;
  1548. - if (pkt->u.request.stub_and_verifier.length < trail_len) {
  1549. - return NT_STATUS_INFO_LENGTH_MISMATCH;
  1550. - }
  1551. - pkt->u.request.stub_and_verifier.length -= trail_len;
  1552. - }
  1553. -
  1554. return NT_STATUS_OK;
  1555. }
  1556. @@ -1816,6 +1950,29 @@ static bool process_request_pdu(struct p
  1557. return False;
  1558. }
  1559. + /*
  1560. + * We don't ignore DCERPC_PFC_FLAG_PENDING_CANCEL.
  1561. + * TODO: we can reject it with DCERPC_FAULT_NO_CALL_ACTIVE later.
  1562. + */
  1563. + status = dcerpc_verify_ncacn_packet_header(pkt,
  1564. + DCERPC_PKT_REQUEST,
  1565. + pkt->u.request.stub_and_verifier.length,
  1566. + 0, /* required_flags */
  1567. + DCERPC_PFC_FLAG_FIRST |
  1568. + DCERPC_PFC_FLAG_LAST |
  1569. + 0x08 | /* this is not defined, but should be ignored */
  1570. + DCERPC_PFC_FLAG_CONC_MPX |
  1571. + DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
  1572. + DCERPC_PFC_FLAG_MAYBE |
  1573. + DCERPC_PFC_FLAG_OBJECT_UUID);
  1574. + if (!NT_STATUS_IS_OK(status)) {
  1575. + DEBUG(1, ("process_request_pdu: invalid pdu: %s\n",
  1576. + nt_errstr(status)));
  1577. + NDR_PRINT_DEBUG(ncacn_packet, pkt);
  1578. + set_incoming_fault(p);
  1579. + return false;
  1580. + }
  1581. +
  1582. /* Store the opnum */
  1583. p->opnum = pkt->u.request.opnum;
  1584. @@ -2065,7 +2222,7 @@ done:
  1585. "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(),
  1586. &p->syntax)));
  1587. set_incoming_fault(p);
  1588. - setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
  1589. + setup_fault_pdu(p, NT_STATUS(DCERPC_NCA_S_PROTO_ERROR));
  1590. TALLOC_FREE(pkt);
  1591. } else {
  1592. /*
  1593. --- a/source3/include/ntdomain.h
  1594. +++ b/source3/include/ntdomain.h
  1595. @@ -135,6 +135,13 @@ struct pipes_struct {
  1596. bool pipe_bound;
  1597. /*
  1598. + * States we can be in.
  1599. + */
  1600. + bool allow_alter;
  1601. + bool allow_bind;
  1602. + bool allow_auth3;
  1603. +
  1604. + /*
  1605. * Set the DCERPC_FAULT to return.
  1606. */
  1607. --- a/source3/rpc_server/rpc_ncacn_np.c
  1608. +++ b/source3/rpc_server/rpc_ncacn_np.c
  1609. @@ -171,6 +171,7 @@ struct pipes_struct *make_internal_rpc_p
  1610. p->syntax = *syntax;
  1611. p->transport = NCALRPC;
  1612. + p->allow_bind = true;
  1613. DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n",
  1614. get_pipe_name_from_syntax(talloc_tos(), syntax), pipes_open));
  1615. @@ -780,6 +781,7 @@ static NTSTATUS rpc_pipe_open_external(T
  1616. }
  1617. result->auth->auth_type = DCERPC_AUTH_TYPE_NONE;
  1618. result->auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
  1619. + result->auth->auth_context_id = 0;
  1620. status = rpccli_anon_bind_data(result, &auth);
  1621. if (!NT_STATUS_IS_OK(status)) {
  1622. --- a/source3/rpc_server/rpc_server.c
  1623. +++ b/source3/rpc_server/rpc_server.c
  1624. @@ -102,6 +102,7 @@ static int make_server_pipes_struct(TALL
  1625. p->syntax = id;
  1626. p->transport = transport;
  1627. p->ncalrpc_as_system = ncalrpc_as_system;
  1628. + p->allow_bind = true;
  1629. p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
  1630. if (!p->mem_ctx) {
  1631. @@ -663,6 +664,12 @@ static void named_pipe_packet_done(struc
  1632. goto fail;
  1633. }
  1634. + if (npc->p->fault_state != 0) {
  1635. + DEBUG(2, ("Disconnect after fault\n"));
  1636. + sys_errno = EINVAL;
  1637. + goto fail;
  1638. + }
  1639. +
  1640. /* clear out any data that may have been left around */
  1641. npc->count = 0;
  1642. TALLOC_FREE(npc->iov);
  1643. @@ -1391,6 +1398,12 @@ static void dcerpc_ncacn_packet_done(str
  1644. goto fail;
  1645. }
  1646. + if (ncacn_conn->p->fault_state != 0) {
  1647. + DEBUG(2, ("Disconnect after fault\n"));
  1648. + sys_errno = EINVAL;
  1649. + goto fail;
  1650. + }
  1651. +
  1652. /* clear out any data that may have been left around */
  1653. ncacn_conn->count = 0;
  1654. TALLOC_FREE(ncacn_conn->iov);