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