Windows: *ParseIoctlPath path has trailing slash
[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,  L'\\');
748             if (lastComponent && (lastComponent - p) > 1) {
749
750                 if (cm_ClientStrLen(lastComponent) == 1) {
751                     *lastComponent = '\0';
752                     lastComponent = L".";
753                 } else {
754                     *lastComponent = L'\0';
755                     lastComponent++;
756                 }
757
758                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
759                                 userp, NULL, reqp, &iscp);
760                 if (code == 0)
761                     code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
762                                     userp, NULL, reqp, scpp);
763                 if (iscp)
764                     cm_ReleaseSCache(iscp);
765             } else {
766                 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
767                                 userp, NULL, reqp, scpp);
768             }
769
770             if (code) {
771                 cm_ReleaseSCache(substRootp);
772                 osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code);
773                 if (relativePath)
774                     free(relativePath);
775                 return code;
776             }
777         }
778     } else {
779         code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
780                          CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
781                          userp, ioctlp->tidPathp, reqp, &substRootp);
782         if (code) {
783             osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code);
784             if (relativePath)
785                 free(relativePath);
786             return code;
787         }
788
789         lastComponent = cm_ClientStrRChr(relativePath,  '\\');
790         if (lastComponent && (lastComponent - relativePath) > 1 &&
791             cm_ClientStrLen(lastComponent) > 1) {
792             *lastComponent = '\0';
793             lastComponent++;
794
795             code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
796                             userp, NULL, reqp, &iscp);
797             if (code == 0)
798                 code = cm_NameI(iscp, lastComponent, CM_FLAG_CASEFOLD | follow,
799                                 userp, NULL, reqp, scpp);
800             if (iscp)
801                 cm_ReleaseSCache(iscp);
802         } else {
803             code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | follow,
804                             userp, NULL, reqp, scpp);
805         }
806         if (code) {
807             cm_ReleaseSCache(substRootp);
808             osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code);
809             if (relativePath)
810                 free(relativePath);
811             return code;
812         }
813     }
814
815     if (substRootp)
816         cm_ReleaseSCache(substRootp);
817
818     if (relativePath)
819         free(relativePath);
820
821     /* Ensure that the status object is up to date */
822     lock_ObtainWrite(&(*scpp)->rw);
823     code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
824                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
825     if (code == 0)
826         cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
827     lock_ReleaseWrite(&(*scpp)->rw);
828
829     /* and return success */
830     osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code);
831     return 0;
832 }
833
834
835
836 #define LEAF_SIZE 256
837 /* parse the passed-in file name and do a namei on its parent.  If we fail,
838  * return an error code, otherwise return the vnode located in *scpp.
839  */
840 afs_int32
841 smb_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
842                      cm_scache_t **scpp, clientchar_t *leafp)
843 {
844     long code;
845     clientchar_t tbuffer[1024];
846     clientchar_t *tp, *jp;
847     cm_scache_t *substRootp = NULL;
848     clientchar_t *inpathp = NULL;
849     char *inpathdatap;
850
851     inpathdatap = ioctlp->ioctl.inDatap;
852
853     /* If the string starts with our UTF-8 prefix (which is the
854        sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8
855        strings), we assume that the provided path is UTF-8.  Otherwise
856        we have to convert the string to UTF-8, since that is what we
857        want to use everywhere else.*/
858
859     if (memcmp(inpathdatap, utf8_prefix, utf8_prefix_size) == 0) {
860
861         /* String is UTF-8 */
862         inpathdatap += utf8_prefix_size;
863         ioctlp->ioctl.flags |= CM_IOCTLFLAG_USEUTF8;
864
865         inpathp = cm_Utf8ToClientStringAlloc(inpathdatap, -1, NULL);
866     } else {
867         int cch;
868
869         /* Not a UTF-8 string */
870         /* TODO: If this is an OEM string, we should convert it to
871            UTF-8. */
872         if (smb_StoreAnsiFilenames) {
873             cch = cm_AnsiToClientString(inpathdatap, -1, NULL, 0);
874 #ifdef DEBUG
875             osi_assert(cch > 0);
876 #endif
877             inpathp = malloc(cch * sizeof(clientchar_t));
878             cm_AnsiToClientString(inpathdatap, -1, inpathp, cch);
879         } else {
880             TranslateExtendedChars(inpathdatap);
881
882             cch = cm_OemToClientString(inpathdatap, -1, NULL, 0);
883 #ifdef DEBUG
884             osi_assert(cch > 0);
885 #endif
886             inpathp = malloc(cch * sizeof(clientchar_t));
887             cm_OemToClientString(inpathdatap, -1, inpathp, cch);
888         }
889     }
890
891     cm_ClientStrCpy(tbuffer, lengthof(tbuffer), inpathp);
892     tp = cm_ClientStrRChr(tbuffer, '\\');
893     jp = cm_ClientStrRChr(tbuffer, '/');
894     if (!tp)
895         tp = jp;
896     else if (jp && (tp - tbuffer) < (jp - tbuffer))
897         tp = jp;
898     if (!tp) {
899         cm_ClientStrCpy(tbuffer, lengthof(tbuffer), _C("\\"));
900         if (leafp)
901             cm_ClientStrCpy(leafp, LEAF_SIZE, inpathp);
902     }
903     else {
904         *tp = 0;
905         if (leafp)
906             cm_ClientStrCpy(leafp, LEAF_SIZE, tp+1);
907     }
908
909     free(inpathp);
910     inpathp = NULL;             /* We don't need this from this point on */
911
912     if (tbuffer[0] == tbuffer[1] &&
913         tbuffer[1] == '\\' &&
914         !cm_ClientStrCmpNI(cm_NetbiosNameC, tbuffer+2,
915                            (int)cm_ClientStrLen(cm_NetbiosNameC)))
916     {
917         clientchar_t shareName[256];
918         clientchar_t *sharePath;
919         int shareFound, i;
920
921         /* We may have found a UNC path.
922          * If the first component is the NetbiosName,
923          * then throw out the second component (the submount)
924          * since it had better expand into the value of ioctl->tidPathp
925          */
926         clientchar_t * p;
927         p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
928         if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
929             p += 4;
930
931         for (i = 0; *p && *p != '\\'; i++,p++ ) {
932             shareName[i] = *p;
933         }
934         p++;                    /* skip past trailing slash */
935         shareName[i] = 0;       /* terminate string */
936
937         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
938         if ( shareFound ) {
939             /* we found a sharename, therefore use the resulting path */
940             code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
941                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
942                             userp, sharePath, reqp, &substRootp);
943             free(sharePath);
944             if (code) return code;
945
946             code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
947                             userp, NULL, reqp, scpp);
948             cm_ReleaseSCache(substRootp);
949             if (code) return code;
950         } else {
951             /* otherwise, treat the name as a cellname mounted off the afs root.
952              * This requires that we reconstruct the shareName string with
953              * leading and trailing slashes.
954              */
955             p = tbuffer + 2 + cm_ClientStrLen(cm_NetbiosNameC) + 1;
956             if ( !cm_ClientStrCmpNI(_C("all"),  p,  3) )
957                 p += 4;
958
959             shareName[0] = '/';
960             for (i = 1; *p && *p != '\\'; i++,p++ ) {
961                 shareName[i] = *p;
962             }
963             p++;                    /* skip past trailing slash */
964             shareName[i++] = '/';       /* add trailing slash */
965             shareName[i] = 0;       /* terminate string */
966
967             code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
968                             CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
969                             userp, shareName, reqp, &substRootp);
970             if (code) return code;
971
972             code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
973                             userp, NULL, reqp, scpp);
974             cm_ReleaseSCache(substRootp);
975             if (code) return code;
976         }
977     } else {
978         code = cm_NameI(cm_RootSCachep(userp, reqp), ioctlp->prefix->wdata,
979                         CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
980                         userp, ioctlp->tidPathp, reqp, &substRootp);
981         if (code) return code;
982
983         code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
984                         userp, NULL, reqp, scpp);
985         cm_ReleaseSCache(substRootp);
986         if (code) return code;
987     }
988
989     /* # of bytes of path */
990     code = (long)strlen(ioctlp->ioctl.inDatap) + 1;
991     ioctlp->ioctl.inDatap += code;
992
993     /* Ensure that the status object is up to date */
994     lock_ObtainWrite(&(*scpp)->rw);
995     code = cm_SyncOp( *scpp, NULL, userp, reqp, 0,
996                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
997     if (code == 0)
998         cm_SyncOpDone( *scpp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
999     lock_ReleaseWrite(&(*scpp)->rw);
1000
1001     /* and return success */
1002     return 0;
1003 }
1004
1005 afs_int32
1006 smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1007 {
1008     char *saveDataPtr;
1009     char *tp;
1010     int ticketLen;
1011     char *ticket;
1012     int ctSize;
1013     struct ClearToken ct;
1014     cm_cell_t *cellp;
1015     cm_ucell_t *ucellp;
1016     afs_uuid_t uuid;
1017     int flags;
1018     char sessionKey[8];
1019     int release_userp = 0;
1020     clientchar_t *uname = NULL;
1021     clientchar_t *smbname = NULL;
1022     clientchar_t *wdir = NULL;
1023     clientchar_t *rpc_sid = NULL;
1024     afs_int32 code = 0;
1025
1026     saveDataPtr = ioctlp->ioctl.inDatap;
1027
1028     cm_SkipIoctlPath(&ioctlp->ioctl);
1029
1030     tp = ioctlp->ioctl.inDatap;
1031
1032     /* ticket length */
1033     memcpy(&ticketLen, tp, sizeof(ticketLen));
1034     tp += sizeof(ticketLen);
1035     if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
1036         return CM_ERROR_INVAL;
1037
1038     /* remember ticket and skip over it for now */
1039     ticket = tp;
1040     tp += ticketLen;
1041
1042     /* clear token size */
1043     memcpy(&ctSize, tp, sizeof(ctSize));
1044     tp += sizeof(ctSize);
1045     if (ctSize != sizeof(struct ClearToken))
1046         return CM_ERROR_INVAL;
1047
1048     /* clear token */
1049     memcpy(&ct, tp, ctSize);
1050     tp += ctSize;
1051     if (ct.AuthHandle == -1)
1052         ct.AuthHandle = 999;    /* more rxvab compat stuff */
1053
1054     /* more stuff, if any */
1055     if (ioctlp->ioctl.inCopied > tp - saveDataPtr) {
1056         /* flags:  logon flag */
1057         memcpy(&flags, tp, sizeof(int));
1058         tp += sizeof(int);
1059
1060         /* cell name */
1061         {
1062             fschar_t * cellnamep;
1063             clientchar_t * temp;
1064
1065             temp = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1066             cellnamep = cm_ClientStringToFsStringAlloc(temp, -1, NULL);
1067             cellp = cm_GetCell(cellnamep, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
1068             free(cellnamep);
1069             free(temp);
1070         }
1071
1072         if (!cellp) {
1073             code = CM_ERROR_NOSUCHCELL;
1074             goto done;
1075         }
1076         tp += strlen(tp) + 1;
1077
1078         /* user name */
1079         uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1080         tp += strlen(tp) + 1;
1081
1082         if (flags & PIOCTL_LOGON) {
1083             /* SMB user name with which to associate tokens */
1084             smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
1085             osi_Log2(smb_logp,"smb_IoctlSetToken for user [%S] smbname [%S]",
1086                      osi_LogSaveClientString(smb_logp,uname),
1087                      osi_LogSaveClientString(smb_logp,smbname));
1088             fprintf(stderr, "SMB name = %S\n", smbname);
1089             tp += strlen(tp) + 1;
1090         } else {
1091             osi_Log1(smb_logp,"smb_IoctlSetToken for user [%S]",
1092                      osi_LogSaveClientString(smb_logp, uname));
1093         }
1094
1095         /* uuid */
1096         memcpy(&uuid, tp, sizeof(uuid));
1097         if (!cm_FindTokenEvent(uuid, sessionKey, &rpc_sid)) {
1098             code = CM_ERROR_INVAL;
1099             goto done;
1100         }
1101
1102         if (rpc_sid) {
1103             if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM)) {
1104                 osi_Log1(smb_logp,"smb_IoctlSetToken Rpc Sid [%S]",
1105                          osi_LogSaveClientString(smb_logp, rpc_sid));
1106                 if (!cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, rpc_sid))
1107                     pflags |= AFSCALL_FLAG_LOCAL_SYSTEM;
1108             }
1109             LocalFree(rpc_sid);
1110         }
1111
1112         if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1113             code = CM_ERROR_NOACCESS;
1114             goto done;
1115         }
1116     } else {
1117         cellp = cm_data.rootCellp;
1118         osi_Log0(smb_logp,"smb_IoctlSetToken - no name specified");
1119     }
1120
1121     if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1122         PSID pSid = NULL;
1123         DWORD dwSize1 = 0, dwSize2 = 0;
1124         wchar_t *pszRefDomain = NULL;
1125         SID_NAME_USE snu = SidTypeGroup;
1126         clientchar_t * secSidString = NULL;
1127         DWORD gle;
1128
1129         /*
1130          * The specified smbname is may not be a SID for the user.
1131          * See if we can obtain the SID for the specified name.
1132          * If we can, use that instead of the name provided.
1133          */
1134
1135         LookupAccountNameW( NULL /* System Name to begin Search */,
1136                             smbname,
1137                             NULL, &dwSize1,
1138                             NULL, &dwSize2,
1139                             &snu);
1140         gle = GetLastError();
1141         if (gle == ERROR_INSUFFICIENT_BUFFER) {
1142             pSid = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, dwSize1);
1143             /*
1144              * Although dwSize2 is supposed to include the terminating
1145              * NUL character, on Win7 it does not.
1146              */
1147             pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
1148         }
1149
1150         if ( pSid && pszRefDomain ) {
1151             if (LookupAccountNameW( NULL /* System Name to begin Search */,
1152                                     smbname,
1153                                     pSid, &dwSize1,
1154                                     pszRefDomain, &dwSize2,
1155                                     &snu))
1156                 ConvertSidToStringSidW(pSid, &secSidString);
1157         }
1158
1159         if (secSidString) {
1160             userp = smb_FindCMUserBySID( secSidString, ioctlp->fidp->vcp->rname,
1161                                          SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1162             LocalFree(secSidString);
1163         } else {
1164             /* Free the SID so we can reuse the variable */
1165             if (pSid) {
1166                 LocalFree(pSid);
1167                 pSid = NULL;
1168             }
1169
1170             /*
1171              * If the SID for the name could not be found,
1172              * perhaps it already is a SID
1173              */
1174             if (!ConvertStringSidToSidW( smbname, &pSid)) {
1175                 userp = smb_FindCMUserBySID( smbname, ioctlp->fidp->vcp->rname,
1176                                              SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1177             } else {
1178                 userp = smb_FindCMUserByName( smbname, ioctlp->fidp->vcp->rname,
1179                                               SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1180             }
1181         }
1182
1183         if (pSid)
1184             LocalFree(pSid);
1185         if (pszRefDomain)
1186             free(pszRefDomain);
1187
1188         release_userp = 1;
1189     }
1190
1191     /* store the token */
1192     lock_ObtainMutex(&userp->mx);
1193     ucellp = cm_GetUCell(userp, cellp);
1194     osi_Log1(smb_logp,"smb_IoctlSetToken ucellp %lx", ucellp);
1195     ucellp->ticketLen = ticketLen;
1196     if (ucellp->ticketp)
1197         free(ucellp->ticketp);  /* Discard old token if any */
1198     ucellp->ticketp = malloc(ticketLen);
1199     memcpy(ucellp->ticketp, ticket, ticketLen);
1200     /*
1201      * Get the session key from the RPC, rather than from the pioctl.
1202      */
1203     /*
1204     memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1205     */
1206     memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1207     ucellp->kvno = ct.AuthHandle;
1208     ucellp->expirationTime = ct.EndTimestamp;
1209     ucellp->gen++;
1210 #ifdef QUERY_AFSID
1211     ucellp->uid = ANONYMOUSID;
1212 #endif
1213     if (uname) {
1214         cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1215 #ifdef QUERY_AFSID
1216         cm_UsernameToId(uname, ucellp, &ucellp->uid);
1217 #endif
1218     }
1219     _InterlockedOr(&ucellp->flags, CM_UCELLFLAG_RXKAD);
1220     lock_ReleaseMutex(&userp->mx);
1221
1222     if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1223         ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1224     }
1225
1226     cm_ResetACLCache(cellp, userp);
1227
1228   done:
1229     SecureZeroMemory(sessionKey, sizeof(sessionKey));
1230
1231     if (release_userp)
1232         cm_ReleaseUser(userp);
1233
1234     if (uname)
1235         free(uname);
1236
1237     if (smbname)
1238         free(smbname);
1239
1240     return code;
1241 }
1242
1243
1244
1245 afs_int32
1246 smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1247 {
1248     smb_user_t *uidp = ioctlp->uidp;
1249
1250     if (uidp && uidp->unp) {
1251         int cch;
1252
1253         cch = cm_ClientStringToUtf8(uidp->unp->name,
1254                                     -1,
1255                                     ioctlp->ioctl.outDatap,
1256                                     (int)(SMB_IOCTL_MAXDATA -
1257                                      (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
1258                                     / sizeof(cm_utf8char_t));
1259
1260         ioctlp->ioctl.outDatap += cch * sizeof(cm_utf8char_t);
1261     }
1262
1263     return 0;
1264 }
1265
1266 afs_int32
1267 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1268 {
1269     cm_scache_t *scp;
1270     afs_int32 code;
1271     cm_req_t req;
1272     cm_ioctlQueryOptions_t *optionsp;
1273     afs_uint32 flags = 0;
1274
1275     smb_InitReq(&req);
1276
1277     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1278     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1279         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1280
1281     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1282         cm_fid_t fid;
1283         cm_SkipIoctlPath(&ioctlp->ioctl);
1284         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1285                   optionsp->fid.vnode, optionsp->fid.unique);
1286         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1287     } else {
1288         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1289     }
1290
1291     if (code)
1292         return code;
1293
1294     code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1295
1296     cm_ReleaseSCache(scp);
1297     return code;
1298 }
1299
1300 afs_int32
1301 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1302 {
1303     cm_scache_t *scp;
1304     afs_int32 code;
1305     cm_req_t req;
1306     afs_uint32 flags = 0;
1307
1308     smb_InitReq(&req);
1309
1310     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1311     if (code)
1312         return code;
1313
1314     code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1315
1316     cm_ReleaseSCache(scp);
1317     return code;
1318 }
1319
1320 afs_int32
1321 smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1322 {
1323     afs_int32 code;
1324     cm_scache_t *scp;
1325     cm_req_t req;
1326     cm_ioctlQueryOptions_t *optionsp;
1327     afs_uint32 flags = 0;
1328
1329     smb_InitReq(&req);
1330
1331     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1332     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1333         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1334
1335     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1336         cm_fid_t fid;
1337         cm_SkipIoctlPath(&ioctlp->ioctl);
1338         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1339                   optionsp->fid.vnode, optionsp->fid.unique);
1340         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1341     } else {
1342         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1343     }
1344     if (code)
1345         return code;
1346
1347     code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1348
1349     cm_ReleaseSCache(scp);
1350
1351     return code;
1352 }
1353
1354 afs_int32
1355 smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1356 {
1357     cm_req_t req;
1358
1359     smb_InitReq(&req);
1360
1361     cm_SkipIoctlPath(&ioctlp->ioctl);   /* we don't care about the path */
1362
1363     return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1364 }
1365
1366 afs_int32
1367 smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1368 {
1369     afs_int32 code;
1370     cm_scache_t *scp;
1371     cm_req_t req;
1372     cm_ioctlQueryOptions_t *optionsp;
1373     afs_uint32 flags = 0;
1374
1375     smb_InitReq(&req);
1376
1377     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1378     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1379         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1380
1381     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1382         cm_fid_t fid;
1383         cm_SkipIoctlPath(&ioctlp->ioctl);
1384         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1385                   optionsp->fid.vnode, optionsp->fid.unique);
1386         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1387     } else {
1388         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1389     }
1390     if (code)
1391         return code;
1392
1393     code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1394
1395     cm_ReleaseSCache(scp);
1396
1397     return code;
1398 }
1399
1400 afs_int32
1401 smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1402 {
1403     afs_int32 code;
1404     cm_scache_t *scp;
1405     cm_req_t req;
1406     cm_ioctlQueryOptions_t *optionsp;
1407     afs_uint32 flags = 0;
1408
1409     smb_InitReq(&req);
1410
1411     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1412     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1413         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1414
1415     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1416         cm_fid_t fid;
1417         cm_SkipIoctlPath(&ioctlp->ioctl);
1418         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1419                   optionsp->fid.vnode, optionsp->fid.unique);
1420         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1421     } else {
1422         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1423     }
1424     if (code)
1425         return code;
1426
1427     code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1428
1429     cm_ReleaseSCache(scp);
1430     return code;
1431 }
1432
1433 afs_int32
1434 smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1435 {
1436     afs_int32 code;
1437     cm_scache_t *scp;
1438     cm_req_t req;
1439
1440     smb_InitReq(&req);
1441
1442     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1443     if (code) return code;
1444
1445     code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1446     cm_ReleaseSCache(scp);
1447
1448     return code;
1449 }
1450
1451 afs_int32
1452 smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1453 {
1454     afs_int32 code;
1455     cm_scache_t *scp;
1456     cm_ioctlQueryOptions_t *optionsp;
1457     afs_uint32 flags = 0;
1458     cm_req_t req;
1459
1460     smb_InitReq(&req);
1461
1462     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1463     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1464         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1465
1466     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1467         cm_fid_t fid;
1468         cm_SkipIoctlPath(&ioctlp->ioctl);
1469         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1470                   optionsp->fid.vnode, optionsp->fid.unique);
1471         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1472     } else {
1473         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1474     }
1475     if (code)
1476         return code;
1477
1478     code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1479
1480     cm_ReleaseSCache(scp);
1481
1482     return code;
1483 }
1484
1485 afs_int32
1486 smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1487 {
1488     afs_int32 code;
1489     cm_scache_t *scp;
1490     cm_req_t req;
1491     cm_ioctlQueryOptions_t * optionsp;
1492     afs_uint32 flags = 0;
1493
1494     smb_InitReq(&req);
1495
1496     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1497     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1498         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1499
1500     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1501     if (code)
1502         return code;
1503
1504     code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1505
1506     cm_ReleaseSCache(scp);
1507
1508     return code;
1509 }
1510
1511 afs_int32
1512 smb_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1513 {
1514     afs_int32 code;
1515     cm_scache_t *scp;
1516     cm_req_t req;
1517     cm_ioctlQueryOptions_t * optionsp;
1518     afs_uint32 flags = 0;
1519
1520     smb_InitReq(&req);
1521
1522     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1523     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1524         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1525
1526     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1527         cm_fid_t fid;
1528         cm_SkipIoctlPath(&ioctlp->ioctl);
1529         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1530                   optionsp->fid.vnode, optionsp->fid.unique);
1531         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1532     } else {
1533         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1534     }
1535     if (code)
1536         return code;
1537
1538     code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1539
1540     cm_ReleaseSCache(scp);
1541
1542     return code;
1543 }
1544
1545 afs_int32
1546 smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1547 {
1548     afs_int32 code;
1549     cm_scache_t *scp;
1550     cm_req_t req;
1551     cm_ioctlQueryOptions_t *optionsp;
1552     afs_uint32 flags = 0;
1553
1554     smb_InitReq(&req);
1555
1556     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1557     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1558         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1559
1560     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1561         cm_fid_t fid;
1562         cm_SkipIoctlPath(&ioctlp->ioctl);
1563         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1564                   optionsp->fid.vnode, optionsp->fid.unique);
1565         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1566     } else {
1567         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1568     }
1569     if (code)
1570         return code;
1571
1572     code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1573
1574     cm_ReleaseSCache(scp);
1575
1576     return code;
1577 }
1578
1579 afs_int32
1580 smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1581 {
1582     afs_int32 code;
1583     cm_scache_t *scp;
1584     cm_req_t req;
1585     cm_ioctlQueryOptions_t *optionsp;
1586     afs_uint32 flags = 0;
1587
1588     smb_InitReq(&req);
1589
1590     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1591     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1592         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1593
1594     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1595         cm_fid_t fid;
1596         cm_SkipIoctlPath(&ioctlp->ioctl);
1597         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1598                   optionsp->fid.vnode, optionsp->fid.unique);
1599         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
1600     } else {
1601         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1602     }
1603     if (code)
1604         return code;
1605
1606     code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1607
1608     cm_ReleaseSCache(scp);
1609
1610     return code;
1611 }
1612
1613
1614 afs_int32
1615 smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1616 {
1617     afs_int32 code;
1618     cm_scache_t *dscp;
1619     cm_req_t req;
1620
1621     smb_InitReq(&req);
1622
1623     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1624     if (code)
1625         return code;
1626
1627     code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1628
1629     cm_ReleaseSCache(dscp);
1630
1631     return code;
1632 }
1633
1634 afs_int32
1635 smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1636 {
1637     afs_int32 code;
1638     cm_scache_t *dscp;
1639     cm_req_t req;
1640
1641     smb_InitReq(&req);
1642
1643     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1644     if (code)
1645         return code;
1646
1647     code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1648
1649     cm_ReleaseSCache(dscp);
1650
1651     return code;
1652 }
1653
1654 afs_int32
1655 smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1656 {
1657     cm_SkipIoctlPath(&ioctlp->ioctl);   /* we don't care about the path */
1658
1659     return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1660 }
1661
1662 afs_int32
1663 smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1664 {
1665     /* we don't print anything superfluous, so we don't support the gag call */
1666     return CM_ERROR_INVAL;
1667 }
1668
1669 afs_int32
1670 smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1671 {
1672     cm_SkipIoctlPath(&ioctlp->ioctl);
1673
1674     return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1675 }
1676
1677 afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1678 {
1679     cm_SkipIoctlPath(&ioctlp->ioctl);
1680
1681     return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1682 }
1683
1684
1685 afs_int32
1686 smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1687 {
1688     cm_SkipIoctlPath(&ioctlp->ioctl);
1689
1690     return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1691 }
1692
1693 afs_int32
1694 smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1695 {
1696     cm_SkipIoctlPath(&ioctlp->ioctl);
1697
1698     return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1699 }
1700
1701 afs_int32
1702 smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1703 {
1704     cm_SkipIoctlPath(&ioctlp->ioctl);
1705
1706     return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1707 }
1708
1709 afs_int32
1710 smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1711 {
1712     cm_SkipIoctlPath(&ioctlp->ioctl);
1713
1714     return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1715 }
1716
1717 afs_int32
1718 smb_IoctlNewCell2(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1719 {
1720     cm_SkipIoctlPath(&ioctlp->ioctl);
1721
1722     return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1723 }
1724
1725 afs_int32
1726 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1727 {
1728     cm_SkipIoctlPath(&ioctlp->ioctl);
1729
1730     return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1731 }
1732
1733 afs_int32
1734 smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1735 {
1736     cm_SkipIoctlPath(&ioctlp->ioctl);
1737
1738     return cm_IoctlSysName(&ioctlp->ioctl, userp);
1739 }
1740
1741 afs_int32
1742 smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1743 {
1744     cm_SkipIoctlPath(&ioctlp->ioctl);
1745
1746     return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1747 }
1748
1749 afs_int32
1750 smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1751 {
1752     cm_SkipIoctlPath(&ioctlp->ioctl);
1753
1754     return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1755 }
1756
1757 afs_int32
1758 smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1759 {
1760     cm_SkipIoctlPath(&ioctlp->ioctl);
1761
1762     return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1763 }
1764
1765 afs_int32
1766 smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1767 {
1768     cm_SkipIoctlPath(&ioctlp->ioctl);
1769
1770     return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1771 }
1772
1773 afs_int32
1774 smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1775 {
1776     /* we ignore default asynchrony since we only have one way
1777      * of doing this today.
1778      */
1779     return 0;
1780 }
1781
1782 afs_int32
1783 smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1784 {
1785     afs_int32 code;
1786     cm_scache_t *dscp;
1787     clientchar_t leaf[LEAF_SIZE];
1788     cm_req_t req;
1789
1790     smb_InitReq(&req);
1791
1792     code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1793     if (code)
1794         return code;
1795
1796     code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1797
1798     cm_ReleaseSCache(dscp);
1799     return code;
1800 }
1801
1802 afs_int32
1803 smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1804 {
1805     afs_int32 code;
1806     cm_scache_t *dscp;
1807     clientchar_t leaf[LEAF_SIZE];
1808     cm_req_t req;
1809
1810     smb_InitReq(&req);
1811
1812     code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1813     if (code) return code;
1814
1815     code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1816
1817     cm_ReleaseSCache(dscp);
1818
1819     return code;
1820 }
1821
1822 afs_int32
1823 smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1824 {
1825     afs_int32 code;
1826     cm_scache_t *dscp;
1827     cm_req_t req;
1828
1829     smb_InitReq(&req);
1830
1831     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1832     if (code) return code;
1833
1834     code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1835
1836     cm_ReleaseSCache(dscp);
1837     return code;
1838 }
1839
1840 afs_int32
1841 smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1842 {/*CHECK FOR VALID SYMLINK*/
1843     afs_int32 code;
1844     cm_scache_t *dscp;
1845     cm_req_t req;
1846
1847     smb_InitReq(&req);
1848
1849     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1850     if (code) return code;
1851
1852     code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1853
1854     cm_ReleaseSCache(dscp);
1855
1856     return code;
1857 }
1858
1859 afs_int32
1860 smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1861 {
1862     afs_int32 code;
1863     cm_scache_t *dscp;
1864     cm_req_t req;
1865
1866     smb_InitReq(&req);
1867
1868     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1869     if (code) return code;
1870
1871     code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1872
1873     cm_ReleaseSCache(dscp);
1874
1875     return code;
1876 }
1877
1878 afs_int32
1879 smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1880 {
1881     cm_SkipIoctlPath(&ioctlp->ioctl);
1882
1883     return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1884 }
1885
1886 afs_int32
1887 smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1888 {
1889     cm_SkipIoctlPath(&ioctlp->ioctl);
1890
1891     return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1892 }
1893
1894
1895 afs_int32
1896 smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1897 {
1898     cm_SkipIoctlPath(&ioctlp->ioctl);
1899
1900     return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1901 }
1902
1903
1904 afs_int32
1905 smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1906 {
1907     cm_SkipIoctlPath(&ioctlp->ioctl);
1908
1909     return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1910 }
1911
1912
1913 afs_int32
1914 smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1915 {
1916     cm_SkipIoctlPath(&ioctlp->ioctl);
1917
1918     return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1919 }
1920
1921 afs_int32
1922 smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1923 {
1924     cm_SkipIoctlPath(&ioctlp->ioctl);
1925
1926     return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1927 }
1928
1929 afs_int32
1930 smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1931 {
1932     cm_SkipIoctlPath(&ioctlp->ioctl);
1933
1934     return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1935 }
1936
1937 afs_int32
1938 smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1939 {
1940     cm_SkipIoctlPath(&ioctlp->ioctl);
1941
1942     return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1943 }
1944
1945
1946 afs_int32
1947 smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1948 {
1949     cm_SkipIoctlPath(&ioctlp->ioctl);
1950
1951     return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1952 }
1953
1954 afs_int32
1955 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1956 {
1957     cm_SkipIoctlPath(&ioctlp->ioctl);
1958
1959     return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1960 }
1961
1962 afs_int32
1963 smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1964 {
1965     cm_SkipIoctlPath(&ioctlp->ioctl);
1966
1967     return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1968 }
1969
1970
1971 afs_int32
1972 smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1973 {
1974     cm_SkipIoctlPath(&ioctlp->ioctl);
1975
1976     return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1977 }
1978
1979 afs_int32
1980 smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1981 {
1982     afs_int32 code;
1983     cm_scache_t *scp;
1984     cm_req_t req;
1985     cm_ioctlQueryOptions_t *optionsp;
1986     afs_uint32 flags = 0;
1987
1988     smb_InitReq(&req);
1989
1990     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1991     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1992         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1993
1994     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1995         cm_fid_t fid;
1996         cm_SkipIoctlPath(&ioctlp->ioctl);
1997         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1998                   optionsp->fid.vnode, optionsp->fid.unique);
1999         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2000     } else {
2001         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2002     }
2003     if (code)
2004         return code;
2005
2006     code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
2007     cm_ReleaseSCache(scp);
2008     return code;
2009 }
2010
2011 afs_int32
2012 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2013 {
2014     cm_req_t req;
2015
2016     smb_InitReq(&req);
2017
2018     cm_SkipIoctlPath(&ioctlp->ioctl);
2019
2020     return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
2021 }
2022
2023 /*
2024  * VIOC_SETOWNER
2025  *
2026  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2027  *
2028  */
2029 afs_int32
2030 smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2031 {
2032     afs_int32 code;
2033     cm_scache_t *scp;
2034     cm_req_t req;
2035     cm_ioctlQueryOptions_t *optionsp;
2036     afs_uint32 flags = 0;
2037
2038     smb_InitReq(&req);
2039
2040     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2041     if (optionsp) {
2042         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2043             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2044
2045         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2046             cm_fid_t fid;
2047             cm_SkipIoctlPath(&ioctlp->ioctl);
2048             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2049                        optionsp->fid.vnode, optionsp->fid.unique);
2050             code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2051         } else {
2052             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2053         }
2054         if (code)
2055             return code;
2056
2057         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2058     }
2059
2060     code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
2061
2062     cm_ReleaseSCache(scp);
2063
2064     return code;
2065 }
2066
2067 /*
2068  * VIOC_SETGROUP
2069  *
2070  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2071  *
2072  */
2073 afs_int32
2074 smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2075 {
2076     afs_int32 code;
2077     cm_scache_t *scp;
2078     cm_req_t req;
2079     cm_ioctlQueryOptions_t *optionsp;
2080     afs_uint32 flags = 0;
2081
2082     smb_InitReq(&req);
2083
2084     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2085     if (optionsp) {
2086         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2087             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2088
2089         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2090             cm_fid_t fid;
2091             cm_SkipIoctlPath(&ioctlp->ioctl);
2092             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2093                        optionsp->fid.vnode, optionsp->fid.unique);
2094             code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2095         } else {
2096             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2097         }
2098         if (code)
2099             return code;
2100
2101         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2102     }
2103
2104     code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
2105
2106     cm_ReleaseSCache(scp);
2107
2108     return code;
2109 }
2110
2111
2112 afs_int32
2113 smb_IoctlGetUnixMode(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2114 {
2115     afs_int32 code;
2116     cm_scache_t *scp;
2117     cm_req_t req;
2118     cm_ioctlQueryOptions_t *optionsp;
2119     afs_uint32 flags = 0;
2120
2121     smb_InitReq(&req);
2122
2123     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2124     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2125         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2126
2127     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2128         cm_fid_t fid;
2129         cm_SkipIoctlPath(&ioctlp->ioctl);
2130         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2131                   optionsp->fid.vnode, optionsp->fid.unique);
2132         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2133     } else {
2134         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2135     }
2136     if (code)
2137         return code;
2138
2139     code = cm_IoctlGetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2140
2141     cm_ReleaseSCache(scp);
2142
2143     return code;
2144 }
2145
2146
2147 /*
2148  * VIOC_SETUNIXMODE
2149  *
2150  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2151  */
2152 afs_int32
2153 smb_IoctlSetUnixMode(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2154 {
2155     afs_int32 code;
2156     cm_scache_t *scp;
2157     cm_req_t req;
2158     cm_ioctlQueryOptions_t *optionsp;
2159     afs_uint32 flags = 0;
2160
2161     smb_InitReq(&req);
2162
2163     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2164     if (optionsp) {
2165         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2166             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2167
2168         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2169             cm_fid_t fid;
2170             cm_SkipIoctlPath(&ioctlp->ioctl);
2171             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2172                        optionsp->fid.vnode, optionsp->fid.unique);
2173             code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2174         } else {
2175             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2176         }
2177         if (code)
2178             return code;
2179
2180         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2181     }
2182
2183     code = cm_IoctlSetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2184
2185     cm_ReleaseSCache(scp);
2186
2187     return code;
2188 }
2189
2190 afs_int32
2191 smb_IoctlGetVerifyData(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2192 {
2193     cm_SkipIoctlPath(&ioctlp->ioctl);
2194
2195     return cm_IoctlGetVerifyData(&ioctlp->ioctl);
2196 }
2197
2198 afs_int32
2199 smb_IoctlSetVerifyData(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2200 {
2201     cm_SkipIoctlPath(&ioctlp->ioctl);
2202
2203     return cm_IoctlSetVerifyData(&ioctlp->ioctl);
2204 }
2205
2206 afs_int32
2207 smb_IoctlGetCallerAccess(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2208 {
2209     afs_int32 code;
2210     cm_scache_t *scp;
2211     cm_req_t req;
2212     cm_ioctlQueryOptions_t * optionsp;
2213     afs_uint32 flags = 0;
2214
2215     smb_InitReq(&req);
2216
2217     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2218     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2219         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2220
2221     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2222         cm_fid_t fid;
2223         cm_SkipIoctlPath(&ioctlp->ioctl);
2224         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2225                   optionsp->fid.vnode, optionsp->fid.unique);
2226         code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
2227     } else {
2228         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2229     }
2230     if (code)
2231         return code;
2232
2233     code = cm_IoctlGetCallerAccess(&ioctlp->ioctl, userp, scp, &req);
2234
2235     cm_ReleaseSCache(scp);
2236
2237     return code;
2238 }