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