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 if (len > MAX_RPC_MSG_SIZE)
983 return CM_ERROR_BUFFERTOOSMALL;
985 call = MSRPC_NewCall();
989 MSRPC_AllocBuffer(&call->in, len);
990 memcpy(call->in.buf_data, buffer, len);
991 call->in.buf_pos = len;
992 call->in.buf_length = call->in.buf_pos;
993 call->status = MSRPC_CALL_MSGRECEIVED;
996 call->cm_userp = userp;
1000 MSRPC_PutCall(conn, call);
1005 /*! \brief Prepare to read the next message from the RPC output queue
1007 Each RPC message received is queued until the response is required.
1008 MSRPC_PrepareRead() will, if necessary, dispatch the RPC request
1009 and prepare the output buffer to be sent to the caller.
1012 MSRPC_PrepareRead(msrpc_conn * conn)
1017 while (conn->head) {
1020 if (call->status == MSRPC_CALL_SKIP ||
1021 call->status == MSRPC_CALL_MSGSENT ||
1022 (call->status == MSRPC_CALL_DISPATCHED &&
1023 call->out.buf_length == 0)) {
1025 MSRPC_DequeueCall(conn, call);
1026 MSRPC_FreeCall(call);
1030 if (call->status == MSRPC_CALL_MSGRECEIVED) {
1031 code = dispatch_call(conn);
1033 /* If the dispatch failed, then we discard the message.
1034 If the error was handled and a response packet was
1035 created, dispatch_call() would return 0. */
1038 MSRPC_DequeueCall(conn, call);
1039 MSRPC_FreeCall(call);
1044 break; /* the status wasn't SKIP or
1045 MSGRECEIVED, or we successfully
1046 dispatched the message. */
1049 if (conn->head == NULL)
1050 return CM_ERROR_BADFD;
1052 if (conn->head->status == MSRPC_CALL_DISPATCHED ||
1053 conn->head->status == MSRPC_CALL_MSGSENDING)
1056 return CM_ERROR_BADFD;
1059 /*! \brief Return the size of the buffer for the next RPC message
1061 Given the maximum size of the buffer, returns the actual size of
1062 the data that will be copied. If the return value is 0, there is
1063 no data to be sent to the caller either because there was no RPC
1064 message queued or the queued message could not be dispatched.
1067 MSRPC_ReadMessageLength(msrpc_conn * conn, unsigned int max_len)
1072 max_len = min(max_len, conn->max_recv_frag);
1074 code = MSRPC_PrepareRead(conn);
1081 (call->status == MSRPC_CALL_DISPATCHED ||
1082 call->status == MSRPC_CALL_MSGSENDING)) {
1084 switch(call->out.pdu_type) {
1085 case PDU_TYPE_RESPONSE:
1087 /* This calculation should mirror what
1088 MSRPC_ReadMessage() does below. */
1090 int fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1093 len = min(max_len, conn->max_recv_frag);
1095 if (call->out.buf_pos % fragment_size == 0) {
1096 if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD)
1099 len = min(len, RPC_RESPONSE_ENVELOPE_OVERHEAD + call->out.buf_length - call->out.buf_pos);
1101 unsigned int to_copy;
1103 to_copy = min(fragment_size - (call->out.buf_pos % fragment_size),
1104 call->out.buf_length - call->out.buf_pos);
1105 len = min(to_copy, len);
1111 case PDU_TYPE_BIND_ACK:
1112 case PDU_TYPE_FAULT:
1113 case PDU_TYPE_BIND_NAK:
1115 int len = min(call->out.buf_length - call->out.buf_pos, max_len);
1127 /*! \brief Read the next message from the RPC queue
1129 Copies the next chunk of data from the response buffer to the
1130 buffer indicated by \a buffer and \a len.
1132 \retval 0 The data was copied to the buffer. There is either no
1133 more data to send or the existence of more data is implicit in
1134 the data already sent. I.e. fragment flags were set
1135 appropriately to indicate more data and we are at a fragment
1138 \retval CM_ERROR_RPC_MOREDATA The data was copied to the buffer and
1139 there is more data to be sent.
1141 \retval Else something went wrong. The data was not copied to the
1142 buffer successfully.
1145 MSRPC_ReadMessage(msrpc_conn * conn, BYTE *buffer, unsigned int len)
1150 code = MSRPC_PrepareRead(conn);
1155 (conn->head->status == MSRPC_CALL_DISPATCHED ||
1156 conn->head->status == MSRPC_CALL_MSGSENDING)) {
1160 switch(call->out.pdu_type) {
1161 case PDU_TYPE_RESPONSE:
1163 BYTE * o_buffer = call->out.buf_data;
1164 unsigned int o_alloc = call->out.buf_alloc;
1165 unsigned int o_pos = call->out.buf_pos;
1166 unsigned int o_len = call->out.buf_length;
1167 unsigned int start_pos = o_pos;
1168 unsigned int fragment_size;
1171 /* If call->out.buf_pos falls on a fragment boundary:
1173 Assume that we are starting a new fragment and deal accordingly.
1177 Assume we are continuing a fragment.
1180 fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1182 /* Don't send more than the max_recv_frag */
1183 len = min(len, conn->max_recv_frag);
1185 /* Switch the supplied user buffer with the output
1187 call->out.buf_data = buffer;
1188 call->out.buf_length = 0;
1189 call->out.buf_alloc = len;
1190 call->out.buf_pos = 0;
1192 if (o_pos % fragment_size == 0) {
1196 We need to write the packet headers and
1197 fragment bits here. The length of the buffer
1198 should be at least big enough to hold the
1199 entire envelope. We don't handle the case were
1200 the envelope itself is too big.
1204 if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD) {
1205 return CM_ERROR_INVAL;
1208 code = write_E_CommonHeader(&o, conn, call, PDU_TYPE_RESPONSE);
1212 write_u_int32(&o, o_len); /* allocation hint */
1213 write_u_int16(&o, call->context_id); /* presentation context ID */
1214 write_u_int8(&o, 0); /* cancel count */
1215 write_u_int8(&o, 0); /* reserved */
1218 int to_copy = min(SPC_LEFT(&o), o_len - o_pos);
1221 O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1223 /* the fragment size of the message is the minimum of:
1225 - max_recv_frag for the connection
1226 - envelope size + (full message size - start offset)
1229 rc = closeMessage(&o, call,
1230 min(conn->max_recv_frag,
1231 RPC_RESPONSE_ENVELOPE_OVERHEAD + o_len - start_pos));
1237 /* If there is more data to be sent and we are
1238 not at a fragment boundary after the last
1239 send, we return CM_ERROR_RPC_MOREDATA.
1240 Having more fragments to send is not a case
1241 we indicate via a return value. */
1243 if (o_pos < o_len &&
1244 o_pos < start_pos + fragment_size)
1245 code = CM_ERROR_RPC_MOREDATA;
1248 if (start_pos + fragment_size < o_len)
1249 buffer[3] &= ~PFC_LAST_FRAG;
1252 buffer[3] &= ~PFC_FIRST_FRAG;
1258 The packet header should have already been sent
1259 in a previous block.
1262 unsigned int to_copy;
1264 INITC(&o, call->out.buf_data, call->out.buf_alloc);
1266 to_copy = min(fragment_size - (o_pos % fragment_size),
1268 to_copy = min(to_copy, SPC_LEFT(&o));
1270 O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1274 if (o_pos < o_len && (o_pos % fragment_size) != 0)
1275 code = CM_ERROR_RPC_MOREDATA;
1278 call->out.buf_data = o_buffer;
1279 call->out.buf_alloc = o_alloc;
1280 call->out.buf_pos = o_pos;
1281 call->out.buf_length = o_len;
1283 if (call->out.buf_pos < call->out.buf_length) {
1284 call->status = MSRPC_CALL_MSGSENDING;
1286 call->status = MSRPC_CALL_MSGSENT;
1287 MSRPC_DequeueCall(conn, call);
1288 MSRPC_FreeCall(call);
1293 case PDU_TYPE_BIND_ACK:
1294 case PDU_TYPE_FAULT:
1295 case PDU_TYPE_BIND_NAK:
1297 unsigned int to_send;
1299 /* These types of packets are already fully formed.
1300 We don't need to wrap them in an envelope. They
1301 also don't fragment. */
1303 to_send = call->out.buf_length - call->out.buf_pos;
1306 code = CM_ERROR_RPC_MOREDATA;
1311 memcpy(buffer, call->out.buf_data + call->out.buf_pos, len);
1314 call->out.buf_pos += len;
1316 if (call->out.buf_pos < call->out.buf_length) {
1317 call->status = MSRPC_CALL_MSGSENDING;
1319 call->status = MSRPC_CALL_MSGSENT;
1320 MSRPC_DequeueCall(conn, call);
1321 MSRPC_FreeCall(call);
1327 return CM_ERROR_INVAL;
1333 pthread_once_t msrpc_user_slot_init = PTHREAD_ONCE_INIT;
1335 DWORD msrpc_tls_user_slot = 0;
1338 msrpc_user_slot_init_func(void)
1340 msrpc_tls_user_slot = TlsAlloc();
1344 MSRPC_GetCmUser(void)
1346 pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1348 return (cm_user_t *) TlsGetValue(msrpc_tls_user_slot);
1352 MSRPC_SetCmUser(cm_user_t * userp)
1354 pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1356 TlsSetValue(msrpc_tls_user_slot, userp);
1359 typedef struct I_RpcAllocatedBuffer {
1360 DWORD magic; /* == _RPCALLOCATEDBUFFER_MAGIC */
1361 #define _RPCALLOCATEDBUFFER_MAGIC 0xa110ca73
1362 struct I_RpcAllocatedBuffer * next;
1364 /* Data goes here */
1365 } I_RpcAllocatedBuffer;
1367 #define I_RPCALLOCATEDBUFFER_FROM_PTR(v) (&(((I_RpcAllocatedBuffer *) (v))[-1]))
1371 I_RpcGetBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1373 I_RpcAllocatedBuffer * newBuffer = I_RpcAllocate(Message->BufferLength + sizeof(I_RpcAllocatedBuffer));
1374 I_RpcAllocatedBuffer * oldBuffer = NULL;
1376 if (Message->Buffer) {
1377 oldBuffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1381 newBuffer->magic = _RPCALLOCATEDBUFFER_MAGIC;
1382 newBuffer->next = oldBuffer;
1384 Message->Buffer = &newBuffer[1];
1386 return ERROR_OUTOFMEMORY;
1394 I_RpcFreeBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1396 if (Message->Buffer) {
1397 I_RpcAllocatedBuffer * buffer;
1399 buffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1402 I_RpcAllocatedBuffer * bnext;
1404 bnext = buffer->next;
1411 Message->Buffer = NULL;
1419 NdrServerInitializeNew(
1420 PRPC_MESSAGE pRpcMsg,
1421 PMIDL_STUB_MESSAGE pStubMsg,
1422 PMIDL_STUB_DESC pStubDesc
1425 ZeroMemory(pStubMsg, sizeof(*pStubMsg));
1427 pStubMsg->RpcMsg = pRpcMsg;
1428 pStubMsg->Buffer = pRpcMsg->Buffer;
1429 pStubMsg->BufferStart = pRpcMsg->Buffer;
1430 pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
1431 pStubMsg->BufferLength = pRpcMsg->BufferLength;
1432 pStubMsg->MemorySize = pRpcMsg->BufferLength;
1433 pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
1434 pStubMsg->pfnFree = pStubDesc->pfnFree;
1435 pStubMsg->StubDesc = pStubDesc;
1436 pStubMsg->dwDestContext = MSHCTX_LOCAL;
1447 MSRPC_Shutdown(void) {
1448 RPC_SRVSVC_Shutdown();
1452 MSRPC_IsWellKnownService(const clientchar_t * lastNamep)
1455 cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
1456 cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
1457 cm_ClientStrCmpIA(lastNamep, _C("\\spoolss")) == 0 ||
1458 cm_ClientStrCmpIA(lastNamep, _C("\\winreg")) == 0 ||
1459 cm_ClientStrCmpIA(lastNamep, _C("\\lsass")) == 0 ||
1460 cm_ClientStrCmpIA(lastNamep, _C("\\lsarpc")) == 0 ||
1461 cm_ClientStrCmpIA(lastNamep, _C("\\samr")) == 0 ||
1462 cm_ClientStrCmpIA(lastNamep, _C("\\netlogon")) == 0 ||
1463 cm_ClientStrCmpIA(lastNamep, _C("\\ntsvcs")) == 0 ||
1464 cm_ClientStrCmpIA(lastNamep, _C("\\eventlog")) == 0 ||
1465 cm_ClientStrCmpIA(lastNamep, _C("\\svcctl")) == 0 ||
1466 cm_ClientStrCmpIA(lastNamep, _C("\\browse")) == 0 ||
1467 cm_ClientStrCmpIA(lastNamep, _C("\\msgsvc")) == 0 ||
1468 cm_ClientStrCmpIA(lastNamep, _C("\\w32time")) == 0 ||
1469 cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0;