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