Windows: fs getcalleraccess
[openafs.git] / src / WINNT / afsd / smb_ioctl.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <roken.h>
13
14 #include <afs/stds.h>
15
16 #include <windows.h>
17 #include <sddl.h>
18 #include <stdlib.h>
19 #include <malloc.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <time.h>
23 #include <strsafe.h>
24
25 #include <osi.h>
26
27 #include "afsd.h"
28
29 #include "smb.h"
30
31 #include "cm_rpc.h"
32 #include "afs/afsrpc.h"
33 #include "afs/auth.h"
34
35 smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS];
36
37 void
38 smb_InitIoctl(void)
39 {
40     int i;
41     for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
42         smb_ioctlProcsp[i] = NULL;
43
44     smb_ioctlProcsp[VIOCGETAL] = smb_IoctlGetACL;
45     smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = smb_IoctlGetFileCellName;
46     smb_ioctlProcsp[VIOCSETAL] = smb_IoctlSetACL;
47     smb_ioctlProcsp[VIOC_FLUSHVOLUME] = smb_IoctlFlushVolume;
48     smb_ioctlProcsp[VIOCFLUSH] = smb_IoctlFlushFile;
49     smb_ioctlProcsp[VIOCSETVOLSTAT] = smb_IoctlSetVolumeStatus;
50     smb_ioctlProcsp[VIOCGETVOLSTAT] = smb_IoctlGetVolumeStatus;
51     smb_ioctlProcsp[VIOCWHEREIS] = smb_IoctlWhereIs;
52     smb_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = smb_IoctlStatMountPoint;
53     smb_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = smb_IoctlDeleteMountPoint;
54     smb_ioctlProcsp[VIOCCKSERV] = smb_IoctlCheckServers;
55     smb_ioctlProcsp[VIOC_GAG] = smb_IoctlGag;
56     smb_ioctlProcsp[VIOCCKBACK] = smb_IoctlCheckVolumes;
57     smb_ioctlProcsp[VIOCSETCACHESIZE] = smb_IoctlSetCacheSize;
58     smb_ioctlProcsp[VIOCGETCACHEPARMS] = smb_IoctlGetCacheParms;
59     smb_ioctlProcsp[VIOCGETCELL] = smb_IoctlGetCell;
60     smb_ioctlProcsp[VIOCNEWCELL] = smb_IoctlNewCell;
61     smb_ioctlProcsp[VIOC_GET_WS_CELL] = smb_IoctlGetWsCell;
62     smb_ioctlProcsp[VIOC_AFS_SYSNAME] = smb_IoctlSysName;
63     smb_ioctlProcsp[VIOC_GETCELLSTATUS] = smb_IoctlGetCellStatus;
64     smb_ioctlProcsp[VIOC_SETCELLSTATUS] = smb_IoctlSetCellStatus;
65     smb_ioctlProcsp[VIOC_SETSPREFS] = smb_IoctlSetSPrefs;
66     smb_ioctlProcsp[VIOC_GETSPREFS] = smb_IoctlGetSPrefs;
67     smb_ioctlProcsp[VIOC_STOREBEHIND] = smb_IoctlStoreBehind;
68     smb_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = smb_IoctlCreateMountPoint;
69     smb_ioctlProcsp[VIOC_TRACECTL] = smb_IoctlTraceControl;
70     smb_ioctlProcsp[VIOCSETTOK] = smb_IoctlSetToken;
71     smb_ioctlProcsp[VIOCGETTOK] = smb_IoctlGetTokenIter;
72     smb_ioctlProcsp[VIOCNEWGETTOK] = smb_IoctlGetToken;
73     smb_ioctlProcsp[VIOCDELTOK] = smb_IoctlDelToken;
74     smb_ioctlProcsp[VIOCDELALLTOK] = smb_IoctlDelAllToken;
75     smb_ioctlProcsp[VIOC_SYMLINK] = smb_IoctlSymlink;
76     smb_ioctlProcsp[VIOC_LISTSYMLINK] = smb_IoctlListlink;
77     smb_ioctlProcsp[VIOC_DELSYMLINK] = smb_IoctlDeletelink;
78     smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = smb_IoctlMakeSubmount;
79     smb_ioctlProcsp[VIOC_GETRXKCRYPT] = smb_IoctlGetRxkcrypt;
80     smb_ioctlProcsp[VIOC_SETRXKCRYPT] = smb_IoctlSetRxkcrypt;
81     smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
82     smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = smb_IoctlMemoryDump;
83     smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
84     smb_ioctlProcsp[VIOC_FLUSHALL] = smb_IoctlFlushAllVolumes;
85     smb_ioctlProcsp[VIOCGETFID] = smb_IoctlGetFid;
86     smb_ioctlProcsp[VIOCGETOWNER] = smb_IoctlGetOwner;
87     smb_ioctlProcsp[VIOC_RXSTAT_PROC] = smb_IoctlRxStatProcess;
88     smb_ioctlProcsp[VIOC_RXSTAT_PEER] = smb_IoctlRxStatPeer;
89     smb_ioctlProcsp[VIOC_UUIDCTL] = smb_IoctlUUIDControl;
90     smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = smb_IoctlPathAvailability;
91     smb_ioctlProcsp[VIOC_GETFILETYPE] = smb_IoctlGetFileType;
92     smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = smb_IoctlVolStatTest;
93     smb_ioctlProcsp[VIOC_UNICODECTL] = smb_IoctlUnicodeControl;
94     smb_ioctlProcsp[VIOC_SETOWNER] = smb_IoctlSetOwner;
95     smb_ioctlProcsp[VIOC_SETGROUP] = smb_IoctlSetGroup;
96     smb_ioctlProcsp[VIOCNEWCELL2] = smb_IoctlNewCell2;
97     smb_ioctlProcsp[VIOC_SETUNIXMODE] = smb_IoctlSetUnixMode;
98     smb_ioctlProcsp[VIOC_GETUNIXMODE] = smb_IoctlGetUnixMode;
99     smb_ioctlProcsp[VIOC_SETVERIFYDATA] = smb_IoctlSetVerifyData;
100     smb_ioctlProcsp[VIOC_GETVERIFYDATA] = smb_IoctlGetVerifyData;
101     smb_ioctlProcsp[VIOC_GETCALLERACCESS] = smb_IoctlGetCallerAccess;
102 }
103
104 /* called to make a fid structure into an IOCTL fid structure */
105 void
106 smb_SetupIoctlFid(smb_fid_t *fidp, cm_space_t *prefix)
107 {
108     smb_ioctl_t *iop;
109     cm_space_t *copyPrefix;
110
111     lock_ObtainMutex(&fidp->mx);
112     fidp->flags |= SMB_FID_IOCTL;
113     fidp->scp = &cm_data.fakeSCache;
114     cm_HoldSCache(fidp->scp);
115     if (fidp->ioctlp == NULL) {
116         iop = malloc(sizeof(*iop));
117         memset(iop, 0, sizeof(*iop));
118         fidp->ioctlp = iop;
119         iop->fidp = fidp;
120     }
121     if (prefix) {
122         copyPrefix = cm_GetSpace();
123         memcpy(copyPrefix->data, prefix->data, CM_UTILS_SPACESIZE);
124         fidp->ioctlp->prefix = copyPrefix;
125     }
126     lock_ReleaseMutex(&fidp->mx);
127 }
128
129 /* called when we receive a read call, does the send of the received data if
130  * this is the first read call.  This is the function that actually makes the
131  * call to the ioctl code.
132  */
133 afs_int32
134 smb_IoctlPrepareRead(struct smb_fid *fidp, smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
135 {
136     afs_int32 opcode;
137     smb_ioctlProc_t *procp = NULL;
138     afs_int32 code;
139
140     if (ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN) {
141         ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAIN;
142         ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAOUT;
143
144         /* do the call now, or fail if we didn't get an opcode, or
145          * enough of an opcode.
146          */
147         if (ioctlp->ioctl.inCopied < sizeof(afs_int32))
148             return CM_ERROR_INVAL;
149         memcpy(&opcode, ioctlp->ioctl.inDatap, sizeof(afs_int32));
150         ioctlp->ioctl.inDatap += sizeof(afs_int32);
151
152         osi_Log1(afsd_logp, "smb_IoctlPrepareRead opcode 0x%x", opcode);
153         /* check for opcode out of bounds */
154         if (opcode < 0 || opcode >= SMB_IOCTL_MAXPROCS) {
155             osi_Log0(afsd_logp, "smb_IoctlPrepareRead - invalid opcode");
156             return CM_ERROR_TOOBIG;
157         }
158
159         /* check for no such proc */
160         procp = smb_ioctlProcsp[opcode];
161         if (procp == NULL) {
162             osi_Log0(afsd_logp, "smb_IoctlPrepareRead - unassigned opcode");
163             return CM_ERROR_INVAL;
164         }
165         /* otherwise, make the call */
166         ioctlp->ioctl.outDatap += sizeof(afs_int32); /* reserve room for return code */
167         code = (*procp)(ioctlp, userp, pflags);
168         osi_Log1(afsd_logp, "smb_IoctlPrepareRead operation returns code 0x%x", code);
169
170         /* copy in return code */
171         memcpy(ioctlp->ioctl.outAllocp, &code, sizeof(afs_int32));
172     } else if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAOUT)) {
173         osi_Log0(afsd_logp, "Ioctl invalid state - dataout expected");
174         return CM_ERROR_INVAL;
175     }
176
177     return 0;
178 }
179
180 /* called when we receive a write call.  If this is the first write call after
181  * a series of reads (or the very first call), then we start a new call.
182  * We also ensure that things are properly initialized for the start of a call.
183  */
184 void
185 smb_IoctlPrepareWrite(smb_fid_t *fidp, smb_ioctl_t *ioctlp)
186 {
187     /* make sure the buffer(s) are allocated */
188     if (!ioctlp->ioctl.inAllocp)
189         ioctlp->ioctl.inAllocp = malloc(SMB_IOCTL_MAXDATA);
190     if (!ioctlp->ioctl.outAllocp)
191         ioctlp->ioctl.outAllocp = malloc(SMB_IOCTL_MAXDATA);
192
193     /* Fixes fs la problem.  We do a StrToOEM later and if this data isn't initialized we get memory issues. */
194     (void) memset(ioctlp->ioctl.inAllocp, 0, SMB_IOCTL_MAXDATA);
195     (void) memset(ioctlp->ioctl.outAllocp, 0, SMB_IOCTL_MAXDATA);
196
197     /* and make sure that we've reset our state for the new incoming request */
198     if (!(ioctlp->ioctl.flags & CM_IOCTLFLAG_DATAIN)) {
199         ioctlp->ioctl.inCopied = 0;
200         ioctlp->ioctl.outCopied = 0;
201         ioctlp->ioctl.inDatap = ioctlp->ioctl.inAllocp;
202         ioctlp->ioctl.outDatap = ioctlp->ioctl.outAllocp;
203         ioctlp->ioctl.flags |= CM_IOCTLFLAG_DATAIN;
204         ioctlp->ioctl.flags &= ~CM_IOCTLFLAG_DATAOUT;
205     }
206 }
207
208 /* called from smb_ReceiveCoreRead when we receive a read on the ioctl fid */
209 afs_int32
210 smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
211 {
212     smb_ioctl_t *iop;
213     long count;
214     afs_int32 leftToCopy;
215     char *op;
216     afs_int32 code;
217     smb_user_t *uidp;
218     cm_user_t *userp = NULL;
219     smb_t *smbp;
220     int isSystem = 0;
221
222     iop = fidp->ioctlp;
223     count = smb_GetSMBParm(inp, 1);
224
225     /* Get the user and determine if it is the local machine account */
226     smbp = (smb_t *) inp;
227     uidp = smb_FindUID(vcp, smbp->uid, 0);
228     if (uidp) {
229         if (uidp->unp) {
230             osi_Log3(afsd_logp, "Ioctl uid %d user %x name %s",
231                       uidp->userID, userp,
232                       osi_LogSaveClientString(afsd_logp, uidp->unp->name));
233         } else {
234             osi_Log2(afsd_logp, "Ioctl uid %d user %x no name",
235                       uidp->userID, userp);
236         }
237         isSystem = smb_userIsLocalSystem(uidp);
238         userp = smb_GetUserFromUID(uidp);
239         if (uidp->unp) {
240             osi_Log3(afsd_logp, "smb_IoctlRead uid %d user %x name %s",
241                       uidp->userID, userp,
242                       osi_LogSaveClientString(afsd_logp, uidp->unp->name));
243         } else {
244             osi_Log2(afsd_logp, "smb_IoctlRead uid %d user %x no name",
245                       uidp->userID, userp);
246         }
247         smb_ReleaseUID(uidp);
248     } else {
249         osi_Log1(afsd_logp, "smb_IoctlRead no uid user %x no name", userp);
250         return CM_ERROR_BADSMB;
251     }
252
253     if (!userp) {
254         userp = cm_rootUserp;
255         cm_HoldUser(userp);
256     }
257
258     /* Identify tree */
259     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
260     if (code) {
261         cm_ReleaseUser(userp);
262         return CM_ERROR_NOSUCHPATH;
263     }
264
265     /* turn the connection around, if required */
266     code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
267
268     if (code) {
269         cm_ReleaseUser(userp);
270         return code;
271     }
272
273     leftToCopy = (afs_int32)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
274     if (leftToCopy < 0) {
275         osi_Log0(afsd_logp, "smb_IoctlRead leftToCopy went negative");
276         cm_ReleaseUser(userp);
277         return CM_ERROR_INVAL;
278     }
279     if (count > leftToCopy)
280         count = leftToCopy;
281
282     /* now set the parms for a read of count bytes */
283     smb_SetSMBParm(outp, 0, count);
284     smb_SetSMBParm(outp, 1, 0);
285     smb_SetSMBParm(outp, 2, 0);
286     smb_SetSMBParm(outp, 3, 0);
287     smb_SetSMBParm(outp, 4, 0);
288
289     smb_SetSMBDataLength(outp, count+3);
290
291     op = smb_GetSMBData(outp, NULL);
292     *op++ = 1;
293     *op++ = (char)(count & 0xff);
294     *op++ = (char)((count >> 8) & 0xff);
295
296     /* now copy the data into the response packet */
297     memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
298
299     /* and adjust the counters */
300     iop->ioctl.outCopied += count;
301
302     cm_ReleaseUser(userp);
303
304     return 0;
305 }
306
307 /* called from smb_ReceiveCoreWrite when we receive a write call on the IOCTL
308  * file descriptor.
309  */
310 afs_int32
311 smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
312 {
313     smb_ioctl_t *iop;
314     long count;
315     afs_int32 code;
316     char *op;
317     int inDataBlockCount;
318
319     code = 0;
320     count = smb_GetSMBParm(inp, 1);
321     iop = fidp->ioctlp;
322
323     smb_IoctlPrepareWrite(fidp, iop);
324
325     op = smb_GetSMBData(inp, NULL);
326     op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
327
328     if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
329         code = CM_ERROR_TOOBIG;
330         goto done;
331     }
332
333     /* copy data */
334     memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
335
336     /* adjust counts */
337     iop->ioctl.inCopied += count;
338
339   done:
340     /* return # of bytes written */
341     if (code == 0) {
342         smb_SetSMBParm(outp, 0, count);
343         smb_SetSMBDataLength(outp, 0);
344     }
345
346     return code;
347 }
348
349 /* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL
350  * file descriptor.
351  */
352 afs_int32
353 smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
354 {
355     smb_ioctl_t *iop;
356     long count;
357     afs_int32 code;
358     char *op;
359     int inDataBlockCount;
360
361     code = 0;
362     count = smb_GetSMBParm(inp, 10);
363     iop = fidp->ioctlp;
364
365     smb_IoctlPrepareWrite(fidp, iop);
366
367     op = inp->data + smb_GetSMBParm(inp, 11);
368     inDataBlockCount = count;
369
370     if (count + iop->ioctl.inCopied > SMB_IOCTL_MAXDATA) {
371         code = CM_ERROR_TOOBIG;
372         goto done;
373     }
374
375     /* copy data */
376     memcpy(iop->ioctl.inDatap + iop->ioctl.inCopied, op, count);
377
378     /* adjust counts */
379     iop->ioctl.inCopied += count;
380
381   done:
382     /* return # of bytes written */
383     if (code == 0) {
384         smb_SetSMBParm(outp, 2, count);
385         smb_SetSMBParm(outp, 3, 0); /* reserved */
386         smb_SetSMBParm(outp, 4, 0); /* reserved */
387         smb_SetSMBParm(outp, 5, 0); /* reserved */
388         smb_SetSMBDataLength(outp, 0);
389     }
390
391     return code;
392 }
393
394
395 /* called from V3 read to handle IOCTL descriptor reads */
396 afs_int32
397 smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
398 {
399     smb_ioctl_t *iop;
400     unsigned short count;
401     afs_int32 code;
402     long leftToCopy;
403     char *op;
404     cm_user_t *userp;
405     smb_user_t *uidp;
406     int isSystem = 0;
407
408     iop = fidp->ioctlp;
409     count = smb_GetSMBParm(inp, 5);
410
411     /* Get the user and determine if it is the local machine account */
412     uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
413     if (uidp) {
414         isSystem = smb_userIsLocalSystem(uidp);
415         userp = smb_GetUserFromUID(uidp);
416         if (uidp->unp) {
417             osi_Log3(afsd_logp, "smb_IoctlV3Read uid %d user %x name %s",
418                       uidp->userID, userp,
419                       osi_LogSaveClientString(afsd_logp, uidp->unp->name));
420         } else {
421             osi_Log2(afsd_logp, "smb_IoctlV3Read uid %d user %x no name",
422                       uidp->userID, userp);
423         }
424      } else {
425          osi_Log0(afsd_logp, "smb_IoctlV3Read no uid");
426          return CM_ERROR_BADSMB;
427      }
428
429     if (!userp) {
430         userp = cm_rootUserp;
431         cm_HoldUser(userp);
432     }
433
434     iop->uidp = uidp;
435
436     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
437     if (code) {
438         if (uidp)
439             smb_ReleaseUID(uidp);
440         cm_ReleaseUser(userp);
441         return CM_ERROR_NOSUCHPATH;
442     }
443
444     code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
445     if (uidp) {
446         iop->uidp = 0;
447         smb_ReleaseUID(uidp);
448     }
449     if (code) {
450         cm_ReleaseUser(userp);
451         return code;
452     }
453
454     leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
455     if (leftToCopy < 0) {
456         osi_Log0(afsd_logp, "smb_IoctlV3Read leftToCopy went negative");
457         cm_ReleaseUser(userp);
458         return CM_ERROR_INVAL;
459     }
460     if (count > leftToCopy)
461         count = (unsigned short)leftToCopy;
462
463     /* 0 and 1 are reserved for request chaining, were setup by our caller,
464      * and will be further filled in after we return.
465      */
466     smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
467     smb_SetSMBParm(outp, 3, 0); /* resvd */
468     smb_SetSMBParm(outp, 4, 0); /* resvd */
469     smb_SetSMBParm(outp, 5, count);     /* # of bytes we're going to read */
470     /* fill in #6 when we have all the parameters' space reserved */
471     smb_SetSMBParm(outp, 7, 0); /* resv'd */
472     smb_SetSMBParm(outp, 8, 0); /* resv'd */
473     smb_SetSMBParm(outp, 9, 0); /* resv'd */
474     smb_SetSMBParm(outp, 10, 0);        /* resv'd */
475     smb_SetSMBParm(outp, 11, 0);        /* reserved */
476
477     /* get op ptr after putting in the last parm, since otherwise we don't
478      * know where the data really is.
479      */
480     op = smb_GetSMBData(outp, NULL);
481
482     /* now fill in offset from start of SMB header to first data byte (to op) */
483     smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
484
485     /* set the packet data length the count of the # of bytes */
486     smb_SetSMBDataLength(outp, count);
487
488     /* now copy the data into the response packet */
489     memcpy(op, iop->ioctl.outCopied + iop->ioctl.outAllocp, count);
490
491     /* and adjust the counters */
492     iop->ioctl.outCopied += count;
493
494     /* and cleanup things */
495     cm_ReleaseUser(userp);
496
497     return 0;
498 }
499
500 /* called from Read Raw to handle IOCTL descriptor reads */
501 afs_int32
502 smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp,
503                  smb_packet_t *outp)
504 {
505     smb_ioctl_t *iop;
506     long leftToCopy;
507     NCB *ncbp;
508     afs_int32 code;
509     cm_user_t *userp;
510     smb_user_t *uidp;
511     int isSystem = 0;
512
513     iop = fidp->ioctlp;
514
515     /* Get the user and determine if it is the local machine account */
516     uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
517     if (uidp) {
518         isSystem = smb_userIsLocalSystem(uidp);
519         userp = smb_GetUserFromUID(uidp);
520         if (uidp->unp) {
521             osi_Log3(afsd_logp, "smb_IoctlRawRead uid %d user %x name %s",
522                       uidp->userID, userp,
523                       osi_LogSaveClientString(afsd_logp, uidp->unp->name));
524         } else {
525             osi_Log2(afsd_logp, "smb_IoctlRawRead uid %d user %x no name",
526                       uidp->userID, userp);
527         }
528         smb_ReleaseUID(uidp);
529     } else {
530         osi_Log0(afsd_logp, "smb_IoctlRawRead no uid");
531     }
532
533     if (!userp) {
534         userp = cm_rootUserp;
535         cm_HoldUser(userp);
536     }
537
538     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
539     if (code) {
540         code = CM_ERROR_NOSUCHPATH;
541         goto done;
542     }
543
544     code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
545     if (code) {
546         goto done;
547     }
548
549     leftToCopy = (long)((iop->ioctl.outDatap - iop->ioctl.outAllocp) - iop->ioctl.outCopied);
550     if (leftToCopy < 0) {
551         osi_Log0(afsd_logp, "smb_IoctlReadRaw leftToCopy went negative");
552         code = CM_ERROR_INVAL;
553         goto done;
554     }
555
556     ncbp = outp->ncbp;
557     memset(ncbp, 0, sizeof(NCB));
558
559     ncbp->ncb_length = (unsigned short) leftToCopy;
560     ncbp->ncb_lsn = (unsigned char) vcp->lsn;
561     ncbp->ncb_command = NCBSEND;
562     /*ncbp->ncb_lana_num = smb_LANadapter;*/
563     ncbp->ncb_lana_num = vcp->lana;
564
565     ncbp->ncb_buffer = iop->ioctl.outCopied + iop->ioctl.outAllocp;
566     code = Netbios(ncbp);
567
568     if (code != 0)
569         osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
570
571   done:
572     cm_ReleaseUser(userp);
573
574     return code;
575 }
576
577 /* parse the passed-in file name and do a namei on it.  If we fail,
578  * return an error code, otherwise return the vnode located in *scpp.
579  */
580 #define CM_PARSE_FLAG_LITERAL 1
581
582 afs_int32
583 smb_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
584                    cm_scache_t **scpp, afs_uint32 flags)
585 {
586     long code;
587     cm_scache_t  *substRootp = NULL;
588     cm_scache_t  *iscp = NULL;
589     char      *inPath;
590     clientchar_t *relativePath = NULL;
591     clientchar_t *lastComponent = NULL;
592     afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW);
593
594     inPath = ioctlp->ioctl.inDatap;
595     /* setup the next data value for the caller to use */
596     ioctlp->ioctl.inDatap += (long)strlen(ioctlp->ioctl.inDatap) + 1;
597
598     osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,inPath));
599
600     /* This is usually the file name, but for StatMountPoint it is the path. */
601     /* ioctlp->ioctl.inDatap can be either of the form:
602      *    \path\.
603      *    \path\file
604      *    \\netbios-name\submount\path\.
605      *    \\netbios-name\submount\path\file
606      */
607
608     /* We do not perform path name translation on the ioctl path data
609      * because these paths were not translated by Windows through the
610      * file system API.  Therefore, they are not OEM characters but
611      * whatever the display character set is.
612      */
613
614     // TranslateExtendedChars(relativePath);
615
616     /* This is usually nothing, but for StatMountPoint it is the file name. */
617     // TranslateExtendedChars(ioctlp->ioctl.inDatap);
618
619     /* If the string starts with our UTF-8 prefix (which is the
620        sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
621        strings), we assume that the provided path is UTF-8.  Otherwise
622        we have to convert the string to UTF-8, since that is what we
623        want to use everywhere else.*/
624
625     if (memcmp(inPath, utf8_prefix, utf8_prefix_size) == 0) {
626         /* String is UTF-8 */
627         inPath += utf8_prefix_size;
628         ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
629
630         relativePath = cm_Utf8ToClientStringAlloc(inPath, -1, NULL);
631     } else {
632         int cch;
633
634         /* Not a UTF-8 string */
635         /* TODO: If this is an OEM string, we should convert it to
636            UTF-8. */
637         if (smb_StoreAnsiFilenames) {
638             cch = cm_AnsiToClientString(inPath, -1, NULL, 0);
639 #ifdef DEBUG
640             osi_assert(cch > 0);
641 #endif
642             relativePath = malloc(cch * sizeof(clientchar_t));
643             cm_AnsiToClientString(inPath, -1, relativePath, cch);
644         } else {
645             TranslateExtendedChars(inPath);
646
647             cch = cm_OemToClientString(inPath, -1, NULL, 0);
648 #ifdef DEBUG
649             osi_assert(cch > 0);
650 #endif
651             relativePath = malloc(cch * sizeof(clientchar_t));
652             cm_OemToClientString(inPath, -1, relativePath, cch);
653         }
654     }
655
656     if (relativePath[0] == relativePath[1] &&
657         relativePath[1] == '\\' &&
658         !cm_ClientStrCmpNI(cm_NetbiosNameC, relativePath+2,
659                            (int)cm_ClientStrLen(cm_NetbiosNameC)))
660     {
661         clientchar_t shareName[256];
662         clientchar_t *sharePath;
663         int shareFound, i;
664
665         /* We may have found a UNC path.
666          * If the first component is the NetbiosName,
667          * then throw out the second component (the submount)
668          * since it had better expand into the value of ioctl->tidPathp
669          */
670         clientchar_t * p;
671         p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;                    /* buffer overflow vuln.? */
672         if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
673             p += 4;
674
675         for (i = 0; *p && *p != '\\'; i++,p++ ) {
676             shareName[i] = *p;
677         }
678         p++;                    /* skip past trailing slash */
679         shareName[i] = 0;       /* terminate string */
680
681         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
682         if ( shareFound ) {
683             /* we found a sharename, therefore use the resulting path */
684             code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
685                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
686                             userp, sharePath, reqp, &substRootp);
687             free(sharePath);
688             if (code) {
689                 osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code);
690                 if (relativePath)
691                     free(relativePath);
692                 return code;
693             }
694
695             lastComponent = cm_ClientStrRChr(p,  '\\');
696             if (lastComponent && (lastComponent - p) > 1 &&
697                 cm_ClientStrLen(lastComponent) > 1) {
698                 *lastComponent = '\0';
699                 lastComponent++;
700
701                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
702                                 userp, NULL, reqp, &iscp);
703                 if (code == 0)
704                     code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
705                                     userp, NULL, reqp, scpp);
706                 if (iscp)
707                     cm_ReleaseSCache(iscp);
708             } else {
709                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
710                                 userp, NULL, reqp, scpp);
711             }
712             cm_ReleaseSCache(substRootp);
713             if (code) {
714                 osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code);
715                 if (relativePath)
716                     free(relativePath);
717                 return code;
718             }
719         } else {
720             /* otherwise, treat the name as a cellname mounted off the afs root.
721              * This requires that we reconstruct the shareName string with
722              * leading and trailing slashes.
723              */
724             p = relativePath + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
725             if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
726                 p += 4;
727
728             shareName[0] = '/';
729             for (i = 1; *p && *p != '\\'; i++,p++ ) {
730                 shareName[i] = *p;
731             }
732             p++;                    /* skip past trailing slash */
733             shareName[i++] = '/';       /* add trailing slash */
734             shareName[i] = 0;       /* terminate string */
735
736
737             code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
738                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
739                             userp, shareName, reqp, &substRootp);
740             if (code) {
741                 osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code);
742                 if (relativePath)
743                     free(relativePath);
744                 return code;
745             }
746
747             lastComponent = cm_ClientStrRChr(p,  '\\');
748             if (lastComponent && (lastComponent - p) > 1 &&
749                 cm_ClientStrLen(lastComponent) > 1) {
750                 *lastComponent = '\0';
751                 lastComponent++;
752
753                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
754                                 userp, NULL, reqp, &iscp);
755                 if (code == 0)
756                     code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
757                                     userp, NULL, reqp, scpp);
758                 if (iscp)
759                     cm_ReleaseSCache(iscp);
760             } else {
761                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
762                                 userp, NULL, reqp, scpp);
763             }
764
765             if (code) {
766                 cm_ReleaseSCache(substRootp);
767                 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
768                 if (relativePath)
769                     free(relativePath);
770                 return code;
771             }
772         }
773     } else {
774         code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
775                          CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
776                          userp, ioctlp->tidPathp, reqp, &substRootp);
777         if (code) {
778             osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
779             if (relativePath)
780                 free(relativePath);
781             return code;
782         }
783
784         lastComponent = cm_ClientStrRChr(relativePath,  '\\');
785         if (lastComponent && (lastComponent - relativePath) > 1 &&
786             cm_ClientStrLen(lastComponent) > 1) {
787             *lastComponent = '\0';
788             lastComponent++;
789
790             code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
791                             userp, NULL, reqp, &iscp);
792             if (code == 0)
793                 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
794                                 userp, NULL, reqp, scpp);
795             if (iscp)
796                 cm_ReleaseSCache(iscp);
797         } else {
798             code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
799                             userp, NULL, reqp, scpp);
800         }
801         if (code) {
802             cm_ReleaseSCache(substRootp);
803             osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
804             if (relativePath)
805                 free(relativePath);
806             return code;
807         }
808     }
809
810     if (substRootp)
811         cm_ReleaseSCache(substRootp);
812
813     if (relativePath)
814         free(relativePath);
815
816     /* Ensure that the status object is up to date */
817     lock_ObtainWrite(&(*scpp)->rw);
818     code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
819                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
820     if (code == 0)
821         cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
822     lock_ReleaseWrite(&(*scpp)->rw);
823
824     /* and return success */
825     osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
826     return 0;
827 }
828
829
830
831 #define LEAF_SIZE 256
832 /* parse the passed-in file name and do a namei on its parent.  If we fail,
833  * return an error code, otherwise return the vnode located in *scpp.
834  */
835 afs_int32
836 smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
837                      cm_scache_t **scpp, clientchar_t *leafp)
838 {
839     long code;
840     clientchar_t tbuffer[1024];
841     clientchar_t *tp, *jp;
842     cm_scache_t *substRootp = NULL;
843     clientchar_t *inpathp = NULL;
844     char *inpathdatap;
845
846     inpathdatap = ioctlp->ioctl.inDatap;
847
848     /* If the string starts with our UTF-8 prefix (which is the
849        sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
850        strings), we assume that the provided path is UTF-8.  Otherwise
851        we have to convert the string to UTF-8, since that is what we
852        want to use everywhere else.*/
853
854     if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
855
856         /* String is UTF-8 */
857         inpathdatap += utf8_prefix_size;
858         ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
859
860         inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
861     } else {
862         int cch;
863
864         /* Not a UTF-8 string */
865         /* TODO: If this is an OEM string, we should convert it to
866            UTF-8. */
867         if (smb_StoreAnsiFilenames) {
868             cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
869 #ifdef DEBUG
870             osi_assert(cch > 0);
871 #endif
872             inpathp = malloc(cch * sizeof(clientchar_t));
873             cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
874         } else {
875             TranslateExtendedChars(inpathdatap);
876
877             cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
878 #ifdef DEBUG
879             osi_assert(cch > 0);
880 #endif
881             inpathp = malloc(cch * sizeof(clientchar_t));
882             cm_OemToClientString(inpathdatap, -1, inpathp, cch);
883         }
884     }
885
886     cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
887     tp = cm_ClientStrRChr(tbuffer, '\\');
888     jp = cm_ClientStrRChr(tbuffer, '/');
889     if (!tp)
890         tp = jp;
891     else if (jp && (tp - tbuffer) < (jp - tbuffer))
892         tp = jp;
893     if (!tp) {
894         cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
895         if (leafp)
896             cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
897     }
898     else {
899         *tp = 0;
900         if (leafp)
901             cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
902     }
903
904     free(inpathp);
905     inpathp = NULL;             /* We don't need this from this point on */
906
907     if (tbuffer[0] == tbuffer[1] &&
908         tbuffer[1] == '\\' &&
909         !cm_ClientStrCmpNI(cm_NetbiosNameC, tbuffer+2,
910                            (int)cm_ClientStrLen(cm_NetbiosNameC)))
911     {
912         clientchar_t shareName[256];
913         clientchar_t *sharePath;
914         int shareFound, i;
915
916         /* We may have found a UNC path.
917          * If the first component is the NetbiosName,
918          * then throw out the second component (the submount)
919          * since it had better expand into the value of ioctl->tidPathp
920          */
921         clientchar_t * p;
922         p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
923         if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
924             p += 4;
925
926         for (i = 0; *p && *p != '\\'; i++,p++ ) {
927             shareName[i] = *p;
928         }
929         p++;                    /* skip past trailing slash */
930         shareName[i] = 0;       /* terminate string */
931
932         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
933         if ( shareFound ) {
934             /* we found a sharename, therefore use the resulting path */
935             code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
936                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
937                             userp, sharePath, reqp, &substRootp);
938             free(sharePath);
939             if (code) return code;
940
941             code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
942                             userp, NULL, reqp, scpp);
943             cm_ReleaseSCache(substRootp);
944             if (code) return code;
945         } else {
946             /* otherwise, treat the name as a cellname mounted off the afs root.
947              * This requires that we reconstruct the shareName string with
948              * leading and trailing slashes.
949              */
950             p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
951             if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
952                 p += 4;
953
954             shareName[0] = '/';
955             for (i = 1; *p && *p != '\\'; i++,p++ ) {
956                 shareName[i] = *p;
957             }
958             p++;                    /* skip past trailing slash */
959             shareName[i++] = '/';       /* add trailing slash */
960             shareName[i] = 0;       /* terminate string */
961
962             code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
963                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
964                             userp, shareName, reqp, &substRootp);
965             if (code) return code;
966
967             code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
968                             userp, NULL, reqp, scpp);
969             cm_ReleaseSCache(substRootp);
970             if (code) return code;
971         }
972     } else {
973         code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
974                         CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
975                         userp, ioctlp->tidPathp, reqp, &substRootp);
976         if (code) return code;
977
978         code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
979                         userp, NULL, reqp, scpp);
980         cm_ReleaseSCache(substRootp);
981         if (code) return code;
982     }
983
984     /* # of bytes of path */
985     code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
986     ioctlp->ioctl.inDatap += code;
987
988     /* Ensure that the status object is up to date */
989     lock_ObtainWrite(&(*scpp)->rw);
990     code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
991                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
992     if (code == 0)
993         cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
994     lock_ReleaseWrite(&(*scpp)->rw);
995
996     /* and return success */
997     return 0;
998 }
999
1000 afs_int32
1001 smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1002 {
1003     char *saveDataPtr;
1004     char *tp;
1005     int ticketLen;
1006     char *ticket;
1007     int ctSize;
1008     struct ClearToken ct;
1009     cm_cell_t *cellp;
1010     cm_ucell_t *ucellp;
1011     afs_uuid_t uuid;
1012     int flags;
1013     char sessionKey[8];
1014     int release_userp = 0;
1015     clientchar_t *uname = NULL;
1016     clientchar_t *smbname = NULL;
1017     clientchar_t *wdir = NULL;
1018     clientchar_t *rpc_sid = NULL;
1019     afs_int32 code = 0;
1020
1021     saveDataPtr = ioctlp->ioctl.inDatap;
1022
1023     cm_SkipIoctlPath(&ioctlp->ioctl);
1024
1025     tp = ioctlp->ioctl.inDatap;
1026
1027     /* ticket length */
1028     memcpy(&ticketLen, tp, sizeof(ticketLen));
1029     tp += sizeof(ticketLen);
1030     if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
1031         return CM_ERROR_INVAL;
1032
1033     /* remember ticket and skip over it for now */
1034     ticket = tp;
1035     tp += ticketLen;
1036
1037     /* clear token size */
1038     memcpy(&ctSize, tp, sizeof(ctSize));
1039     tp += sizeof(ctSize);
1040     if (ctSize != sizeof(struct ClearToken))
1041         return CM_ERROR_INVAL;
1042
1043     /* clear token */
1044     memcpy(&ct, tp, ctSize);
1045     tp += ctSize;
1046     if (ct.AuthHandle == -1)
1047         ct.AuthHandle = 999;    /* more rxvab compat stuff */
1048
1049     /* more stuff, if any */
1050     if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
1051         /* flags:  logon flag */
1052         memcpy(&flags, tp, sizeof(int));
1053         tp += sizeof(int);
1054
1055         /* cell name */
1056         {
1057             fschar_t * cellnamep;
1058             clientchar_t * temp;
1059
1060             temp = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1061             cellnamep = cm_ClientStringToFsStringAlloc(temp, -1, NULL);
1062             cellp = cm_GetCell(cellnamep, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
1063             free(cellnamep);
1064             free(temp);
1065         }
1066
1067         if (!cellp) {
1068             code = CM_ERROR_NOSUCHCELL;
1069             goto done;
1070         }
1071         tp += strlen(tp) + 1;
1072
1073         /* user name */
1074         uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1075         tp += strlen(tp) + 1;
1076
1077         if (flags & PIOCTL_LOGON) {
1078             /* SMB user name with which to associate tokens */
1079             smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1080             osi_Log2(smb_logp,"smb_IoctlSetToken for user [%S] smbname [%S]",
1081                      osi_LogSaveClientString(smb_logp,uname),
1082                      osi_LogSaveClientString(smb_logp,smbname));
1083             fprintf(stderr, "SMB name = %S\n", smbname);
1084             tp += strlen(tp) + 1;
1085         } else {
1086             osi_Log1(smb_logp,"smb_IoctlSetToken for user [%S]",
1087                      osi_LogSaveClientString(smb_logp, uname));
1088         }
1089
1090         /* uuid */
1091         memcpy(&uuid, tp, sizeof(uuid));
1092         if (!cm_FindTokenEvent(uuid, sessionKey, &rpc_sid)) {
1093             code = CM_ERROR_INVAL;
1094             goto done;
1095         }
1096
1097         if (rpc_sid) {
1098             if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM)) {
1099                 osi_Log1(smb_logp,"smb_IoctlSetToken Rpc Sid [%S]",
1100                          osi_LogSaveClientString(smb_logp, rpc_sid));
1101                 if (!cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, rpc_sid))
1102                     pflags |= AFSCALL_FLAG_LOCAL_SYSTEM;
1103             }
1104             LocalFree(rpc_sid);
1105         }
1106
1107         if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1108             code = CM_ERROR_NOACCESS;
1109             goto done;
1110         }
1111     } else {
1112         cellp = cm_data.rootCellp;
1113         osi_Log0(smb_logp,"smb_IoctlSetToken - no name specified");
1114     }
1115
1116     if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1117         PSID pSid = NULL;
1118         DWORD dwSize1 = 0, dwSize2 = 0;
1119         wchar_t *pszRefDomain = NULL;
1120         SID_NAME_USE snu = SidTypeGroup;
1121         clientchar_t * secSidString = NULL;
1122         DWORD gle;
1123
1124         /*
1125          * The specified smbname is may not be a SID for the user.
1126          * See if we can obtain the SID for the specified name.
1127          * If we can, use that instead of the name provided.
1128          */
1129
1130         LookupAccountNameW( NULL /* System Name to begin Search */,
1131                             smbname,
1132                             NULL, &dwSize1,
1133                             NULL, &dwSize2,
1134                             &snu);
1135         gle = GetLastError();
1136         if (gle == ERROR_INSUFFICIENT_BUFFER) {
1137             pSid = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, dwSize1);
1138             /*
1139              * Although dwSize2 is supposed to include the terminating
1140              * NUL character, on Win7 it does not.
1141              */
1142             pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
1143         }
1144
1145         if ( pSid && pszRefDomain ) {
1146             if (LookupAccountNameW( NULL /* System Name to begin Search */,
1147                                     smbname,
1148                                     pSid, &dwSize1,
1149                                     pszRefDomain, &dwSize2,
1150                                     &snu))
1151                 ConvertSidToStringSidW(pSid, &secSidString);
1152         }
1153
1154         if (secSidString) {
1155             userp = smb_FindCMUserBySID( secSidString, ioctlp->fidp->vcp->rname,
1156                                          SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1157             LocalFree(secSidString);
1158         } else {
1159             /* Free the SID so we can reuse the variable */
1160             if (pSid) {
1161                 LocalFree(pSid);
1162                 pSid = NULL;
1163             }
1164
1165             /*
1166              * If the SID for the name could not be found,
1167              * perhaps it already is a SID
1168              */
1169             if (!ConvertStringSidToSidW( smbname, &pSid)) {
1170                 userp = smb_FindCMUserBySID( smbname, ioctlp->fidp->vcp->rname,
1171                                              SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1172             } else {
1173                 userp = smb_FindCMUserByName( smbname, ioctlp->fidp->vcp->rname,
1174                                               SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1175             }
1176         }
1177
1178         if (pSid)
1179             LocalFree(pSid);
1180         if (pszRefDomain)
1181             free(pszRefDomain);
1182
1183         release_userp = 1;
1184     }
1185
1186     /* store the token */
1187     lock_ObtainMutex(&userp->mx);
1188     ucellp = cm_GetUCell(userp, cellp);
1189     osi_Log1(smb_logp,"smb_IoctlSetToken ucellp %lx", ucellp);
1190     ucellp->ticketLen = ticketLen;
1191     if (ucellp->ticketp)
1192         free(ucellp->ticketp);  /* Discard old token if any */
1193     ucellp->ticketp = malloc(ticketLen);
1194     memcpy(ucellp->ticketp, ticket, ticketLen);
1195     /*
1196      * Get the session key from the RPC, rather than from the pioctl.
1197      */
1198     /*
1199     memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1200     */
1201     memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1202     ucellp->kvno = ct.AuthHandle;
1203     ucellp->expirationTime = ct.EndTimestamp;
1204     ucellp->gen++;
1205 #ifdef QUERY_AFSID
1206     ucellp->uid = ANONYMOUSID;
1207 #endif
1208     if (uname) {
1209         cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1210 #ifdef QUERY_AFSID
1211         cm_UsernameToId(uname, ucellp, &ucellp->uid);
1212 #endif
1213     }
1214     _InterlockedOr(&ucellp->flags, CM_UCELLFLAG_RXKAD);
1215     lock_ReleaseMutex(&userp->mx);
1216
1217     if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1218         ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1219     }
1220
1221     cm_ResetACLCache(cellp, userp);
1222
1223   done:
1224     SecureZeroMemory(sessionKey, sizeof(sessionKey));
1225
1226     if (release_userp)
1227         cm_ReleaseUser(userp);
1228
1229     if (uname)
1230         free(uname);
1231
1232     if (smbname)
1233         free(smbname);
1234
1235     return code;
1236 }
1237
1238
1239
1240 afs_int32
1241 smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1242 {
1243     smb_user_t *uidp = ioctlp->uidp;
1244
1245     if (uidp && uidp->unp) {
1246         int cch;
1247
1248         cch = cm_ClientStringToUtf8(uidp->unp->name,
1249                                     -1,
1250                                     ioctlp->ioctl.outDatap,
1251                                     (int)(SMB_IOCTL_MAXDATA -
1252                                      (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
1253                                     / sizeof(cm_utf8char_t));
1254
1255         ioctlp->ioctl.outDatap += cch * sizeof(cm_utf8char_t);
1256     }
1257
1258     return 0;
1259 }
1260
1261 afs_int32
1262 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1263 {
1264     cm_scache_t *scp;
1265     afs_int32 code;
1266     cm_req_t req;
1267     cm_ioctlQueryOptions_t *optionsp;
1268     afs_uint32 flags = 0;
1269
1270     smb_InitReq(&req);
1271
1272     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1273     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1274         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1275
1276     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1277         cm_fid_t fid;
1278         cm_SkipIoctlPath(&ioctlp->ioctl);
1279         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1280                   optionsp->fid.vnode, optionsp->fid.unique);
1281         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1282     } else {
1283         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1284     }
1285
1286     if (code)
1287         return code;
1288
1289     code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1290
1291     cm_ReleaseSCache(scp);
1292     return code;
1293 }
1294
1295 afs_int32
1296 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1297 {
1298     cm_scache_t *scp;
1299     afs_int32 code;
1300     cm_req_t req;
1301     afs_uint32 flags = 0;
1302
1303     smb_InitReq(&req);
1304
1305     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1306     if (code)
1307         return code;
1308
1309     code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1310
1311     cm_ReleaseSCache(scp);
1312     return code;
1313 }
1314
1315 afs_int32
1316 smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1317 {
1318     afs_int32 code;
1319     cm_scache_t *scp;
1320     cm_req_t req;
1321     cm_ioctlQueryOptions_t *optionsp;
1322     afs_uint32 flags = 0;
1323
1324     smb_InitReq(&req);
1325
1326     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1327     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1328         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1329
1330     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1331         cm_fid_t fid;
1332         cm_SkipIoctlPath(&ioctlp->ioctl);
1333         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1334                   optionsp->fid.vnode, optionsp->fid.unique);
1335         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1336     } else {
1337         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1338     }
1339     if (code)
1340         return code;
1341
1342     code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1343
1344     cm_ReleaseSCache(scp);
1345
1346     return code;
1347 }
1348
1349 afs_int32
1350 smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1351 {
1352     cm_req_t req;
1353
1354     smb_InitReq(&req);
1355
1356     cm_SkipIoctlPath(&ioctlp->ioctl);   /* we don't care about the path */
1357
1358     return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1359 }
1360
1361 afs_int32
1362 smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1363 {
1364     afs_int32 code;
1365     cm_scache_t *scp;
1366     cm_req_t req;
1367     cm_ioctlQueryOptions_t *optionsp;
1368     afs_uint32 flags = 0;
1369
1370     smb_InitReq(&req);
1371
1372     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1373     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1374         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1375
1376     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1377         cm_fid_t fid;
1378         cm_SkipIoctlPath(&ioctlp->ioctl);
1379         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1380                   optionsp->fid.vnode, optionsp->fid.unique);
1381         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1382     } else {
1383         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1384     }
1385     if (code)
1386         return code;
1387
1388     code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1389
1390     cm_ReleaseSCache(scp);
1391
1392     return code;
1393 }
1394
1395 afs_int32
1396 smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1397 {
1398     afs_int32 code;
1399     cm_scache_t *scp;
1400     cm_req_t req;
1401     cm_ioctlQueryOptions_t *optionsp;
1402     afs_uint32 flags = 0;
1403
1404     smb_InitReq(&req);
1405
1406     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1407     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1408         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1409
1410     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1411         cm_fid_t fid;
1412         cm_SkipIoctlPath(&ioctlp->ioctl);
1413         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1414                   optionsp->fid.vnode, optionsp->fid.unique);
1415         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1416     } else {
1417         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1418     }
1419     if (code)
1420         return code;
1421
1422     code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1423
1424     cm_ReleaseSCache(scp);
1425     return code;
1426 }
1427
1428 afs_int32
1429 smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1430 {
1431     afs_int32 code;
1432     cm_scache_t *scp;
1433     cm_req_t req;
1434
1435     smb_InitReq(&req);
1436
1437     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1438     if (code) return code;
1439
1440     code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1441     cm_ReleaseSCache(scp);
1442
1443     return code;
1444 }
1445
1446 afs_int32
1447 smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1448 {
1449     afs_int32 code;
1450     cm_scache_t *scp;
1451     cm_ioctlQueryOptions_t *optionsp;
1452     afs_uint32 flags = 0;
1453     cm_req_t req;
1454
1455     smb_InitReq(&req);
1456
1457     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1458     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1459         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1460
1461     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1462         cm_fid_t fid;
1463         cm_SkipIoctlPath(&ioctlp->ioctl);
1464         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1465                   optionsp->fid.vnode, optionsp->fid.unique);
1466         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1467     } else {
1468         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1469     }
1470     if (code)
1471         return code;
1472
1473     code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1474
1475     cm_ReleaseSCache(scp);
1476
1477     return code;
1478 }
1479
1480 afs_int32
1481 smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1482 {
1483     afs_int32 code;
1484     cm_scache_t *scp;
1485     cm_req_t req;
1486     cm_ioctlQueryOptions_t * optionsp;
1487     afs_uint32 flags = 0;
1488
1489     smb_InitReq(&req);
1490
1491     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1492     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1493         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1494
1495     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1496     if (code)
1497         return code;
1498
1499     code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1500
1501     cm_ReleaseSCache(scp);
1502
1503     return code;
1504 }
1505
1506 afs_int32
1507 smb_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1508 {
1509     afs_int32 code;
1510     cm_scache_t *scp;
1511     cm_req_t req;
1512     cm_ioctlQueryOptions_t * optionsp;
1513     afs_uint32 flags = 0;
1514
1515     smb_InitReq(&req);
1516
1517     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1518     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1519         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1520
1521     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1522         cm_fid_t fid;
1523         cm_SkipIoctlPath(&ioctlp->ioctl);
1524         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1525                   optionsp->fid.vnode, optionsp->fid.unique);
1526         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1527     } else {
1528         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1529     }
1530     if (code)
1531         return code;
1532
1533     code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1534
1535     cm_ReleaseSCache(scp);
1536
1537     return code;
1538 }
1539
1540 afs_int32
1541 smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1542 {
1543     afs_int32 code;
1544     cm_scache_t *scp;
1545     cm_req_t req;
1546     cm_ioctlQueryOptions_t *optionsp;
1547     afs_uint32 flags = 0;
1548
1549     smb_InitReq(&req);
1550
1551     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1552     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1553         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1554
1555     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1556         cm_fid_t fid;
1557         cm_SkipIoctlPath(&ioctlp->ioctl);
1558         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1559                   optionsp->fid.vnode, optionsp->fid.unique);
1560         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1561     } else {
1562         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1563     }
1564     if (code)
1565         return code;
1566
1567     code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1568
1569     cm_ReleaseSCache(scp);
1570
1571     return code;
1572 }
1573
1574 afs_int32
1575 smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1576 {
1577     afs_int32 code;
1578     cm_scache_t *scp;
1579     cm_req_t req;
1580     cm_ioctlQueryOptions_t *optionsp;
1581     afs_uint32 flags = 0;
1582
1583     smb_InitReq(&req);
1584
1585     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1586     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1587         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1588
1589     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1590         cm_fid_t fid;
1591         cm_SkipIoctlPath(&ioctlp->ioctl);
1592         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1593                   optionsp->fid.vnode, optionsp->fid.unique);
1594         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1595     } else {
1596         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1597     }
1598     if (code)
1599         return code;
1600
1601     code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1602
1603     cm_ReleaseSCache(scp);
1604
1605     return code;
1606 }
1607
1608
1609 afs_int32
1610 smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1611 {
1612     afs_int32 code;
1613     cm_scache_t *dscp;
1614     cm_req_t req;
1615
1616     smb_InitReq(&req);
1617
1618     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1619     if (code)
1620         return code;
1621
1622     code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1623
1624     cm_ReleaseSCache(dscp);
1625
1626     return code;
1627 }
1628
1629 afs_int32
1630 smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1631 {
1632     afs_int32 code;
1633     cm_scache_t *dscp;
1634     cm_req_t req;
1635
1636     smb_InitReq(&req);
1637
1638     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1639     if (code)
1640         return code;
1641
1642     code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1643
1644     cm_ReleaseSCache(dscp);
1645
1646     return code;
1647 }
1648
1649 afs_int32
1650 smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1651 {
1652     cm_SkipIoctlPath(&ioctlp->ioctl);   /* we don't care about the path */
1653
1654     return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1655 }
1656
1657 afs_int32
1658 smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1659 {
1660     /* we don't print anything superfluous, so we don't support the gag call */
1661     return CM_ERROR_INVAL;
1662 }
1663
1664 afs_int32
1665 smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1666 {
1667     cm_SkipIoctlPath(&ioctlp->ioctl);
1668
1669     return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1670 }
1671
1672 afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1673 {
1674     cm_SkipIoctlPath(&ioctlp->ioctl);
1675
1676     return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1677 }
1678
1679
1680 afs_int32
1681 smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1682 {
1683     cm_SkipIoctlPath(&ioctlp->ioctl);
1684
1685     return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1686 }
1687
1688 afs_int32
1689 smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1690 {
1691     cm_SkipIoctlPath(&ioctlp->ioctl);
1692
1693     return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1694 }
1695
1696 afs_int32
1697 smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1698 {
1699     cm_SkipIoctlPath(&ioctlp->ioctl);
1700
1701     return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1702 }
1703
1704 afs_int32
1705 smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1706 {
1707     cm_SkipIoctlPath(&ioctlp->ioctl);
1708
1709     return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1710 }
1711
1712 afs_int32
1713 smb_IoctlNewCell2(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1714 {
1715     cm_SkipIoctlPath(&ioctlp->ioctl);
1716
1717     return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1718 }
1719
1720 afs_int32
1721 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1722 {
1723     cm_SkipIoctlPath(&ioctlp->ioctl);
1724
1725     return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1726 }
1727
1728 afs_int32
1729 smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1730 {
1731     cm_SkipIoctlPath(&ioctlp->ioctl);
1732
1733     return cm_IoctlSysName(&ioctlp->ioctl, userp);
1734 }
1735
1736 afs_int32
1737 smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1738 {
1739     cm_SkipIoctlPath(&ioctlp->ioctl);
1740
1741     return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1742 }
1743
1744 afs_int32
1745 smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1746 {
1747     cm_SkipIoctlPath(&ioctlp->ioctl);
1748
1749     return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1750 }
1751
1752 afs_int32
1753 smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1754 {
1755     cm_SkipIoctlPath(&ioctlp->ioctl);
1756
1757     return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1758 }
1759
1760 afs_int32
1761 smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1762 {
1763     cm_SkipIoctlPath(&ioctlp->ioctl);
1764
1765     return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1766 }
1767
1768 afs_int32
1769 smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1770 {
1771     /* we ignore default asynchrony since we only have one way
1772      * of doing this today.
1773      */
1774     return 0;
1775 }
1776
1777 afs_int32
1778 smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1779 {
1780     afs_int32 code;
1781     cm_scache_t *dscp;
1782     clientchar_t leaf[LEAF_SIZE];
1783     cm_req_t req;
1784
1785     smb_InitReq(&req);
1786
1787     code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1788     if (code)
1789         return code;
1790
1791     code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1792
1793     cm_ReleaseSCache(dscp);
1794     return code;
1795 }
1796
1797 afs_int32
1798 smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1799 {
1800     afs_int32 code;
1801     cm_scache_t *dscp;
1802     clientchar_t leaf[LEAF_SIZE];
1803     cm_req_t req;
1804
1805     smb_InitReq(&req);
1806
1807     code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1808     if (code) return code;
1809
1810     code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1811
1812     cm_ReleaseSCache(dscp);
1813
1814     return code;
1815 }
1816
1817 afs_int32
1818 smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1819 {
1820     afs_int32 code;
1821     cm_scache_t *dscp;
1822     cm_req_t req;
1823
1824     smb_InitReq(&req);
1825
1826     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1827     if (code) return code;
1828
1829     code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1830
1831     cm_ReleaseSCache(dscp);
1832     return code;
1833 }
1834
1835 afs_int32
1836 smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1837 {/*CHECK FOR VALID SYMLINK*/
1838     afs_int32 code;
1839     cm_scache_t *dscp;
1840     cm_req_t req;
1841
1842     smb_InitReq(&req);
1843
1844     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1845     if (code) return code;
1846
1847     code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1848
1849     cm_ReleaseSCache(dscp);
1850
1851     return code;
1852 }
1853
1854 afs_int32
1855 smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1856 {
1857     afs_int32 code;
1858     cm_scache_t *dscp;
1859     cm_req_t req;
1860
1861     smb_InitReq(&req);
1862
1863     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1864     if (code) return code;
1865
1866     code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1867
1868     cm_ReleaseSCache(dscp);
1869
1870     return code;
1871 }
1872
1873 afs_int32
1874 smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1875 {
1876     cm_SkipIoctlPath(&ioctlp->ioctl);
1877
1878     return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1879 }
1880
1881 afs_int32
1882 smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1883 {
1884     cm_SkipIoctlPath(&ioctlp->ioctl);
1885
1886     return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1887 }
1888
1889
1890 afs_int32
1891 smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1892 {
1893     cm_SkipIoctlPath(&ioctlp->ioctl);
1894
1895     return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1896 }
1897
1898
1899 afs_int32
1900 smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1901 {
1902     cm_SkipIoctlPath(&ioctlp->ioctl);
1903
1904     return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1905 }
1906
1907
1908 afs_int32
1909 smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1910 {
1911     cm_SkipIoctlPath(&ioctlp->ioctl);
1912
1913     return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1914 }
1915
1916 afs_int32
1917 smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1918 {
1919     cm_SkipIoctlPath(&ioctlp->ioctl);
1920
1921     return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1922 }
1923
1924 afs_int32
1925 smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1926 {
1927     cm_SkipIoctlPath(&ioctlp->ioctl);
1928
1929     return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1930 }
1931
1932 afs_int32
1933 smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1934 {
1935     cm_SkipIoctlPath(&ioctlp->ioctl);
1936
1937     return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1938 }
1939
1940
1941 afs_int32
1942 smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1943 {
1944     cm_SkipIoctlPath(&ioctlp->ioctl);
1945
1946     return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1947 }
1948
1949 afs_int32
1950 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1951 {
1952     cm_SkipIoctlPath(&ioctlp->ioctl);
1953
1954     return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1955 }
1956
1957 afs_int32
1958 smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1959 {
1960     cm_SkipIoctlPath(&ioctlp->ioctl);
1961
1962     return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1963 }
1964
1965
1966 afs_int32
1967 smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1968 {
1969     cm_SkipIoctlPath(&ioctlp->ioctl);
1970
1971     return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1972 }
1973
1974 afs_int32
1975 smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1976 {
1977     afs_int32 code;
1978     cm_scache_t *scp;
1979     cm_req_t req;
1980     cm_ioctlQueryOptions_t *optionsp;
1981     afs_uint32 flags = 0;
1982
1983     smb_InitReq(&req);
1984
1985     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1986     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1987         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1988
1989     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1990         cm_fid_t fid;
1991         cm_SkipIoctlPath(&ioctlp->ioctl);
1992         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1993                   optionsp->fid.vnode, optionsp->fid.unique);
1994         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1995     } else {
1996         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1997     }
1998     if (code)
1999         return code;
2000
2001     code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
2002     cm_ReleaseSCache(scp);
2003     return code;
2004 }
2005
2006 afs_int32
2007 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2008 {
2009     cm_req_t req;
2010
2011     smb_InitReq(&req);
2012
2013     cm_SkipIoctlPath(&ioctlp->ioctl);
2014
2015     return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
2016 }
2017
2018 /*
2019  * VIOC_SETOWNER
2020  *
2021  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2022  *
2023  */
2024 afs_int32
2025 smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2026 {
2027     afs_int32 code;
2028     cm_scache_t *scp;
2029     cm_req_t req;
2030     cm_ioctlQueryOptions_t *optionsp;
2031     afs_uint32 flags = 0;
2032
2033     smb_InitReq(&req);
2034
2035     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2036     if (optionsp) {
2037         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2038             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2039
2040         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2041             cm_fid_t fid;
2042             cm_SkipIoctlPath(&ioctlp->ioctl);
2043             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2044                        optionsp->fid.vnode, optionsp->fid.unique);
2045             code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2046         } else {
2047             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2048         }
2049         if (code)
2050             return code;
2051
2052         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2053     }
2054
2055     code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
2056
2057     cm_ReleaseSCache(scp);
2058
2059     return code;
2060 }
2061
2062 /*
2063  * VIOC_SETGROUP
2064  *
2065  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2066  *
2067  */
2068 afs_int32
2069 smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2070 {
2071     afs_int32 code;
2072     cm_scache_t *scp;
2073     cm_req_t req;
2074     cm_ioctlQueryOptions_t *optionsp;
2075     afs_uint32 flags = 0;
2076
2077     smb_InitReq(&req);
2078
2079     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2080     if (optionsp) {
2081         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2082             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2083
2084         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2085             cm_fid_t fid;
2086             cm_SkipIoctlPath(&ioctlp->ioctl);
2087             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2088                        optionsp->fid.vnode, optionsp->fid.unique);
2089             code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2090         } else {
2091             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2092         }
2093         if (code)
2094             return code;
2095
2096         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2097     }
2098
2099     code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
2100
2101     cm_ReleaseSCache(scp);
2102
2103     return code;
2104 }
2105
2106
2107 afs_int32
2108 smb_IoctlGetUnixMode(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2109 {
2110     afs_int32 code;
2111     cm_scache_t *scp;
2112     cm_req_t req;
2113     cm_ioctlQueryOptions_t *optionsp;
2114     afs_uint32 flags = 0;
2115
2116     smb_InitReq(&req);
2117
2118     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2119     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2120         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2121
2122     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2123         cm_fid_t fid;
2124         cm_SkipIoctlPath(&ioctlp->ioctl);
2125         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2126                   optionsp->fid.vnode, optionsp->fid.unique);
2127         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2128     } else {
2129         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2130     }
2131     if (code)
2132         return code;
2133
2134     code = cm_IoctlGetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2135
2136     cm_ReleaseSCache(scp);
2137
2138     return code;
2139 }
2140
2141
2142 /*
2143  * VIOC_SETUNIXMODE
2144  *
2145  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2146  */
2147 afs_int32
2148 smb_IoctlSetUnixMode(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2149 {
2150     afs_int32 code;
2151     cm_scache_t *scp;
2152     cm_req_t req;
2153     cm_ioctlQueryOptions_t *optionsp;
2154     afs_uint32 flags = 0;
2155
2156     smb_InitReq(&req);
2157
2158     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2159     if (optionsp) {
2160         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2161             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2162
2163         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2164             cm_fid_t fid;
2165             cm_SkipIoctlPath(&ioctlp->ioctl);
2166             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2167                        optionsp->fid.vnode, optionsp->fid.unique);
2168             code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2169         } else {
2170             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2171         }
2172         if (code)
2173             return code;
2174
2175         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2176     }
2177
2178     code = cm_IoctlSetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2179
2180     cm_ReleaseSCache(scp);
2181
2182     return code;
2183 }
2184
2185 afs_int32
2186 smb_IoctlGetVerifyData(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2187 {
2188     cm_SkipIoctlPath(&ioctlp->ioctl);
2189
2190     return cm_IoctlGetVerifyData(&ioctlp->ioctl);
2191 }
2192
2193 afs_int32
2194 smb_IoctlSetVerifyData(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2195 {
2196     cm_SkipIoctlPath(&ioctlp->ioctl);
2197
2198     return cm_IoctlSetVerifyData(&ioctlp->ioctl);
2199 }
2200
2201 afs_int32
2202 smb_IoctlGetCallerAccess(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2203 {
2204     afs_int32 code;
2205     cm_scache_t *scp;
2206     cm_req_t req;
2207     cm_ioctlQueryOptions_t * optionsp;
2208     afs_uint32 flags = 0;
2209
2210     smb_InitReq(&req);
2211
2212     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2213     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2214         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2215
2216     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2217         cm_fid_t fid;
2218         cm_SkipIoctlPath(&ioctlp->ioctl);
2219         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2220                   optionsp->fid.vnode, optionsp->fid.unique);
2221         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2222     } else {
2223         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2224     }
2225     if (code)
2226         return code;
2227
2228     code = cm_IoctlGetCallerAccess(&ioctlp->ioctl, userp, scp, &req);
2229
2230     cm_ReleaseSCache(scp);
2231
2232     return code;
2233 }