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
25 #include <afsconfig.h>
26 #include <afs/param.h>
30 #include "ms-wkssvc.h"
31 #include "ms-srvsvc.h"
38 MSRPC_AllocBuffer(msrpc_buffer * buf, unsigned int size);
41 MSRPC_ReallocBuffer(msrpc_buffer * buf, unsigned int size);
44 MSRPC_FreeBuffer(msrpc_buffer * buf);
47 MSRPC_SetCmUser(cm_user_t * userp);
49 /*! \brief Interface list
51 This is the list of interfaces that are exported through this RPC
52 module. The *_ifspec variable is defined the <interface>_s.c file
53 that is generated by MIDL. We have to use an extra level of
54 indirection because the actual RPC_SERVER_INTERFACE structure is
55 not exported in the generated code.
57 RPC_SERVER_INTERFACE **_Interfaces[] = {
58 (RPC_SERVER_INTERFACE **) &wkssvc_v1_0_s_ifspec,
59 (RPC_SERVER_INTERFACE **) &srvsvc_v3_0_s_ifspec,
62 const int n_Interfaces = sizeof(_Interfaces)/sizeof(_Interfaces[0]);
66 #define RPC_ALIGNMENT 8
67 #define ALIGNTO8(x) (((((x) - 1)/8) + 1) * 8)
69 typedef struct fcursor {
74 #define INITC(pfc, buf, len) (pfc)->pos = (BYTE *)(buf); (pfc)->end = (pfc)->pos + (len)
76 #define SPC_LEFT(pfc) ((unsigned int)((pfc)->end - (pfc)->pos))
77 #define IS_SPC(pfc, n) (SPC_LEFT(pfc) >= (n))
79 __inline BYTE READB(fcursor * pfc) {
85 #define READW(pfc) (((WORD)READB(pfc)) | (((WORD)READB(pfc)) << 8))
86 #define READDW(pfc) (((DWORD)READW(pfc)) | (((DWORD)READW(pfc)) << 16))
87 #define O_READS(pfc, s) do { memcpy(s, (pfc)->pos, sizeof(*s)); (pfc)->pos += sizeof(*s); } while (0)
88 #define O_READA(pfc, a) do { memcpy(&a, (pfc)->pos, sizeof(a)); (pfc)->pos += sizeof(a); } while (0)
89 #define O_READSZ(pfc, s, sz) do { memcpy(s, (pfc)->pos, sz); (pfc)->pos += sz; } while (0)
90 #define O_RALIGN4(pfc) do { while(((size_t) (pfc)->pos) & 0x3) READB(pfc); } while (0)
91 #define O_RALIGN8(pfc) do { while(((size_t) (pfc)->pos) & 0x7) READB(pfc); } while (0)
93 __inline void WRITEB(fcursor * pfc, BYTE b) {
98 #define WRITEW(pfc, w) (WRITEB(pfc, ((w) & 0xff)), WRITEB(pfc, (((w) >> 8) & 0xff)))
99 #define WRITEDW(pfc, dw) (WRITEW(pfc, ((dw) & 0xffff)), WRITEW(pfc, (((dw) >> 16) & 0xffff)))
100 #define O_WRITES(pfc, s) do { memcpy((pfc)->pos, s, sizeof(*s)); (pfc)->pos += sizeof(*s); } while (0)
101 #define O_WRITEA(pfc, a) do { memcpy((pfc)->pos, &a, sizeof(a)); (pfc)->pos += sizeof(a); } while (0)
102 #define O_WRITESZ(pfc, s, sz) do { memcpy((pfc)->pos, s, sz); (pfc)->pos += sz; } while (0)
103 #define O_WALIGN4(pfc) do { while(((size_t) (pfc)->pos) & 0x3) WRITEB(pfc, 0); } while (0)
104 #define O_WALIGN8(pfc) do { while(((size_t) (pfc)->pos) & 0x7) WRITEB(pfc, 0); } while (0)
106 #define iread_u_int8(pfc) READB(pfc)
107 #define iread_byte(pfc) READB(pfc)
108 #define iread_u_int16(pfc) READW(pfc)
109 #define iread_u_int32(pfc) READDW(pfc)
111 #define write_u_int8(pfc, i) WRITEB(pfc, i)
112 #define write_byte(pfc, i) WRITEB(pfc, i)
113 #define write_u_int16(pfc, i) WRITEW(pfc, i)
114 #define write_u_int32(pfc, i) WRITEDW(pfc, i)
116 /*! \brief Supported RPC protocol version numbers */
117 RPC_VERSION msrpc_supported_protocol_versions[] = {
122 const int n_msrpc_supported_protocol_versions = sizeof(msrpc_supported_protocol_versions)/sizeof(msrpc_supported_protocol_versions[0]);
124 #define IS_PROTOCOL_VER_SUPPORTED(_maj, _min) ((_maj) == 5 && ((_min) == 0 || (_min) == 1))
126 /*! \brief Number of bytes of envelope overhead for an RPC response PDU */
127 #define RPC_RESPONSE_ENVELOPE_OVERHEAD 24
130 read_E_CommonHeader(fcursor *pc, E_CommonHeader * pr)
132 if (IS_SPC(pc, 16)) {
134 pr->rpc_vers = iread_u_int8(pc);
135 pr->rpc_vers_minor = iread_u_int8(pc);
136 pr->PTYPE = iread_u_int8(pc);
137 pr->pfc_flags = iread_u_int8(pc);
138 O_READA(pc, pr->packed_drep);
139 pr->frag_length = iread_u_int16(pc);
140 pr->auth_length = iread_u_int16(pc);
141 pr->call_id = iread_u_int32(pc);
146 return CM_ERROR_BADFORMAT;
151 write_E_CommonHeader(fcursor * pc, msrpc_conn * conn,
152 msrpc_call * call, PDU_TYPE pdu_type)
154 INITC(pc, call->out.buf_data, call->out.buf_alloc);
156 call->out.pdu_type = pdu_type;
158 if (IS_SPC(pc, 16)) {
159 write_u_int8(pc, conn->rpc_vers); /* protocol version */
160 write_u_int8(pc, conn->rpc_vers_minor); /* minor version */
161 write_u_int8(pc, pdu_type);
162 write_u_int8(pc, PFC_FIRST_FRAG|PFC_LAST_FRAG);
164 write_byte(pc, 0x10); /* Data representation */
169 write_u_int16(pc, 0); /* Fragment ength, to be filled in
171 write_u_int16(pc, 0); /* Length of auth data. Always 0 since
172 we don't do authentication for RPC
174 write_u_int32(pc, call->call_id);
178 return CM_ERROR_BUFFERTOOSMALL;
182 #define USE_CURRENT_BUFFER_LENGTH (-1)
184 closeMessage(fcursor * pc, msrpc_call * call, ptrdiff_t len)
189 if (len == USE_CURRENT_BUFFER_LENGTH)
190 len = pc->pos - call->out.buf_data;
192 if (len >= USHRT_MAX)
193 return CM_ERROR_TOOBIG;
194 slen = (unsigned short)len;
196 pc->pos = &call->out.buf_data[8];
197 write_u_int16(pc, slen);
198 call->out.buf_length = slen;
204 read_UUID(fcursor * pc,
207 if (IS_SPC(pc, sizeof(*uuid))) {
211 return CM_ERROR_BADFORMAT;
216 write_UUID(fcursor * pc,
219 if (IS_SPC(pc, sizeof(*uuid))) {
223 return CM_ERROR_BUFFERTOOSMALL;
228 read_RPC_VERSION(fcursor * pc,
232 ver->MajorVersion = iread_u_int16(pc);
233 ver->MinorVersion = iread_u_int16(pc);
236 return CM_ERROR_BADFORMAT;
241 write_RPC_VERSION(fcursor * pc,
242 const RPC_VERSION * ver)
245 write_u_int16(pc, ver->MajorVersion);
246 write_u_int16(pc, ver->MinorVersion);
249 return CM_ERROR_BUFFERTOOSMALL;
254 read_RPC_SYNTAX_IDENTIFIER(fcursor * pc,
255 RPC_SYNTAX_IDENTIFIER * psi)
259 code = read_UUID(pc, &psi->SyntaxGUID);
262 code = read_RPC_VERSION(pc, &psi->SyntaxVersion);
267 write_RPC_SYNTAX_IDENTIFIER(fcursor * pc,
268 const RPC_SYNTAX_IDENTIFIER * psi)
272 code = write_UUID(pc, &psi->SyntaxGUID);
275 code = write_RPC_VERSION(pc, &psi->SyntaxVersion);
280 is_equal_RPC_SYNTAX_IDENTIFIER(const RPC_SYNTAX_IDENTIFIER * s1,
281 const RPC_SYNTAX_IDENTIFIER * s2)
284 IsEqualGUID(&s1->SyntaxGUID, &s2->SyntaxGUID) &&
285 s1->SyntaxVersion.MajorVersion == s2->SyntaxVersion.MajorVersion &&
286 s2->SyntaxVersion.MinorVersion == s2->SyntaxVersion.MinorVersion;
289 #define FAULT_PDU_PACKET_SIZE 32
291 /*! \brief Write a fault PDU as the output of this call */
293 write_fault_PDU(msrpc_conn * conn, msrpc_call * call,
294 u_int32 status, u_int8 flags)
298 MSRPC_AllocBuffer(&call->out, FAULT_PDU_PACKET_SIZE);
300 write_E_CommonHeader(&o, conn, call, PDU_TYPE_FAULT);
302 write_u_int32(&o, 16); /* allocation hint */
303 write_u_int16(&o, call->context_id); /* presentation context ID */
305 write_u_int8(&o, 0); /* cancel count */
306 write_u_int8(&o, 0); /* reserved */
308 write_u_int32(&o, status); /* status code */
310 O_WALIGN8(&o); /* alignment */
312 closeMessage(&o, call, USE_CURRENT_BUFFER_LENGTH);
315 call->out.buf_data[3] |= flags;
318 call->status = MSRPC_CALL_DISPATCHED;
323 #define BIND_NAK_PDU_PACKET_SIZE 18
325 /*! \brief Write a bind_nak PDU as the output of this call */
327 write_bind_nak_PDU(msrpc_conn * conn, msrpc_call * call,
328 BIND_REJECT_REASON reject_reason)
331 unsigned buf_size = BIND_NAK_PDU_PACKET_SIZE;
333 if (reject_reason == BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED)
334 buf_size += n_msrpc_supported_protocol_versions * 2 + 1;
336 MSRPC_AllocBuffer(&call->out, buf_size);
338 write_E_CommonHeader(&o, conn, call, PDU_TYPE_BIND_NAK);
340 write_u_int16(&o, reject_reason);
342 if (reject_reason == BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED) {
345 write_u_int8(&o, n_msrpc_supported_protocol_versions);
347 for (i=0; i < n_msrpc_supported_protocol_versions; i++) {
348 write_u_int8(&o, (u_int8) msrpc_supported_protocol_versions[i].MajorVersion);
349 write_u_int8(&o, (u_int8) msrpc_supported_protocol_versions[i].MinorVersion);
353 closeMessage(&o, call, USE_CURRENT_BUFFER_LENGTH);
355 call->status = MSRPC_CALL_DISPATCHED;
361 handle_ConnBind(msrpc_conn * conn, msrpc_call * call, fcursor * in, fcursor * out)
366 return CM_ERROR_BADFORMAT;
368 conn->max_xmit_frag = iread_u_int16(in);
369 conn->max_recv_frag = iread_u_int16(in);
370 conn->assoc_group_id = iread_u_int32(in);
372 conn->rpc_vers = call->in_header->rpc_vers;
373 conn->rpc_vers_minor = call->in_header->rpc_vers_minor;
375 if (conn->assoc_group_id == 0)
376 conn->assoc_group_id = 1;
378 write_E_CommonHeader(out, conn, call, PDU_TYPE_BIND_ACK);
380 write_u_int16(out, conn->max_xmit_frag);
381 write_u_int16(out, conn->max_recv_frag);
382 write_u_int32(out, conn->assoc_group_id);
384 if (conn->secondary_address) {
385 int len = (int)strlen(conn->secondary_address) + 1;
387 write_u_int16(out, len);
388 O_WRITESZ(out, conn->secondary_address, len);
390 write_u_int16(out, 0);
395 /* presentation context negotiation */
400 n_context_elem = iread_u_int8(in);
401 iread_u_int8(in); /* skip over reserved */
402 iread_u_int16(in); /* skip over reserved */
404 write_u_int8(out, n_context_elem);
405 write_u_int8(out, 0); /* pad */
406 write_u_int16(out, 0); /* pad */
408 for (i=0; i < n_context_elem; i++) {
410 RPC_SYNTAX_IDENTIFIER abstract_syntax;
411 RPC_SYNTAX_IDENTIFIER transfer_syntax;
412 RPC_SERVER_INTERFACE *interf = NULL;
415 if (!IS_SPC(in, 4 + 16))
416 return CM_ERROR_BADFORMAT;
418 call->context_id = iread_u_int16(in);
419 n_transfer_syn = iread_u_int8(in);
420 iread_u_int8(in); /* skip */
422 code = read_RPC_SYNTAX_IDENTIFIER(in, &abstract_syntax);
426 for (j=0; j < n_Interfaces; j++) {
427 interf = *_Interfaces[j];
429 if (is_equal_RPC_SYNTAX_IDENTIFIER(&abstract_syntax, &interf->InterfaceId))
433 if (j < n_Interfaces) {
434 for (k=0; k < n_transfer_syn; k++) {
435 code = read_RPC_SYNTAX_IDENTIFIER(in, &transfer_syntax);
439 if (is_equal_RPC_SYNTAX_IDENTIFIER(&transfer_syntax, &interf->TransferSyntax))
444 if (j < n_Interfaces && k < n_transfer_syn) {
446 write_u_int16(out, 0);
447 write_u_int16(out, 0);
448 write_RPC_SYNTAX_IDENTIFIER(out, &transfer_syntax);
450 conn->interface = interf;
454 if (j >= n_Interfaces)
455 reason = 1; /* abstract syntax not supported */
457 reason = 2; /* transfer syntax not supported */
458 write_u_int16(out, 2); /* provider rejection */
459 write_u_int16(out, reason);
460 ZeroMemory(&transfer_syntax, sizeof(transfer_syntax));
461 write_RPC_SYNTAX_IDENTIFIER(out, &transfer_syntax);
466 return closeMessage(out, call, USE_CURRENT_BUFFER_LENGTH);
470 handle_ConnRequest(msrpc_conn * conn, msrpc_call * call, fcursor * in, fcursor * out)
476 RPC_STATUS _Status = RPC_S_OK;
481 return CM_ERROR_BADFORMAT;
483 alloc_hint = iread_u_int32(in);
484 call->context_id = iread_u_int16(in);
485 op_num = iread_u_int16(in);
487 if (call->in_header->pfc_flags & PFC_OBJECT_UUID) {
490 code = read_UUID(in, &uuid);
497 if (conn->interface == NULL) {
498 /* if there was no interface selected, we can't go ahead with
500 return write_fault_PDU(conn, call, RPC_S_NO_BINDINGS, PFC_DID_NOT_EXECUTE);
505 if (op_num < 0 || op_num >= conn->interface->DispatchTable->DispatchTableCount ||
506 conn->interface->DispatchTable->DispatchTable[op_num] == NULL) {
508 return write_fault_PDU(conn, call, RPC_S_PROCNUM_OUT_OF_RANGE, PFC_DID_NOT_EXECUTE);
511 call->msg.BufferLength = len;
512 call->msg.ProcNum = op_num;
513 call->msg.TransferSyntax = &conn->interface->TransferSyntax;
514 call->msg.RpcInterfaceInformation = conn->interface;
516 _Status = I_RpcGetBuffer(&call->msg);
517 if ( _Status || call->msg.Buffer == NULL) {
518 return write_fault_PDU(conn, call, RPC_S_SERVER_OUT_OF_MEMORY, PFC_DID_NOT_EXECUTE);
521 memcpy(call->msg.Buffer, in->pos, len);
523 MSRPC_SetCmUser(call->cm_userp);
527 (*conn->interface->DispatchTable->DispatchTable[op_num])(&call->msg);
531 code = CM_ERROR_UNKNOWN;
535 MSRPC_SetCmUser(NULL);
538 call->out.pdu_type = PDU_TYPE_RESPONSE;
540 MSRPC_AllocBuffer(&call->out, call->msg.BufferLength);
541 call->out.buf_length = call->msg.BufferLength;
542 memcpy(call->out.buf_data, call->msg.Buffer, call->out.buf_length);
544 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, 0);
551 merge_fragment_Bind(msrpc_call * call, E_CommonHeader * ph,
552 msrpc_call * ncall, E_CommonHeader *pnh)
554 if (ph->auth_length + (unsigned int) pnh->auth_length > _UI16_MAX ||
555 ph->frag_length + (unsigned int) pnh->auth_length > _UI16_MAX ||
556 pnh->auth_length + 16 > pnh->frag_length)
557 return CM_ERROR_TOOBIG;
559 MSRPC_ReallocBuffer(&call->in, call->in.buf_length + pnh->auth_length);
560 if (call->in.buf_data == NULL)
561 return CM_ERROR_TOOBIG;
563 memcpy(call->in.buf_data + ph->frag_length,
564 ncall->in.buf_data + (pnh->frag_length - pnh->auth_length),
567 call->in.buf_length += pnh->auth_length;
568 ph->frag_length += pnh->auth_length;
569 ph->auth_length += pnh->auth_length;
571 if ((pnh->pfc_flags & PFC_LAST_FRAG) == PFC_LAST_FRAG) {
572 ph->pfc_flags |= PFC_LAST_FRAG;
579 merge_fragment_Request(msrpc_call * call, E_CommonHeader * ph,
580 msrpc_call * ncall, E_CommonHeader * pnh)
582 int new_auth_length = pnh->auth_length;
583 int new_stub_length = (int)pnh->frag_length - (pnh->auth_length + 24);
585 if (pnh->pfc_flags & PFC_OBJECT_UUID)
586 new_stub_length -= 16;
588 if (ph->auth_length + new_auth_length > _UI16_MAX ||
589 ph->frag_length + new_stub_length + new_auth_length > _UI16_MAX ||
590 pnh->auth_length + 24 > pnh->frag_length)
591 return CM_ERROR_TOOBIG;
593 MSRPC_ReallocBuffer(&call->in, call->in.buf_length + new_auth_length + new_stub_length);
594 if (call->in.buf_data == NULL)
595 return CM_ERROR_TOOBIG;
598 memmove(call->in.buf_data + (ph->frag_length - ph->auth_length),
599 call->in.buf_data + (ph->frag_length - ph->auth_length) + new_stub_length,
602 memcpy(call->in.buf_data + (ph->frag_length - ph->auth_length),
603 ncall->in.buf_data + (pnh->frag_length - (new_auth_length + new_stub_length)),
606 memcpy(call->in.buf_data + ph->frag_length + new_stub_length,
607 ncall->in.buf_data + (pnh->frag_length - pnh->auth_length),
610 call->in.buf_length += new_auth_length + new_stub_length;
611 ph->frag_length += new_auth_length + new_stub_length;
612 ph->auth_length += new_auth_length;
614 if ((pnh->pfc_flags & PFC_LAST_FRAG) == PFC_LAST_FRAG) {
615 ph->pfc_flags |= PFC_LAST_FRAG;
622 assemble_message(msrpc_conn * conn)
633 return CM_ERROR_INVAL;
635 INITC(&c, call->in.buf_data, call->in.buf_length);
637 code = read_E_CommonHeader(&c, &h);
641 if ((h.pfc_flags & (PFC_FIRST_FRAG | PFC_LAST_FRAG)) ==
642 (PFC_FIRST_FRAG | PFC_LAST_FRAG))
645 if ((h.pfc_flags & PFC_FIRST_FRAG) != PFC_FIRST_FRAG)
646 return CM_ERROR_INVAL;
648 for (ncall = call->next; ncall; ncall = ncall->next) {
652 INITC(&nc, ncall->in.buf_data, ncall->in.buf_length);
654 code = read_E_CommonHeader(&nc, &nh);
656 if (nh.call_id != h.call_id)
659 if ((nh.pfc_flags & PFC_FIRST_FRAG) != 0)
664 case PDU_TYPE_ALTER_CONTEXT:
665 code = merge_fragment_Bind(call, &h, ncall, &nh);
668 case PDU_TYPE_REQUEST:
669 code = merge_fragment_Request(call, &h, ncall, &nh);
673 code = CM_ERROR_INVAL;
676 ncall->status = MSRPC_CALL_SKIP;
678 if (nh.pfc_flags & PFC_LAST_FRAG) {
683 c.pos = &call->in.buf_data[3];
684 write_u_int8(&c, h.pfc_flags);
685 write_u_int16(&c, h.frag_length);
686 write_u_int16(&c, h.auth_length);
692 dispatch_call(msrpc_conn * conn)
703 call->status != MSRPC_CALL_MSGRECEIVED)
704 return CM_ERROR_INVAL;
706 MSRPC_AllocBuffer(&call->out, DEF_RPC_MSG_SIZE);
710 INITC(&c, call->in.buf_data, call->in.buf_length);
712 code = read_E_CommonHeader(&c, &h);
716 if (!IS_PROTOCOL_VER_SUPPORTED(h.rpc_vers, h.rpc_vers_minor)) {
717 if (h.PTYPE == PDU_TYPE_BIND) {
718 return write_bind_nak_PDU(conn, call, BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED);
720 /* we shouldn't get here, but just in case */
721 return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
725 if (h.packed_drep[0] != 0x10 ||
726 h.packed_drep[1] != 0 ||
727 h.packed_drep[2] != 0 ||
728 h.packed_drep[3] != 0) {
730 if (h.PTYPE == PDU_TYPE_BIND) {
731 return write_bind_nak_PDU(conn, call, BIND_REJ_REASON_NOT_SPECIFIED);
733 return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
737 if (h.frag_length > call->in.buf_length) {
738 return CM_ERROR_INVAL;
741 if ((h.pfc_flags & (PFC_FIRST_FRAG | PFC_LAST_FRAG)) !=
742 (PFC_FIRST_FRAG | PFC_LAST_FRAG)) {
743 code = assemble_message(conn);
747 return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
750 if (h.auth_length != 0) {
751 return write_fault_PDU(conn, call, RPC_S_BINDING_HAS_NO_AUTH, PFC_DID_NOT_EXECUTE);
754 call->call_id = h.call_id;
756 call->in.pdu_type = h.PTYPE;
758 INITC(&o, call->out.buf_data, call->out.buf_alloc);
760 call->in_header = &h;
762 code = CM_ERROR_INVAL;
765 case PDU_TYPE_REQUEST:
766 code = handle_ConnRequest(conn, call, &c, &o);
770 code = handle_ConnBind(conn, call, &c, &o);
773 case PDU_TYPE_ALTER_CONTEXT:
774 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
777 case PDU_TYPE_SHUTDOWN:
778 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
781 case PDU_TYPE_CO_CANCEL:
782 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
785 case PDU_TYPE_ORPHANED:
786 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
790 code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
793 call->in_header = NULL;
795 call->status = MSRPC_CALL_DISPATCHED;
801 MSRPC_AllocBuffer(msrpc_buffer * buf, unsigned int size)
803 if (buf->buf_alloc < size) {
805 _aligned_free(buf->buf_data);
807 buf->buf_alloc = ALIGNTO8(size);
808 buf->buf_data = _aligned_malloc(buf->buf_alloc, RPC_ALIGNMENT);
815 MSRPC_FreeBuffer(msrpc_buffer * buf)
818 _aligned_free(buf->buf_data);
819 buf->buf_data = NULL;
827 MSRPC_ReallocBuffer(msrpc_buffer * buf, unsigned int size)
829 if (buf->buf_alloc < size) {
832 buf->buf_alloc = ALIGNTO8(size);
833 new_buf = _aligned_realloc(buf->buf_data, buf->buf_alloc, RPC_ALIGNMENT);
834 if (new_buf != NULL) {
835 buf->buf_data = new_buf;
837 MSRPC_FreeBuffer(buf);
847 c = calloc(sizeof(*c), 1);
849 c->msg.Handle = NULL;
850 c->msg.DataRepresentation = 0x00000010;
851 c->msg.Buffer = NULL;
852 c->msg.BufferLength = 0;
853 c->msg.TransferSyntax = NULL;
859 MSRPC_PutCall(msrpc_conn * conn, msrpc_call * pcall)
862 conn->tail->next = pcall;
863 pcall->prev = conn->tail;
867 conn->head = conn->tail = pcall;
868 pcall->next = pcall->prev = NULL;
874 MSRPC_DequeueCall(msrpc_conn * conn, msrpc_call * call)
877 call->prev->next = call->next;
879 call->next->prev = call->prev;
881 if (conn->head && conn->head == call)
882 conn->head = call->next;
884 if (conn->tail && conn->tail == call)
885 conn->tail = call->prev;
887 call->next = call->prev = NULL;
893 MSRPC_GetCall(msrpc_conn * conn, msrpc_call ** ppcall)
896 *ppcall = conn->head;
897 conn->head = conn->head->next;
899 conn->head->prev = NULL;
900 (*ppcall)->next = (*ppcall)->prev = NULL;
901 if (conn->tail == *ppcall)
911 MSRPC_FreeCall(msrpc_call * call)
913 I_RpcFreeBuffer(&call->msg);
914 MSRPC_FreeBuffer(&call->in);
915 MSRPC_FreeBuffer(&call->out);
917 if (call->cm_userp) {
918 cm_ReleaseUser(call->cm_userp);
919 call->cm_userp = NULL;
922 ZeroMemory(call, sizeof(*call));
927 /*! \brief Initialize a msrpc_conn
929 \param [out] conn Connection to initialize
931 \param [in] secondary_address An optional secondary address for the
932 query. Typically for RPCs to wellknown endpoints such as
933 SRVSVC or WKSSVC, this is a named pipe address (e.g.:
936 \return Always returns 0.
939 MSRPC_InitConn(msrpc_conn * conn, const char * secondary_address)
941 ZeroMemory(conn, sizeof(*conn));
942 if (secondary_address) {
943 conn->secondary_address = strdup(secondary_address);
948 /*! \brief Free a msrcp_conn structure contents
950 This doesn't free the msrpc_conn object, but frees the contents.
953 MSRPC_FreeConn(msrpc_conn * conn)
955 msrpc_call * call = NULL;
957 while(!MSRPC_GetCall(conn, &call)) {
958 MSRPC_FreeCall(call);
961 if (conn->secondary_address)
962 free(conn->secondary_address);
964 ZeroMemory(conn, sizeof(*conn));
969 /*! \brief Write an RPC message into the RPC module
971 This function should be used by message mode RPC transports to
972 submit a single message. if successful, the message will be queued
973 for dispatch. The RPC will not be executed until
974 MSRPC_PrepareRead() or MSRPC_ReadMessageLength() or
975 MSRPC_ReadMessage() is called.
978 MSRPC_WriteMessage(msrpc_conn * conn, BYTE * buffer, unsigned int len,
984 return CM_ERROR_INVAL;
986 if (len > MAX_RPC_MSG_SIZE)
987 return CM_ERROR_BUFFERTOOSMALL;
989 call = MSRPC_NewCall();
993 MSRPC_AllocBuffer(&call->in, len);
994 memcpy(call->in.buf_data, buffer, len);
995 call->in.buf_pos = len;
996 call->in.buf_length = call->in.buf_pos;
997 call->status = MSRPC_CALL_MSGRECEIVED;
1000 call->cm_userp = userp;
1004 MSRPC_PutCall(conn, call);
1009 /*! \brief Prepare to read the next message from the RPC output queue
1011 Each RPC message received is queued until the response is required.
1012 MSRPC_PrepareRead() will, if necessary, dispatch the RPC request
1013 and prepare the output buffer to be sent to the caller.
1016 MSRPC_PrepareRead(msrpc_conn * conn)
1021 while (conn->head) {
1024 if (call->status == MSRPC_CALL_SKIP ||
1025 call->status == MSRPC_CALL_MSGSENT ||
1026 (call->status == MSRPC_CALL_DISPATCHED &&
1027 call->out.buf_length == 0)) {
1029 MSRPC_DequeueCall(conn, call);
1030 MSRPC_FreeCall(call);
1034 if (call->status == MSRPC_CALL_MSGRECEIVED) {
1035 code = dispatch_call(conn);
1037 /* If the dispatch failed, then we discard the message.
1038 If the error was handled and a response packet was
1039 created, dispatch_call() would return 0. */
1042 MSRPC_DequeueCall(conn, call);
1043 MSRPC_FreeCall(call);
1048 break; /* the status wasn't SKIP or
1049 MSGRECEIVED, or we successfully
1050 dispatched the message. */
1053 if (conn->head == NULL)
1054 return CM_ERROR_BADFD;
1056 if (conn->head->status == MSRPC_CALL_DISPATCHED ||
1057 conn->head->status == MSRPC_CALL_MSGSENDING)
1060 return CM_ERROR_BADFD;
1063 /*! \brief Return the size of the buffer for the next RPC message
1065 Given the maximum size of the buffer, returns the actual size of
1066 the data that will be copied. If the return value is 0, there is
1067 no data to be sent to the caller either because there was no RPC
1068 message queued or the queued message could not be dispatched.
1071 MSRPC_ReadMessageLength(msrpc_conn * conn, unsigned int max_len)
1076 max_len = min(max_len, conn->max_recv_frag);
1078 code = MSRPC_PrepareRead(conn);
1085 (call->status == MSRPC_CALL_DISPATCHED ||
1086 call->status == MSRPC_CALL_MSGSENDING)) {
1088 switch(call->out.pdu_type) {
1089 case PDU_TYPE_RESPONSE:
1091 /* This calculation should mirror what
1092 MSRPC_ReadMessage() does below. */
1094 int fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1097 len = min(max_len, conn->max_recv_frag);
1099 if (call->out.buf_pos % fragment_size == 0) {
1100 if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD)
1103 len = min(len, RPC_RESPONSE_ENVELOPE_OVERHEAD + call->out.buf_length - call->out.buf_pos);
1105 unsigned int to_copy;
1107 to_copy = min(fragment_size - (call->out.buf_pos % fragment_size),
1108 call->out.buf_length - call->out.buf_pos);
1109 len = min(to_copy, len);
1115 case PDU_TYPE_BIND_ACK:
1116 case PDU_TYPE_FAULT:
1117 case PDU_TYPE_BIND_NAK:
1119 int len = min(call->out.buf_length - call->out.buf_pos, max_len);
1131 /*! \brief Read the next message from the RPC queue
1133 Copies the next chunk of data from the response buffer to the
1134 buffer indicated by \a buffer and \a len.
1136 \retval 0 The data was copied to the buffer. There is either no
1137 more data to send or the existence of more data is implicit in
1138 the data already sent. I.e. fragment flags were set
1139 appropriately to indicate more data and we are at a fragment
1142 \retval CM_ERROR_RPC_MOREDATA The data was copied to the buffer and
1143 there is more data to be sent.
1145 \retval Else something went wrong. The data was not copied to the
1146 buffer successfully.
1149 MSRPC_ReadMessage(msrpc_conn * conn, BYTE *buffer, unsigned int len)
1154 code = MSRPC_PrepareRead(conn);
1159 (conn->head->status == MSRPC_CALL_DISPATCHED ||
1160 conn->head->status == MSRPC_CALL_MSGSENDING)) {
1164 switch(call->out.pdu_type) {
1165 case PDU_TYPE_RESPONSE:
1167 BYTE * o_buffer = call->out.buf_data;
1168 unsigned int o_alloc = call->out.buf_alloc;
1169 unsigned int o_pos = call->out.buf_pos;
1170 unsigned int o_len = call->out.buf_length;
1171 unsigned int start_pos = o_pos;
1172 unsigned int fragment_size;
1175 /* If call->out.buf_pos falls on a fragment boundary:
1177 Assume that we are starting a new fragment and deal accordingly.
1181 Assume we are continuing a fragment.
1184 fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
1186 /* Don't send more than the max_recv_frag */
1187 len = min(len, conn->max_recv_frag);
1189 /* Switch the supplied user buffer with the output
1191 call->out.buf_data = buffer;
1192 call->out.buf_length = 0;
1193 call->out.buf_alloc = len;
1194 call->out.buf_pos = 0;
1196 if (o_pos % fragment_size == 0) {
1200 We need to write the packet headers and
1201 fragment bits here. The length of the buffer
1202 should be at least big enough to hold the
1203 entire envelope. We don't handle the case were
1204 the envelope itself is too big.
1208 if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD) {
1209 return CM_ERROR_INVAL;
1212 code = write_E_CommonHeader(&o, conn, call, PDU_TYPE_RESPONSE);
1216 write_u_int32(&o, o_len); /* allocation hint */
1217 write_u_int16(&o, call->context_id); /* presentation context ID */
1218 write_u_int8(&o, 0); /* cancel count */
1219 write_u_int8(&o, 0); /* reserved */
1222 int to_copy = min(SPC_LEFT(&o), o_len - o_pos);
1225 O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1227 /* the fragment size of the message is the minimum of:
1229 - max_recv_frag for the connection
1230 - envelope size + (full message size - start offset)
1233 rc = closeMessage(&o, call,
1234 min(conn->max_recv_frag,
1235 RPC_RESPONSE_ENVELOPE_OVERHEAD + o_len - start_pos));
1241 /* If there is more data to be sent and we are
1242 not at a fragment boundary after the last
1243 send, we return CM_ERROR_RPC_MOREDATA.
1244 Having more fragments to send is not a case
1245 we indicate via a return value. */
1247 if (o_pos < o_len &&
1248 o_pos < start_pos + fragment_size)
1249 code = CM_ERROR_RPC_MOREDATA;
1252 if (start_pos + fragment_size < o_len)
1253 buffer[3] &= ~PFC_LAST_FRAG;
1256 buffer[3] &= ~PFC_FIRST_FRAG;
1262 The packet header should have already been sent
1263 in a previous block.
1266 unsigned int to_copy;
1268 INITC(&o, call->out.buf_data, call->out.buf_alloc);
1270 to_copy = min(fragment_size - (o_pos % fragment_size),
1272 to_copy = min(to_copy, SPC_LEFT(&o));
1274 O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
1278 if (o_pos < o_len && (o_pos % fragment_size) != 0)
1279 code = CM_ERROR_RPC_MOREDATA;
1282 call->out.buf_data = o_buffer;
1283 call->out.buf_alloc = o_alloc;
1284 call->out.buf_pos = o_pos;
1285 call->out.buf_length = o_len;
1287 if (call->out.buf_pos < call->out.buf_length) {
1288 call->status = MSRPC_CALL_MSGSENDING;
1290 call->status = MSRPC_CALL_MSGSENT;
1291 MSRPC_DequeueCall(conn, call);
1292 MSRPC_FreeCall(call);
1297 case PDU_TYPE_BIND_ACK:
1298 case PDU_TYPE_FAULT:
1299 case PDU_TYPE_BIND_NAK:
1301 unsigned int to_send;
1303 /* These types of packets are already fully formed.
1304 We don't need to wrap them in an envelope. They
1305 also don't fragment. */
1307 to_send = call->out.buf_length - call->out.buf_pos;
1310 code = CM_ERROR_RPC_MOREDATA;
1315 memcpy(buffer, call->out.buf_data + call->out.buf_pos, len);
1318 call->out.buf_pos += len;
1320 if (call->out.buf_pos < call->out.buf_length) {
1321 call->status = MSRPC_CALL_MSGSENDING;
1323 call->status = MSRPC_CALL_MSGSENT;
1324 MSRPC_DequeueCall(conn, call);
1325 MSRPC_FreeCall(call);
1331 return CM_ERROR_INVAL;
1337 pthread_once_t msrpc_user_slot_init = PTHREAD_ONCE_INIT;
1339 DWORD msrpc_tls_user_slot = 0;
1342 msrpc_user_slot_init_func(void)
1344 msrpc_tls_user_slot = TlsAlloc();
1348 MSRPC_GetCmUser(void)
1350 pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1352 return (cm_user_t *) TlsGetValue(msrpc_tls_user_slot);
1356 MSRPC_SetCmUser(cm_user_t * userp)
1358 pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
1360 TlsSetValue(msrpc_tls_user_slot, userp);
1363 typedef struct I_RpcAllocatedBuffer {
1364 DWORD magic; /* == _RPCALLOCATEDBUFFER_MAGIC */
1365 #define _RPCALLOCATEDBUFFER_MAGIC 0xa110ca73
1366 struct I_RpcAllocatedBuffer * next;
1368 /* Data goes here */
1369 } I_RpcAllocatedBuffer;
1371 #define I_RPCALLOCATEDBUFFER_FROM_PTR(v) (&(((I_RpcAllocatedBuffer *) (v))[-1]))
1375 I_RpcGetBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1377 I_RpcAllocatedBuffer * newBuffer = I_RpcAllocate(Message->BufferLength + sizeof(I_RpcAllocatedBuffer));
1378 I_RpcAllocatedBuffer * oldBuffer = NULL;
1380 if (Message->Buffer) {
1381 oldBuffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1385 newBuffer->magic = _RPCALLOCATEDBUFFER_MAGIC;
1386 newBuffer->next = oldBuffer;
1388 Message->Buffer = &newBuffer[1];
1390 return ERROR_OUTOFMEMORY;
1398 I_RpcFreeBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
1400 if (Message->Buffer) {
1401 I_RpcAllocatedBuffer * buffer;
1403 buffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
1406 I_RpcAllocatedBuffer * bnext;
1408 bnext = buffer->next;
1415 Message->Buffer = NULL;
1423 NdrServerInitializeNew(
1424 PRPC_MESSAGE pRpcMsg,
1425 PMIDL_STUB_MESSAGE pStubMsg,
1426 PMIDL_STUB_DESC pStubDesc
1429 ZeroMemory(pStubMsg, sizeof(*pStubMsg));
1431 pStubMsg->RpcMsg = pRpcMsg;
1432 pStubMsg->Buffer = pRpcMsg->Buffer;
1433 pStubMsg->BufferStart = pRpcMsg->Buffer;
1434 pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
1435 pStubMsg->BufferLength = pRpcMsg->BufferLength;
1436 pStubMsg->MemorySize = pRpcMsg->BufferLength;
1437 pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
1438 pStubMsg->pfnFree = pStubDesc->pfnFree;
1439 pStubMsg->StubDesc = pStubDesc;
1440 pStubMsg->dwDestContext = MSHCTX_LOCAL;
1451 MSRPC_Shutdown(void) {
1452 RPC_SRVSVC_Shutdown();
1456 MSRPC_IsWellKnownService(const clientchar_t * lastNamep)
1459 cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
1460 cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
1461 cm_ClientStrCmpIA(lastNamep, _C("\\spoolss")) == 0 ||
1462 cm_ClientStrCmpIA(lastNamep, _C("\\winreg")) == 0 ||
1463 cm_ClientStrCmpIA(lastNamep, _C("\\lsass")) == 0 ||
1464 cm_ClientStrCmpIA(lastNamep, _C("\\lsarpc")) == 0 ||
1465 cm_ClientStrCmpIA(lastNamep, _C("\\samr")) == 0 ||
1466 cm_ClientStrCmpIA(lastNamep, _C("\\netlogon")) == 0 ||
1467 cm_ClientStrCmpIA(lastNamep, _C("\\ntsvcs")) == 0 ||
1468 cm_ClientStrCmpIA(lastNamep, _C("\\eventlog")) == 0 ||
1469 cm_ClientStrCmpIA(lastNamep, _C("\\svcctl")) == 0 ||
1470 cm_ClientStrCmpIA(lastNamep, _C("\\browse")) == 0 ||
1471 cm_ClientStrCmpIA(lastNamep, _C("\\msgsvc")) == 0 ||
1472 cm_ClientStrCmpIA(lastNamep, _C("\\w32time")) == 0 ||
1473 cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0;