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
27 #include <afsconfig.h>
28 #include <afs/param.h>
35 #pragma warning(disable: 4005)
48 Meant to set up an endpoing by name, but only checks for a valid name
50 We don't bother trying to locate the endpoint here because the RPC
51 logic already does that using much more specific information than
56 smb_RPC_SetupEndpointByname(smb_rpc_t * rpcp, const clientchar_t * epnamep)
58 const char * secondary_name = NULL;
60 if (!cm_ClientStrCmpI(epnamep, _C("wkssvc"))) {
61 secondary_name = ".\\PIPE\\wkssvc";
62 } else if (!cm_ClientStrCmpI(epnamep, _C("srvsvc"))) {
63 secondary_name = ".\\PIPE\\srvsvc";
65 return CM_ERROR_NOSUCHPATH;
68 return MSRPC_InitConn(&rpcp->rpc_conn, secondary_name);
72 Setup a smb_fid:: structure for RPC
74 \note Obtains fidp->mx */
76 smb_SetupRPCFid(smb_fid_t * fidp, const clientchar_t * _epnamep,
77 unsigned short * file_type,
78 unsigned short * device_state)
82 const clientchar_t * epnamep;
84 epnamep = cm_ClientStrChr(_epnamep, _C('\\'));
88 epnamep = cm_ClientCharNext(epnamep);
90 lock_ObtainMutex(&fidp->mx);
91 fidp->flags |= SMB_FID_RPC;
92 fidp->scp = &cm_data.fakeSCache;
93 cm_HoldSCache(fidp->scp);
94 if (fidp->rpcp == NULL) {
95 rpcp = malloc(sizeof(*rpcp));
96 memset(rpcp, 0, sizeof(*rpcp));
102 code = smb_RPC_SetupEndpointByname(rpcp, epnamep);
103 lock_ReleaseMutex(&fidp->mx);
106 *file_type = SMB_FILETYPE_MESSAGE_MODE_PIPE;
107 *device_state =((0xff) | /* instance count */
108 SMB_DEVICESTATE_READMSGFROMPIPE |
109 SMB_DEVICESTATE_MESSAGEMODEPIPE |
110 SMB_DEVICESTATE_PIPECLIENTEND);
117 Cleanup a smb_fid:: structure that was used for RPC
119 \note Called with fidp->mx locked */
121 smb_CleanupRPCFid(smb_fid_t * fidp)
124 MSRPC_FreeConn(&fidp->rpcp->rpc_conn);
128 smb_RPC_PrepareRead(smb_rpc_t * rpcp)
130 return MSRPC_PrepareRead(&rpcp->rpc_conn);
134 smb_RPC_PrepareWrite(smb_rpc_t * rpcp)
140 smb_RPC_ReadPacketLength(smb_rpc_t * rpcp, afs_uint32 max_length)
142 return MSRPC_ReadMessageLength(&rpcp->rpc_conn, max_length);
146 smb_RPC_ReadPacket(smb_rpc_t * rpcp, BYTE * buffer, afs_uint32 length)
148 osi_Log1(smb_logp, " RPC Read Packet for length %d", length);
149 return MSRPC_ReadMessage(&rpcp->rpc_conn, buffer, length);
153 smb_RPC_WritePacket(smb_rpc_t * rpcp, BYTE * buffer, afs_uint32 length,
156 return MSRPC_WriteMessage(&rpcp->rpc_conn, buffer, length, userp);
159 /*! \brief Begin an RPC operation
161 While generally we receive RPC requests one at a time, we have to
162 protect against receiving multiple requests in parallel since
163 there's nothing really preventing that from happening.
165 This should be called before calling any of the smb_RPC_*()
166 functions. If the return value is non-zero, it should be considered
167 unsafe to call any smb_RPC_*() function.
169 Each successful call to smb_RPC_BeginOp() should be coupled with a
170 call to smb_RPC_EndOp().
172 \note Should be called with rpcp->fidp->mx locked.
175 smb_RPC_BeginOp(smb_rpc_t * rpcp)
178 return CM_ERROR_INVAL;
180 osi_assertx(rpcp->fidp, "No fidp assigned to smb_rpc_t");
181 lock_AssertMutex(&rpcp->fidp->mx);
183 while (rpcp->fidp->flags & SMB_FID_RPC_INCALL) {
184 osi_SleepM((LONG_PTR) rpcp, &rpcp->fidp->mx);
185 lock_ObtainMutex(&rpcp->fidp->mx);
188 rpcp->fidp->flags |= SMB_FID_RPC_INCALL;
192 /*! \brief End an RPC operation
194 \see smb_RPC_BeginOp()
197 smb_RPC_EndOp(smb_rpc_t * rpcp)
199 lock_ObtainMutex(&rpcp->fidp->mx);
200 osi_assertx(rpcp->fidp->flags & SMB_FID_RPC_INCALL, "RPC_EndOp() call without RPC_BeginOp()");
201 rpcp->fidp->flags &= ~SMB_FID_RPC_INCALL;
202 lock_ReleaseMutex(&rpcp->fidp->mx);
204 osi_Wakeup((LONG_PTR) rpcp);
210 Handle a SMB_COM_READ for an RPC fid
212 Called from smb_ReceiveCoreRead when we receive a read on the RPC
215 smb_RPCRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
223 count = smb_GetSMBParm(inp, 1);
224 userp = smb_GetUserFromVCP(vcp, inp);
226 osi_Log3(smb_logp, "smb_RPCRead for user[0x%p] fid[0x%p (%d)]",
227 userp, fidp, fidp->fid);
229 lock_ObtainMutex(&fidp->mx);
231 code = smb_RPC_BeginOp(rpcp);
232 lock_ReleaseMutex(&fidp->mx);
235 cm_ReleaseUser(userp);
240 code = smb_RPC_PrepareRead(rpcp);
243 cm_ReleaseUser(userp);
250 count = smb_RPC_ReadPacketLength(rpcp, count);
252 /* now set the parms for a read of count bytes */
253 smb_SetSMBParm(outp, 0, count);
254 smb_SetSMBParm(outp, 1, 0);
255 smb_SetSMBParm(outp, 2, 0);
256 smb_SetSMBParm(outp, 3, 0);
257 smb_SetSMBParm(outp, 4, 0);
259 smb_SetSMBDataLength(outp, count+3);
261 op = smb_GetSMBData(outp, NULL);
263 *op++ = (char)(count & 0xff);
264 *op++ = (char)((count >> 8) & 0xff);
266 smb_RPC_ReadPacket(rpcp, op, count);
270 cm_ReleaseUser(userp);
276 Handle SMB_COM_WRITE for an RPC fid
278 Called from smb_ReceiveCoreWrite when we receive a write call on
279 the RPC file descriptor.
282 smb_RPCWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
288 int inDataBlockCount;
289 cm_user_t *userp = NULL;
292 count = smb_GetSMBParm(inp, 1);
293 userp = smb_GetUserFromVCP(vcp, inp);
295 osi_Log3(smb_logp, "smb_RPCWrite for user[0x%p] fid[0x%p (%d)]",
296 userp, fidp, fidp->fid);
299 code = CM_ERROR_BADSMB;
303 lock_ObtainMutex(&fidp->mx);
305 code = smb_RPC_BeginOp(rpcp);
306 lock_ReleaseMutex(&fidp->mx);
310 smb_RPC_PrepareWrite(rpcp);
312 op = smb_GetSMBData(inp, NULL);
313 op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
315 code = smb_RPC_WritePacket(rpcp, op, count, userp);
320 /* return # of bytes written */
322 smb_SetSMBParm(outp, 0, count);
323 smb_SetSMBDataLength(outp, 0);
327 cm_ReleaseUser(userp);
333 Handle SMB_COM_WRITE_ANDX for an RPC fid
335 Called from smb_ReceiveV3WriteX when we receive a write call on the
339 smb_RPCV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
345 cm_user_t *userp = NULL;
348 count = smb_GetSMBParm(inp, 10);
349 userp = smb_GetUserFromVCP(vcp, inp);
351 osi_Log3(smb_logp, "smb_RPCV3Write for user[0x%p] fid[0x%p (%d)]",
352 userp, fidp, fidp->fid);
355 code = CM_ERROR_BADSMB;
359 lock_ObtainMutex(&fidp->mx);
361 code = smb_RPC_BeginOp(rpcp);
362 lock_ReleaseMutex(&fidp->mx);
367 smb_RPC_PrepareWrite(rpcp);
369 op = inp->data + smb_GetSMBParm(inp, 11);
371 code = smb_RPC_WritePacket(rpcp, op, count, userp);
376 /* return # of bytes written */
378 smb_SetSMBParm(outp, 2, count);
379 smb_SetSMBParm(outp, 3, 0); /* reserved */
380 smb_SetSMBParm(outp, 4, 0); /* reserved */
381 smb_SetSMBParm(outp, 5, 0); /* reserved */
382 smb_SetSMBDataLength(outp, 0);
386 cm_ReleaseUser(userp);
393 Handle SMB_COM_READ_ANDX for an RPC fid
395 Called from smb_ReceiveV3ReadX to handle RPC descriptor reads */
397 smb_RPCV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
406 count = smb_GetSMBParm(inp, 5);
408 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
410 return CM_ERROR_BADSMB;
411 userp = smb_GetUserFromUID(uidp);
412 osi_assertx(userp != NULL, "null cm_user_t");
414 osi_Log3(smb_logp, "smb_RPCV3Read for user[0x%p] fid[0x%p (%d)]",
415 userp, fidp, fidp->fid);
417 if (uidp && uidp->unp) {
418 osi_Log3(afsd_logp, "RPC uid %d user %x name %S",
420 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
423 osi_Log2(afsd_logp, "RPC uid %d user %x no name",
424 uidp->userID, userp);
426 osi_Log1(afsd_logp, "RPC no uid user %x no name",
430 lock_ObtainMutex(&fidp->mx);
432 code = smb_RPC_BeginOp(rpcp);
433 lock_ReleaseMutex(&fidp->mx);
437 smb_ReleaseUID(uidp);
438 cm_ReleaseUser(userp);
442 code = smb_RPC_PrepareRead(rpcp);
444 smb_ReleaseUID(uidp);
447 cm_ReleaseUser(userp);
452 count = smb_RPC_ReadPacketLength(rpcp, count);
454 /* 0 and 1 are reserved for request chaining, were setup by our caller,
455 * and will be further filled in after we return.
457 smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
458 smb_SetSMBParm(outp, 3, 0); /* resvd */
459 smb_SetSMBParm(outp, 4, 0); /* resvd */
460 smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
461 /* fill in #6 when we have all the parameters' space reserved */
462 smb_SetSMBParm(outp, 7, 0); /* resv'd */
463 smb_SetSMBParm(outp, 8, 0); /* resv'd */
464 smb_SetSMBParm(outp, 9, 0); /* resv'd */
465 smb_SetSMBParm(outp, 10, 0); /* resv'd */
466 smb_SetSMBParm(outp, 11, 0); /* reserved */
468 /* get op ptr after putting in the last parm, since otherwise we don't
469 * know where the data really is.
471 op = smb_GetSMBData(outp, NULL);
473 /* now fill in offset from start of SMB header to first data byte (to op) */
474 smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
476 /* set the packet data length the count of the # of bytes */
477 smb_SetSMBDataLength(outp, count);
479 smb_RPC_ReadPacket(rpcp, op, count);
483 /* and cleanup things */
484 cm_ReleaseUser(userp);
490 smb_RPCNmpipeTransact(smb_fid_t *fidp, smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
492 smb_tran2Packet_t *outp = NULL;
493 struct smb_rpc *rpcp;
495 cm_user_t * userp = NULL;
496 smb_user_t * uidp = NULL;
499 osi_Log0(smb_logp, "smb_RPCNmpipeTransact() begin");
501 uidp = smb_FindUID(vcp, p->uid, 0);
503 return CM_ERROR_BADSMB;
504 userp = smb_GetUserFromUID(uidp);
505 osi_assertx(userp != NULL, "null cm_user_t");
507 if (uidp && uidp->unp) {
508 osi_Log3(afsd_logp, "RPC Transact uid %d user %x name %S",
510 osi_LogSaveClientString(afsd_logp, uidp->unp->name));
513 osi_Log2(afsd_logp, "RPC Transact uid %d user %x no name",
514 uidp->userID, userp);
516 osi_Log1(afsd_logp, "RPC Transact no uid user %x no name",
520 lock_ObtainMutex(&fidp->mx);
522 code = smb_RPC_BeginOp(rpcp);
525 osi_Log0(smb_logp, "Can't begin RPC op. Aborting");
526 lock_ReleaseMutex(&fidp->mx);
528 smb_ReleaseUID(uidp);
529 cm_ReleaseUser(userp);
533 osi_assertx((fidp->flags & SMB_FID_RPC), "FID wasn't setup for RPC");
534 osi_assertx(fidp->rpcp, "smb_rpc_t not associated with RPC FID");
536 lock_ReleaseMutex(&fidp->mx);
538 code = smb_RPC_PrepareWrite(rpcp);
542 code = smb_RPC_WritePacket(rpcp, p->datap, p->totalData, userp);
546 code = smb_RPC_PrepareRead(rpcp);
550 len = smb_RPC_ReadPacketLength(rpcp, p->maxReturnData);
552 outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, len);
554 code = smb_RPC_ReadPacket(rpcp, outp->datap, len);
556 if (code == CM_ERROR_RPC_MOREDATA) {
557 outp->error_code = CM_ERROR_RPC_MOREDATA;
561 if (code == 0 || code == CM_ERROR_RPC_MOREDATA)
562 smb_SendTran2Packet(vcp, outp, op);
563 smb_FreeTran2Packet(outp);
568 osi_Log1(smb_logp, "smb_RPCNmpipeTransact() end code=%d", code);
571 smb_ReleaseUID(uidp);
573 cm_ReleaseUser(userp);