2 * Copyright (c) 2009 Secure Endpoints Inc.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "ms-wkssvc.h"
27 #include "ms-srvsvc.h"
34 MSRPC_AllocBuffer(msrpc_buffer * buf, unsigned int size);
37 MSRPC_ReallocBuffer(msrpc_buffer * buf, unsigned int size);
40 MSRPC_FreeBuffer(msrpc_buffer * buf);
43 MSRPC_SetCmUser(cm_user_t * userp);
45 /*! \brief Interface list
47 This is the list of interfaces that are exported through this RPC
48 module. The *_ifspec variable is defined the <interface>_s.c file
49 that is generated by MIDL. We have to use an extra level of
50 indirection because the actual RPC_SERVER_INTERFACE structure is
51 not exported in the generated code.
53 RPC_SERVER_INTERFACE **_Interfaces[] = {
54 (RPC_SERVER_INTERFACE **) &wkssvc_v1_0_s_ifspec,
55 (RPC_SERVER_INTERFACE **) &srvsvc_v3_0_s_ifspec,
58 const int n_Interfaces = sizeof(_Interfaces)/sizeof(_Interfaces[0]);
62 #define RPC_ALIGNMENT 8
63 #define ALIGNTO8(x) (((((x) - 1)/8) + 1) * 8)
65 typedef struct fcursor {
70 #define INITC(pfc, buf, len) (pfc)->pos = (BYTE *)(buf); (pfc)->end = (pfc)->pos + (len)
72 #define SPC_LEFT(pfc) ((unsigned int)((pfc)->end - (pfc)->pos))
73 #define IS_SPC(pfc, n) (SPC_LEFT(pfc) >= (n))
75 __inline BYTE READB(fcursor * pfc) {
81 #define READW(pfc) (((WORD)READB(pfc)) | (((WORD)READB(pfc)) << 8))
82 #define READDW(pfc) (((DWORD)READW(pfc)) | (((DWORD)READW(pfc)) << 16))
83 #define O_READS(pfc, s) do { memcpy(s, (pfc)->pos, sizeof(*s)); (pfc)->pos += sizeof(*s); } while (0)
84 #define O_READA(pfc, a) do { memcpy(&a, (pfc)->pos, sizeof(a)); (pfc)->pos += sizeof(a); } while (0)
85 #define O_READSZ(pfc, s, sz) do { memcpy(s, (pfc)->pos, sz); (pfc)->pos += sz; } while (0)
86 #define O_RALIGN4(pfc) do { while(((size_t) (pfc)->pos) & 0x3) READB(pfc); } while (0)
87 #define O_RALIGN8(pfc) do { while(((size_t) (pfc)->pos) & 0x7) READB(pfc); } while (0)
89 __inline void WRITEB(fcursor * pfc, BYTE b) {
94 #define WRITEW(pfc, w) (WRITEB(pfc, ((w) & 0xff)), WRITEB(pfc, (((w) >> 8) & 0xff)))
95 #define WRITEDW(pfc, dw) (WRITEW(pfc, ((dw) & 0xffff)), WRITEW(pfc, (((dw) >> 16) & 0xffff)))
96 #define O_WRITES(pfc, s) do { memcpy((pfc)->pos, s, sizeof(*s)); (pfc)->pos += sizeof(*s); } while (0)
97 #define O_WRITEA(pfc, a) do { memcpy((pfc)->pos, &a, sizeof(a)); (pfc)->pos += sizeof(a); } while (0)
98 #define O_WRITESZ(pfc, s, sz) do { memcpy((pfc)->pos, s, sz); (pfc)->pos += sz; } while (0)
99 #define O_WALIGN4(pfc) do { while(((size_t) (pfc)->pos) & 0x3) WRITEB(pfc, 0); } while (0)
100 #define O_WALIGN8(pfc) do { while(((size_t) (pfc)->pos) & 0x7) WRITEB(pfc, 0); } while (0)
102 #define iread_u_int8(pfc) READB(pfc)
103 #define iread_byte(pfc) READB(pfc)
104 #define iread_u_int16(pfc) READW(pfc)
105 #define iread_u_int32(pfc) READDW(pfc)
107 #define write_u_int8(pfc, i) WRITEB(pfc, i)
108 #define write_byte(pfc, i) WRITEB(pfc, i)
109 #define write_u_int16(pfc, i) WRITEW(pfc, i)
110 #define write_u_int32(pfc, i) WRITEDW(pfc, i)
112 /*! \brief Supported RPC protocol version numbers */
113 RPC_VERSION msrpc_supported_protocol_versions[] = {
118 const int n_msrpc_supported_protocol_versions = sizeof(msrpc_supported_protocol_versions)/sizeof(msrpc_supported_protocol_versions[0]);
120 #define IS_PROTOCOL_VER_SUPPORTED(_maj, _min) ((_maj) == 5 && ((_min) == 0 || (_min) == 1))
122 /*! \brief Number of bytes of envelope overhead for an RPC response PDU */
123 #define RPC_RESPONSE_ENVELOPE_OVERHEAD 24
126 read_E_CommonHeader(fcursor *pc, E_CommonHeader * pr)
128 if (IS_SPC(pc, 16)) {
130 pr->rpc_vers = iread_u_int8(pc);
131 pr->rpc_vers_minor = iread_u_int8(pc);
132 pr->PTYPE = iread_u_int8(pc);
133 pr->pfc_flags = iread_u_int8(pc);
134 O_READA(pc, pr->packed_drep);
135 pr->frag_length = iread_u_int16(pc);
136 pr->auth_length = iread_u_int16(pc);
137 pr->call_id = iread_u_int32(pc);
142 return CM_ERROR_BADFORMAT;
147 write_E_CommonHeader(fcursor * pc, msrpc_conn * conn,
148 msrpc_call * call, PDU_TYPE pdu_type)
150 INITC(pc, call->out.buf_data, call->out.buf_alloc);
152 call->out.pdu_type = pdu_type;
154 if (IS_SPC(pc, 16)) {
155 write_u_int8(pc, conn->rpc_vers); /* protocol version */
156 write_u_int8(pc, conn->rpc_vers_minor); /* minor version */
157 write_u_int8(pc, pdu_type);
158 write_u_int8(pc, PFC_FIRST_FRAG|PFC_LAST_FRAG);
160 write_byte(pc, 0x10); /* Data representation */
165 write_u_int16(pc, 0); /* Fragment ength, to be filled in
167 write_u_int16(pc, 0); /* Length of auth data. Always 0 since
168 we don't do authentication for RPC
170 write_u_int32(pc, call->call_id);
174 return CM_ERROR_BUFFERTOOSMALL;
178 #define USE_CURRENT_BUFFER_LENGTH (-1)
180 closeMessage(fcursor * pc, msrpc_call * call, ptrdiff_t len)
185 if (len == USE_CURRENT_BUFFER_LENGTH)
186 len = pc->pos - call->out.buf_data;
188 if (len >= USHRT_MAX)
189 return CM_ERROR_TOOBIG;
190 slen = (unsigned short)len;
192 pc->pos = &call->out.buf_data[8];
193 write_u_int16(pc, slen);
194 call->out.buf_length = slen;
200 read_UUID(fcursor * pc,
203 if (IS_SPC(pc, sizeof(*uuid))) {
207 return CM_ERROR_BADFORMAT;
212 write_UUID(fcursor * pc,
215 if (IS_SPC(pc, sizeof(*uuid))) {
219 return CM_ERROR_BUFFERTOOSMALL;
224 read_RPC_VERSION(fcursor * pc,
228 ver->MajorVersion = iread_u_int16(pc);
229 ver->MinorVersion = iread_u_int16(pc);
232 return CM_ERROR_BADFORMAT;
237 write_RPC_VERSION(fcursor * pc,
238 const RPC_VERSION * ver)
241 write_u_int16(pc, ver->MajorVersion);
242 write_u_int16(pc, ver->MinorVersion);
245 return CM_ERROR_BUFFERTOOSMALL;
250 read_RPC_SYNTAX_IDENTIFIER(fcursor * pc,
251 RPC_SYNTAX_IDENTIFIER * psi)
255 code = read_UUID(pc, &psi->SyntaxGUID);
258 code = read_RPC_VERSION(pc, &psi->SyntaxVersion);
263 write_RPC_SYNTAX_IDENTIFIER(fcursor * pc,
264 const RPC_SYNTAX_IDENTIFIER * psi)
268 code = write_UUID(pc, &psi->SyntaxGUID);
271 code = write_RPC_VERSION(pc, &psi->SyntaxVersion);
276 is_equal_RPC_SYNTAX_IDENTIFIER(const RPC_SYNTAX_IDENTIFIER * s1,
277 const RPC_SYNTAX_IDENTIFIER * s2)
280 IsEqualGUID(&s1->SyntaxGUID, &s2->SyntaxGUID) &&
281 s1->SyntaxVersion.MajorVersion == s2->SyntaxVersion.MajorVersion &&
282 s2->SyntaxVersion.MinorVersion == s2->SyntaxVersion.MinorVersion;
285 #define FAULT_PDU_PACKET_SIZE 32
287 /*! \brief Write a fault PDU as the output of this call */
289 write_fault_PDU(msrpc_conn * conn, msrpc_call * call,
290 u_int32 status, u_int8 flags)
294 MSRPC_AllocBuffer(&call->out, FAULT_PDU_PACKET_SIZE);
296 write_E_CommonHeader(&o, conn, call, PDU_TYPE_FAULT);
298 write_u_int32(&o, 16); /* allocation hint */
299 write_u_int16(&o, call->context_id); /* presentation context ID */
301 write_u_int8(&o, 0); /* cancel count */
302 write_u_int8(&o, 0); /* reserved */
304 write_u_int32(&o, status); /* status code */
306 O_WALIGN8(&o); /* alignment */
308 closeMessage(&o, call, USE_CURRENT_BUFFER_LENGTH);
311 call->out.buf_data[3] |= flags;
314 call->status = MSRPC_CALL_DISPATCHED;
319 #define BIND_NAK_PDU_PACKET_SIZE 18
321 /*! \brief Write a bind_nak PDU as the output of this call */
323 write_bind_nak_PDU(msrpc_conn * conn, msrpc_call * call,
324 BIND_REJECT_REASON reject_reason)
327 unsigned buf_size = BIND_NAK_PDU_PACKET_SIZE;
329 if (reject_reason == BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED)
330 buf_size += n_msrpc_supported_protocol_versions * 2 + 1;
332 MSRPC_AllocBuffer(&call->out, buf_size);
334 write_E_CommonHeader(&o, conn, call, PDU_TYPE_BIND_NAK);
336 write_u_int16(&o, reject_reason);
338 if (reject_reason == BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED) {
341 write_u_int8(&o, n_msrpc_supported_protocol_versions);
343 for (i=0; i < n_msrpc_supported_protocol_versions; i++) {
344 write_u_int8(&o, (u_int8) msrpc_supported_protocol_versions[i].MajorVersion);
345 write_u_int8(&o, (u_int8) msrpc_supported_protocol_versions[i].MinorVersion);
349 closeMessage(&o, call, USE_CURRENT_BUFFER_LENGTH);
351 call->status = MSRPC_CALL_DISPATCHED;
357 handle_ConnBind(msrpc_conn * conn, msrpc_call * call, fcursor * in, fcursor * out)
362 return CM_ERROR_BADFORMAT;
364 conn->max_xmit_frag = iread_u_int16(in);
365 conn->max_recv_frag = iread_u_int16(in);
366 conn->assoc_group_id = iread_u_int32(in);
368 conn->rpc_vers = call->in_header->rpc_vers;
369 conn->rpc_vers_minor = call->in_header->rpc_vers_minor;
371 if (conn->assoc_group_id == 0)
372 conn->assoc_group_id = 1;
374 write_E_CommonHeader(out, conn, call, PDU_TYPE_BIND_ACK);
376 write_u_int16(out, conn->max_xmit_frag);
377 write_u_int16(out, conn->max_recv_frag);
378 write_u_int32(out, conn->assoc_group_id);
380 if (conn->secondary_address) {
381 int len = (int)strlen(conn->secondary_address) + 1;
383 write_u_int16(out, len);
384 O_WRITESZ(out, conn->secondary_address, len);
386 write_u_int16(out, 0);
391 /* presentation context negotiation */
396 n_context_elem = iread_u_int8(in);
397 iread_u_int8(in); /* skip over reserved */
398 iread_u_int16(in); /* skip over reserved */
400 write_u_int8(out, n_context_elem);
401 write_u_int8(out, 0); /* pad */
402 write_u_int16(out, 0); /* pad */
404 for (i=0; i < n_context_elem; i++) {
406 RPC_SYNTAX_IDENTIFIER abstract_syntax;
407 RPC_SYNTAX_IDENTIFIER transfer_syntax;
408 RPC_SERVER_INTERFACE *interf = NULL;
411 if (!IS_SPC(in, 4 + 16))
412 return CM_ERROR_BADFORMAT;
414 call->context_id = iread_u_int16(in);
415 n_transfer_syn = iread_u_int8(in);
416 iread_u_int8(in); /* skip */
418 code = read_RPC_SYNTAX_IDENTIFIER(in, &abstract_syntax);
422 for (j=0; j < n_Interfaces; j++) {
423 interf = *_Interfaces[j];
425 if (is_equal_RPC_SYNTAX_IDENTIFIER(&abstract_syntax, &interf->InterfaceId))
429 if (j < n_Interfaces) {
430 for (k=0; k < n_transfer_syn; k++) {
431 code = read_RPC_SYNTAX_IDENTIFIER(in, &transfer_syntax);
435 if (is_equal_RPC_SYNTAX_IDENTIFIER(&transfer_syntax, &interf->TransferSyntax))
440 if (j < n_Interfaces && k < n_transfer_syn) {
442 write_u_int16(out, 0);
443 write_u_int16(out, 0);
444 write_RPC_SYNTAX_IDENTIFIER(out, &transfer_syntax);
446 conn->interface = interf;
450 if (j >= n_Interfaces)
451 reason = 1; /* abstract syntax not supported */
453 reason = 2; /* transfer syntax not supported */
454 write_u_int16(out, 2); /* provider rejection */
455 write_u_int16(out, reason);
456 ZeroMemory(&transfer_syntax, sizeof(transfer_syntax));
457 write_RPC_SYNTAX_IDENTIFIER(out, &transfer_syntax);
462 return closeMessage(out, call, USE_CURRENT_BUFFER_LENGTH);
466 handle_ConnRequest(msrpc_conn * conn, msrpc_call * call, fcursor * in, fcursor * out)
472 RPC_STATUS _Status = RPC_S_OK;
477 return CM_ERROR_BADFORMAT;
479 alloc_hint = iread_u_int32(in);
480 call->context_id = iread_u_int16(in);
481 op_num = iread_u_int16(in);
483 if (call->in_header->pfc_flags & PFC_OBJECT_UUID) {
486 code = read_UUID(in, &uuid);
493 if (conn->interface == NULL) {
494 /* if there was no interface selected, we can't go ahead with
496 return write_fault_PDU(conn, call, RPC_S_NO_BINDINGS, PFC_DID_NOT_EXECUTE);
501 if (op_num < 0 || op_num >= conn->interface->DispatchTable->DispatchTableCount ||
502 conn->interface->DispatchTable->DispatchTable[op_num] == NULL) {
504 return write_fault_PDU(conn, call, RPC_S_PROCNUM_OUT_OF_RANGE, PFC_DID_NOT_EXECUTE);
507 call->msg.BufferLength = len;
508 call->msg.ProcNum = op_num;
509 call->msg.TransferSyntax = &conn->interface->TransferSyntax;
510 call->msg.RpcInterfaceInformation = conn->interface;
512 _Status = I_RpcGetBuffer(&call->msg);
513 if ( _Status || call->msg.Buffer == NULL) {
514 return write_fault_PDU(conn, call, RPC_S_SERVER_OUT_OF_MEMORY, PFC_DID_NOT_EXECUTE);
517 memcpy(call->msg.Buffer, in->pos, len);
519 MSRPC_SetCmUser(call->cm_userp);
523 (*conn->interface->DispatchTable->DispatchTable[op_num])(&call->msg);
527 code = CM_ERROR_UNKNOWN;
531 MSRPC_SetCmUser(NULL);
534 call->out.pdu_type = PDU_TYPE_RESPONSE;
536 MSRPC_AllocBuffer(&call->out, call->msg.BufferLength);
537 call->out.buf_length = call->msg.BufferLength;
538 memcpy(call->out.buf_data, call->msg.Buffer, call->out.buf_length);
540 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, 0);
547 merge_fragment_Bind(msrpc_call * call, E_CommonHeader * ph,
548 msrpc_call * ncall, E_CommonHeader *pnh)
550 if (ph->auth_length + (unsigned int) pnh->auth_length > _UI16_MAX ||
551 ph->frag_length + (unsigned int) pnh->auth_length > _UI16_MAX ||
552 pnh->auth_length + 16 > pnh->frag_length)
553 return CM_ERROR_TOOBIG;
555 MSRPC_ReallocBuffer(&call->in, call->in.buf_length + pnh->auth_length);
556 if (call->in.buf_data == NULL)
557 return CM_ERROR_TOOBIG;
559 memcpy(call->in.buf_data + ph->frag_length,
560 ncall->in.buf_data + (pnh->frag_length - pnh->auth_length),
563 call->in.buf_length += pnh->auth_length;
564 ph->frag_length += pnh->auth_length;
565 ph->auth_length += pnh->auth_length;
567 if ((pnh->pfc_flags & PFC_LAST_FRAG) == PFC_LAST_FRAG) {
568 ph->pfc_flags |= PFC_LAST_FRAG;
575 merge_fragment_Request(msrpc_call * call, E_CommonHeader * ph,
576 msrpc_call * ncall, E_CommonHeader * pnh)
578 int new_auth_length = pnh->auth_length;
579 int new_stub_length = (int)pnh->frag_length - (pnh->auth_length + 24);
581 if (pnh->pfc_flags & PFC_OBJECT_UUID)
582 new_stub_length -= 16;
584 if (ph->auth_length + new_auth_length > _UI16_MAX ||
585 ph->frag_length + new_stub_length + new_auth_length > _UI16_MAX ||
586 pnh->auth_length + 24 > pnh->frag_length)
587 return CM_ERROR_TOOBIG;
589 MSRPC_ReallocBuffer(&call->in, call->in.buf_length + new_auth_length + new_stub_length);
590 if (call->in.buf_data == NULL)
591 return CM_ERROR_TOOBIG;
594 memmove(call->in.buf_data + (ph->frag_length - ph->auth_length),
595 call->in.buf_data + (ph->frag_length - ph->auth_length) + new_stub_length,
598 memcpy(call->in.buf_data + (ph->frag_length - ph->auth_length),
599 ncall->in.buf_data + (pnh->frag_length - (new_auth_length + new_stub_length)),
602 memcpy(call->in.buf_data + ph->frag_length + new_stub_length,
603 ncall->in.buf_data + (pnh->frag_length - pnh->auth_length),
606 call->in.buf_length += new_auth_length + new_stub_length;
607 ph->frag_length += new_auth_length + new_stub_length;
608 ph->auth_length += new_auth_length;
610 if ((pnh->pfc_flags & PFC_LAST_FRAG) == PFC_LAST_FRAG) {
611 ph->pfc_flags |= PFC_LAST_FRAG;
618 assemble_message(msrpc_conn * conn)
629 return CM_ERROR_INVAL;
631 INITC(&c, call->in.buf_data, call->in.buf_length);
633 code = read_E_CommonHeader(&c, &h);
637 if ((h.pfc_flags & (PFC_FIRST_FRAG | PFC_LAST_FRAG)) ==
638 (PFC_FIRST_FRAG | PFC_LAST_FRAG))
641 if ((h.pfc_flags & PFC_FIRST_FRAG) != PFC_FIRST_FRAG)
642 return CM_ERROR_INVAL;
644 for (ncall = call->next; ncall; ncall = ncall->next) {
648 INITC(&nc, ncall->in.buf_data, ncall->in.buf_length);
650 code = read_E_CommonHeader(&nc, &nh);
652 if (nh.call_id != h.call_id)
655 if ((nh.pfc_flags & PFC_FIRST_FRAG) != 0)
660 case PDU_TYPE_ALTER_CONTEXT:
661 code = merge_fragment_Bind(call, &h, ncall, &nh);
664 case PDU_TYPE_REQUEST:
665 code = merge_fragment_Request(call, &h, ncall, &nh);
669 code = CM_ERROR_INVAL;
672 ncall->status = MSRPC_CALL_SKIP;
674 if (nh.pfc_flags & PFC_LAST_FRAG) {
679 c.pos = &call->in.buf_data[3];
680 write_u_int8(&c, h.pfc_flags);
681 write_u_int16(&c, h.frag_length);
682 write_u_int16(&c, h.auth_length);
688 dispatch_call(msrpc_conn * conn)
699 call->status != MSRPC_CALL_MSGRECEIVED)
700 return CM_ERROR_INVAL;
702 MSRPC_AllocBuffer(&call->out, DEF_RPC_MSG_SIZE);
706 INITC(&c, call->in.buf_data, call->in.buf_length);
708 code = read_E_CommonHeader(&c, &h);
712 if (!IS_PROTOCOL_VER_SUPPORTED(h.rpc_vers, h.rpc_vers_minor)) {
713 if (h.PTYPE == PDU_TYPE_BIND) {
714 return write_bind_nak_PDU(conn, call, BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED);
716 /* we shouldn't get here, but just in case */
717 return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
721 if (h.packed_drep[0] != 0x10 ||
722 h.packed_drep[1] != 0 ||
723 h.packed_drep[2] != 0 ||
724 h.packed_drep[3] != 0) {
726 if (h.PTYPE == PDU_TYPE_BIND) {
727 return write_bind_nak_PDU(conn, call, BIND_REJ_REASON_NOT_SPECIFIED);
729 return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
733 if (h.frag_length > call->in.buf_length) {
734 return CM_ERROR_INVAL;
737 if ((h.pfc_flags & (PFC_FIRST_FRAG | PFC_LAST_FRAG)) !=
738 (PFC_FIRST_FRAG | PFC_LAST_FRAG)) {
739 code = assemble_message(conn);
743 return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
746 if (h.auth_length != 0) {
747 return write_fault_PDU(conn, call, RPC_S_BINDING_HAS_NO_AUTH, PFC_DID_NOT_EXECUTE);
750 call->call_id = h.call_id;
752 call->in.pdu_type = h.PTYPE;
754 INITC(&o, call->out.buf_data, call->out.buf_alloc);
756 call->in_header = &h;
758 code = CM_ERROR_INVAL;
761 case PDU_TYPE_REQUEST:
762 code = handle_ConnRequest(conn, call, &c, &o);
766 code = handle_ConnBind(conn, call, &c, &o);
769 case PDU_TYPE_ALTER_CONTEXT:
770 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
773 case PDU_TYPE_SHUTDOWN:
774 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
777 case PDU_TYPE_CO_CANCEL:
778 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
781 case PDU_TYPE_ORPHANED:
782 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
786 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
789 call->in_header = NULL;
791 call->status = MSRPC_CALL_DISPATCHED;
797 MSRPC_AllocBuffer(msrpc_buffer * buf, unsigned int size)
799 if (buf->buf_alloc < size) {
801 _aligned_free(buf->buf_data);
803 buf->buf_alloc = ALIGNTO8(size);
804 buf->buf_data = _aligned_malloc(buf->buf_alloc, RPC_ALIGNMENT);
811 MSRPC_FreeBuffer(msrpc_buffer * buf)
814 _aligned_free(buf->buf_data);
815 buf->buf_data = NULL;
823 MSRPC_ReallocBuffer(msrpc_buffer * buf, unsigned int size)
825 if (buf->buf_alloc < size) {
828 buf->buf_alloc = ALIGNTO8(size);
829 new_buf = _aligned_realloc(buf->buf_data, buf->buf_alloc, RPC_ALIGNMENT);
830 if (new_buf != NULL) {
831 buf->buf_data = new_buf;
833 MSRPC_FreeBuffer(buf);
843 c = calloc(sizeof(*c), 1);
845 c->msg.Handle = NULL;
846 c->msg.DataRepresentation = 0x00000010;
847 c->msg.Buffer = NULL;
848 c->msg.BufferLength = 0;
849 c->msg.TransferSyntax = NULL;
855 MSRPC_PutCall(msrpc_conn * conn, msrpc_call * pcall)
858 conn->tail->next = pcall;
859 pcall->prev = conn->tail;
863 conn->head = conn->tail = pcall;
864 pcall->next = pcall->prev = NULL;
870 MSRPC_DequeueCall(msrpc_conn * conn, msrpc_call * call)
873 call->prev->next = call->next;
875 call->next->prev = call->prev;
877 if (conn->head && conn->head == call)
878 conn->head = call->next;
880 if (conn->tail && conn->tail == call)
881 conn->tail = call->prev;
883 call->next = call->prev = NULL;
889 MSRPC_GetCall(msrpc_conn * conn, msrpc_call ** ppcall)
892 *ppcall = conn->head;
893 conn->head = conn->head->next;
895 conn->head->prev = NULL;
896 (*ppcall)->next = (*ppcall)->prev = NULL;
897 if (conn->tail == *ppcall)
907 MSRPC_FreeCall(msrpc_call * call)
909 I_RpcFreeBuffer(&call->msg);
910 MSRPC_FreeBuffer(&call->in);
911 MSRPC_FreeBuffer(&call->out);
913 if (call->cm_userp) {
914 cm_ReleaseUser(call->cm_userp);
915 call->cm_userp = NULL;
918 ZeroMemory(call, sizeof(*call));
923 /*! \brief Initialize a msrpc_conn
925 \param [out] conn Connection to initialize
927 \param [in] secondary_address An optional secondary address for the
928 query. Typically for RPCs to wellknown endpoints such as
929 SRVSVC or WKSSVC, this is a named pipe address (e.g.:
932 \return Always returns 0.
935 MSRPC_InitConn(msrpc_conn * conn, const char * secondary_address)
937 ZeroMemory(conn, sizeof(*conn));
938 if (secondary_address) {
939 conn->secondary_address = strdup(secondary_address);
944 /*! \brief Free a msrcp_conn structure contents
946 This doesn't free the msrpc_conn object, but frees the contents.
949 MSRPC_FreeConn(msrpc_conn * conn)
951 msrpc_call * call = NULL;
953 while(!MSRPC_GetCall(conn, &call)) {
954 MSRPC_FreeCall(call);
957 if (conn->secondary_address)
958 free(conn->secondary_address);
960 ZeroMemory(conn, sizeof(*conn));
965 /*! \brief Write an RPC message into the RPC module
967 This function should be used by message mode RPC transports to
968 submit a single message. if successful, the message will be queued
969 for dispatch. The RPC will not be executed until
970 MSRPC_PrepareRead() or MSRPC_ReadMessageLength() or
971 MSRPC_ReadMessage() is called.
974 MSRPC_WriteMessage(msrpc_conn * conn, BYTE * buffer, unsigned int len,
980 return CM_ERROR_INVAL;
982 call = MSRPC_NewCall();
984 if (len > MAX_RPC_MSG_SIZE)
985 return CM_ERROR_BUFFERTOOSMALL;
987 MSRPC_AllocBuffer(&call->in, len);
988 memcpy(call->in.buf_data, buffer, len);
989 call->in.buf_pos = len;
990 call->in.buf_length = call->in.buf_pos;
991 call->status = MSRPC_CALL_MSGRECEIVED;
994 call->cm_userp = userp;
998 MSRPC_PutCall(conn, call);
1003 /*! \brief Prepare to read the next message from the RPC output queue
1005 Each RPC message received is queued until the response is required.
1006 MSRPC_PrepareRead() will, if necessary, dispatch the RPC request
1007 and prepare the output buffer to be sent to the caller.
1010 MSRPC_PrepareRead(msrpc_conn * conn)
1015 while (conn->head) {
1018 if (call->status == MSRPC_CALL_SKIP ||
1019 call->status == MSRPC_CALL_MSGSENT ||
1020 (call->status == MSRPC_CALL_DISPATCHED &&
1021 call->out.buf_length == 0)) {
1023 MSRPC_DequeueCall(conn, call);
1024 MSRPC_FreeCall(call);
1028 if (call->status == MSRPC_CALL_MSGRECEIVED) {
1029 code = dispatch_call(conn);
1031 /* If the dispatch failed, then we discard the message.
1032 If the error was handled and a response packet was
1033 created, dispatch_call() would return 0. */
1036 MSRPC_DequeueCall(conn, call);
1037 MSRPC_FreeCall(call);
1042 break; /* the status wasn't SKIP or
1043 MSGRECEIVED, or we successfully
1044 dispatched the message. */
1047 if (conn->head == NULL)
1048 return CM_ERROR_BADFD;
1050 if (conn->head->status == MSRPC_CALL_DISPATCHED ||
1051 conn->head->status == MSRPC_CALL_MSGSENDING)
1054 return CM_ERROR_BADFD;
1057 /*! \brief Return the size of the buffer for the next RPC message
1059 Given the maximum size of the buffer, returns the actual size of
1060 the data that will be copied. If the return value is 0, there is
1061 no data to be sent to the caller either because there was no RPC
1062 message queued or the queued message could not be dispatched.
1065 MSRPC_ReadMessageLength(msrpc_conn * conn, unsigned int max_len)
1070 max_len = min(max_len, conn->max_recv_frag);
1072 code = MSRPC_PrepareRead(conn);
1079 (call->status == MSRPC_CALL_DISPATCHED ||
1080 call->status == MSRPC_CALL_MSGSENDING)) {
1082 switch(call->out.pdu_type) {
1083 case PDU_TYPE_RESPONSE:
1085 /* This calculation should mirror what
1086 MSRPC_ReadMessage() does below. */
1088 int fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1091 len = min(max_len, conn->max_recv_frag);
1093 if (call->out.buf_pos % fragment_size == 0) {
1094 if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD)
1097 len = min(len, RPC_RESPONSE_ENVELOPE_OVERHEAD + call->out.buf_length - call->out.buf_pos);
1099 unsigned int to_copy;
1101 to_copy = min(fragment_size - (call->out.buf_pos % fragment_size),
1102 call->out.buf_length - call->out.buf_pos);
1103 len = min(to_copy, len);
1109 case PDU_TYPE_BIND_ACK:
1110 case PDU_TYPE_FAULT:
1111 case PDU_TYPE_BIND_NAK:
1113 int len = min(call->out.buf_length - call->out.buf_pos, max_len);
1125 /*! \brief Read the next message from the RPC queue
1127 Copies the next chunk of data from the response buffer to the
1128 buffer indicated by \a buffer and \a len.
1130 \retval 0 The data was copied to the buffer. There is either no
1131 more data to send or the existence of more data is implicit in
1132 the data already sent. I.e. fragment flags were set
1133 appropriately to indicate more data and we are at a fragment
1136 \retval CM_ERROR_RPC_MOREDATA The data was copied to the buffer and
1137 there is more data to be sent.
1139 \retval Else something went wrong. The data was not copied to the
1140 buffer successfully.
1143 MSRPC_ReadMessage(msrpc_conn * conn, BYTE *buffer, unsigned int len)
1148 code = MSRPC_PrepareRead(conn);
1153 (conn->head->status == MSRPC_CALL_DISPATCHED ||
1154 conn->head->status == MSRPC_CALL_MSGSENDING)) {
1158 switch(call->out.pdu_type) {
1159 case PDU_TYPE_RESPONSE:
1161 BYTE * o_buffer = call->out.buf_data;
1162 unsigned int o_alloc = call->out.buf_alloc;
1163 unsigned int o_pos = call->out.buf_pos;
1164 unsigned int o_len = call->out.buf_length;
1165 unsigned int start_pos = o_pos;
1166 unsigned int fragment_size;
1169 /* If call->out.buf_pos falls on a fragment boundary:
1171 Assume that we are starting a new fragment and deal accordingly.
1175 Assume we are continuing a fragment.
1178 fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1180 /* Don't send more than the max_recv_frag */
1181 len = min(len, conn->max_recv_frag);
1183 /* Switch the supplied user buffer with the output
1185 call->out.buf_data = buffer;
1186 call->out.buf_length = 0;
1187 call->out.buf_alloc = len;
1188 call->out.buf_pos = 0;
1190 if (o_pos % fragment_size == 0) {
1194 We need to write the packet headers and
1195 fragment bits here. The length of the buffer
1196 should be at least big enough to hold the
1197 entire envelope. We don't handle the case were
1198 the envelope itself is too big.
1202 if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD) {
1203 return CM_ERROR_INVAL;
1206 code = write_E_CommonHeader(&o, conn, call, PDU_TYPE_RESPONSE);
1210 write_u_int32(&o, o_len); /* allocation hint */
1211 write_u_int16(&o, call->context_id); /* presentation context ID */
1212 write_u_int8(&o, 0); /* cancel count */
1213 write_u_int8(&o, 0); /* reserved */
1216 int to_copy = min(SPC_LEFT(&o), o_len - o_pos);
1219 O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1221 /* the fragment size of the message is the minimum of:
1223 - max_recv_frag for the connection
1224 - envelope size + (full message size - start offset)
1227 rc = closeMessage(&o, call,
1228 min(conn->max_recv_frag,
1229 RPC_RESPONSE_ENVELOPE_OVERHEAD + o_len - start_pos));
1235 /* If there is more data to be sent and we are
1236 not at a fragment boundary after the last
1237 send, we return CM_ERROR_RPC_MOREDATA.
1238 Having more fragments to send is not a case
1239 we indicate via a return value. */
1241 if (o_pos < o_len &&
1242 o_pos < start_pos + fragment_size)
1243 code = CM_ERROR_RPC_MOREDATA;
1246 if (start_pos + fragment_size < o_len)
1247 buffer[3] &= ~PFC_LAST_FRAG;
1250 buffer[3] &= ~PFC_FIRST_FRAG;
1256 The packet header should have already been sent
1257 in a previous block.
1260 unsigned int to_copy;
1262 INITC(&o, call->out.buf_data, call->out.buf_alloc);
1264 to_copy = min(fragment_size - (o_pos % fragment_size),
1266 to_copy = min(to_copy, SPC_LEFT(&o));
1268 O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1272 if (o_pos < o_len && (o_pos % fragment_size) != 0)
1273 code = CM_ERROR_RPC_MOREDATA;
1276 call->out.buf_data = o_buffer;
1277 call->out.buf_alloc = o_alloc;
1278 call->out.buf_pos = o_pos;
1279 call->out.buf_length = o_len;
1281 if (call->out.buf_pos < call->out.buf_length) {
1282 call->status = MSRPC_CALL_MSGSENDING;
1284 call->status = MSRPC_CALL_MSGSENT;
1285 MSRPC_DequeueCall(conn, call);
1286 MSRPC_FreeCall(call);
1291 case PDU_TYPE_BIND_ACK:
1292 case PDU_TYPE_FAULT:
1293 case PDU_TYPE_BIND_NAK:
1295 unsigned int to_send;
1297 /* These types of packets are already fully formed.
1298 We don't need to wrap them in an envelope. They
1299 also don't fragment. */
1301 to_send = call->out.buf_length - call->out.buf_pos;
1304 code = CM_ERROR_RPC_MOREDATA;
1309 memcpy(buffer, call->out.buf_data + call->out.buf_pos, len);
1312 call->out.buf_pos += len;
1314 if (call->out.buf_pos < call->out.buf_length) {
1315 call->status = MSRPC_CALL_MSGSENDING;
1317 call->status = MSRPC_CALL_MSGSENT;
1318 MSRPC_DequeueCall(conn, call);
1319 MSRPC_FreeCall(call);
1325 return CM_ERROR_INVAL;
1331 pthread_once_t msrpc_user_slot_init = PTHREAD_ONCE_INIT;
1333 DWORD msrpc_tls_user_slot = 0;
1336 msrpc_user_slot_init_func(void)
1338 msrpc_tls_user_slot = TlsAlloc();
1342 MSRPC_GetCmUser(void)
1344 pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1346 return (cm_user_t *) TlsGetValue(msrpc_tls_user_slot);
1350 MSRPC_SetCmUser(cm_user_t * userp)
1352 pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1354 TlsSetValue(msrpc_tls_user_slot, userp);
1357 typedef struct I_RpcAllocatedBuffer {
1358 DWORD magic; /* == _RPCALLOCATEDBUFFER_MAGIC */
1359 #define _RPCALLOCATEDBUFFER_MAGIC 0xa110ca73
1360 struct I_RpcAllocatedBuffer * next;
1362 /* Data goes here */
1363 } I_RpcAllocatedBuffer;
1365 #define I_RPCALLOCATEDBUFFER_FROM_PTR(v) (&(((I_RpcAllocatedBuffer *) (v))[-1]))
1369 I_RpcGetBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1371 I_RpcAllocatedBuffer * newBuffer = I_RpcAllocate(Message->BufferLength + sizeof(I_RpcAllocatedBuffer));
1372 I_RpcAllocatedBuffer * oldBuffer = NULL;
1374 if (Message->Buffer) {
1375 oldBuffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1379 newBuffer->magic = _RPCALLOCATEDBUFFER_MAGIC;
1380 newBuffer->next = oldBuffer;
1382 Message->Buffer = &newBuffer[1];
1384 return ERROR_OUTOFMEMORY;
1392 I_RpcFreeBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1394 if (Message->Buffer) {
1395 I_RpcAllocatedBuffer * buffer;
1397 buffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1400 I_RpcAllocatedBuffer * bnext;
1402 bnext = buffer->next;
1409 Message->Buffer = NULL;
1417 NdrServerInitializeNew(
1418 PRPC_MESSAGE pRpcMsg,
1419 PMIDL_STUB_MESSAGE pStubMsg,
1420 PMIDL_STUB_DESC pStubDesc
1423 ZeroMemory(pStubMsg, sizeof(*pStubMsg));
1425 pStubMsg->RpcMsg = pRpcMsg;
1426 pStubMsg->Buffer = pRpcMsg->Buffer;
1427 pStubMsg->BufferStart = pRpcMsg->Buffer;
1428 pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
1429 pStubMsg->BufferLength = pRpcMsg->BufferLength;
1430 pStubMsg->MemorySize = pRpcMsg->BufferLength;
1431 pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
1432 pStubMsg->pfnFree = pStubDesc->pfnFree;
1433 pStubMsg->StubDesc = pStubDesc;
1434 pStubMsg->dwDestContext = MSHCTX_LOCAL;
1445 MSRPC_Shutdown(void) {
1446 RPC_SRVSVC_Shutdown();
1450 MSRPC_IsWellKnownService(const clientchar_t * lastNamep)
1453 cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
1454 cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
1455 cm_ClientStrCmpIA(lastNamep, _C("\\spoolss")) == 0 ||
1456 cm_ClientStrCmpIA(lastNamep, _C("\\winreg")) == 0 ||
1457 cm_ClientStrCmpIA(lastNamep, _C("\\lsass")) == 0 ||
1458 cm_ClientStrCmpIA(lastNamep, _C("\\lsarpc")) == 0 ||
1459 cm_ClientStrCmpIA(lastNamep, _C("\\samr")) == 0 ||
1460 cm_ClientStrCmpIA(lastNamep, _C("\\netlogon")) == 0 ||
1461 cm_ClientStrCmpIA(lastNamep, _C("\\ntsvcs")) == 0 ||
1462 cm_ClientStrCmpIA(lastNamep, _C("\\eventlog")) == 0 ||
1463 cm_ClientStrCmpIA(lastNamep, _C("\\svcctl")) == 0 ||
1464 cm_ClientStrCmpIA(lastNamep, _C("\\browse")) == 0 ||
1465 cm_ClientStrCmpIA(lastNamep, _C("\\msgsvc")) == 0 ||
1466 cm_ClientStrCmpIA(lastNamep, _C("\\w32time")) == 0 ||
1467 cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0;