Windows: VIOC_GETUNIXMODE = smb_IoctlGetUnixMode
[openafs.git] / src / WINNT / afsd / smb_ioctl.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <roken.h>
13
14 #include <afs/stds.h>
15
16 #include <windows.h>
17 #include <sddl.h>
18 #include <stdlib.h>
19 #include <malloc.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <time.h>
23 #include <strsafe.h>
24
25 #include <osi.h>
26
27 #include "afsd.h"
28
29 #include "smb.h"
30
31 #include "cm_rpc.h"
32 #include "afs/afsrpc.h"
33 #include "afs/auth.h"
34
35 smb_ioctlProc_t *smb_ioctlProcsp[SMB_IOCTL_MAXPROCS];
36
37 void
38 smb_InitIoctl(void)
39 {
40     int i;
41     for (i=0; i<SMB_IOCTL_MAXPROCS; i++)
42         smb_ioctlProcsp[i] = NULL;
43
44     smb_ioctlProcsp[VIOCGETAL] = smb_IoctlGetACL;
45     smb_ioctlProcsp[VIOC_FILE_CELL_NAME] = smb_IoctlGetFileCellName;
46     smb_ioctlProcsp[VIOCSETAL] = smb_IoctlSetACL;
47     smb_ioctlProcsp[VIOC_FLUSHVOLUME] = smb_IoctlFlushVolume;
48     smb_ioctlProcsp[VIOCFLUSH] = smb_IoctlFlushFile;
49     smb_ioctlProcsp[VIOCSETVOLSTAT] = smb_IoctlSetVolumeStatus;
50     smb_ioctlProcsp[VIOCGETVOLSTAT] = smb_IoctlGetVolumeStatus;
51     smb_ioctlProcsp[VIOCWHEREIS] = smb_IoctlWhereIs;
52     smb_ioctlProcsp[VIOC_AFS_STAT_MT_PT] = smb_IoctlStatMountPoint;
53     smb_ioctlProcsp[VIOC_AFS_DELETE_MT_PT] = smb_IoctlDeleteMountPoint;
54     smb_ioctlProcsp[VIOCCKSERV] = smb_IoctlCheckServers;
55     smb_ioctlProcsp[VIOC_GAG] = smb_IoctlGag;
56     smb_ioctlProcsp[VIOCCKBACK] = smb_IoctlCheckVolumes;
57     smb_ioctlProcsp[VIOCSETCACHESIZE] = smb_IoctlSetCacheSize;
58     smb_ioctlProcsp[VIOCGETCACHEPARMS] = smb_IoctlGetCacheParms;
59     smb_ioctlProcsp[VIOCGETCELL] = smb_IoctlGetCell;
60     smb_ioctlProcsp[VIOCNEWCELL] = smb_IoctlNewCell;
61     smb_ioctlProcsp[VIOC_GET_WS_CELL] = smb_IoctlGetWsCell;
62     smb_ioctlProcsp[VIOC_AFS_SYSNAME] = smb_IoctlSysName;
63     smb_ioctlProcsp[VIOC_GETCELLSTATUS] = smb_IoctlGetCellStatus;
64     smb_ioctlProcsp[VIOC_SETCELLSTATUS] = smb_IoctlSetCellStatus;
65     smb_ioctlProcsp[VIOC_SETSPREFS] = smb_IoctlSetSPrefs;
66     smb_ioctlProcsp[VIOC_GETSPREFS] = smb_IoctlGetSPrefs;
67     smb_ioctlProcsp[VIOC_STOREBEHIND] = smb_IoctlStoreBehind;
68     smb_ioctlProcsp[VIOC_AFS_CREATE_MT_PT] = smb_IoctlCreateMountPoint;
69     smb_ioctlProcsp[VIOC_TRACECTL] = smb_IoctlTraceControl;
70     smb_ioctlProcsp[VIOCSETTOK] = smb_IoctlSetToken;
71     smb_ioctlProcsp[VIOCGETTOK] = smb_IoctlGetTokenIter;
72     smb_ioctlProcsp[VIOCNEWGETTOK] = smb_IoctlGetToken;
73     smb_ioctlProcsp[VIOCDELTOK] = smb_IoctlDelToken;
74     smb_ioctlProcsp[VIOCDELALLTOK] = smb_IoctlDelAllToken;
75     smb_ioctlProcsp[VIOC_SYMLINK] = smb_IoctlSymlink;
76     smb_ioctlProcsp[VIOC_LISTSYMLINK] = smb_IoctlListlink;
77     smb_ioctlProcsp[VIOC_DELSYMLINK] = smb_IoctlDeletelink;
78     smb_ioctlProcsp[VIOC_MAKESUBMOUNT] = smb_IoctlMakeSubmount;
79     smb_ioctlProcsp[VIOC_GETRXKCRYPT] = smb_IoctlGetRxkcrypt;
80     smb_ioctlProcsp[VIOC_SETRXKCRYPT] = smb_IoctlSetRxkcrypt;
81     smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
82     smb_ioctlProcsp[VIOC_TRACEMEMDUMP] = smb_IoctlMemoryDump;
83     smb_ioctlProcsp[VIOC_ISSYMLINK] = smb_IoctlIslink;
84     smb_ioctlProcsp[VIOC_FLUSHALL] = smb_IoctlFlushAllVolumes;
85     smb_ioctlProcsp[VIOCGETFID] = smb_IoctlGetFid;
86     smb_ioctlProcsp[VIOCGETOWNER] = smb_IoctlGetOwner;
87     smb_ioctlProcsp[VIOC_RXSTAT_PROC] = smb_IoctlRxStatProcess;
88     smb_ioctlProcsp[VIOC_RXSTAT_PEER] = smb_IoctlRxStatPeer;
89     smb_ioctlProcsp[VIOC_UUIDCTL] = smb_IoctlUUIDControl;
90     smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = smb_IoctlPathAvailability;
91     smb_ioctlProcsp[VIOC_GETFILETYPE] = smb_IoctlGetFileType;
92     smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = smb_IoctlVolStatTest;
93     smb_ioctlProcsp[VIOC_UNICODECTL] = smb_IoctlUnicodeControl;
94     smb_ioctlProcsp[VIOC_SETOWNER] = smb_IoctlSetOwner;
95     smb_ioctlProcsp[VIOC_SETGROUP] = smb_IoctlSetGroup;
96     smb_ioctlProcsp[VIOCNEWCELL2] = smb_IoctlNewCell2;
97     smb_ioctlProcsp[VIOC_SETUNIXMODE] = smb_IoctlSetUnixMode;
98     smb_ioctlProcsp[VIOC_GETUNIXMODE] = smb_IoctlGetUnixMode;
99 }
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 (rpc_sid) {
1095             if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM)) {
1096                 osi_Log1(smb_logp,"smb_IoctlSetToken Rpc Sid [%S]",
1097                          osi_LogSaveClientString(smb_logp, rpc_sid));
1098                 if (!cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, rpc_sid))
1099                     pflags |= AFSCALL_FLAG_LOCAL_SYSTEM;
1100             }
1101             LocalFree(rpc_sid);
1102         }
1103
1104         if (!(pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1105             code = CM_ERROR_NOACCESS;
1106             goto done;
1107         }
1108     } else {
1109         cellp = cm_data.rootCellp;
1110         osi_Log0(smb_logp,"smb_IoctlSetToken - no name specified");
1111     }
1112
1113     if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1114         PSID pSid = NULL;
1115         DWORD dwSize1 = 0, dwSize2 = 0;
1116         wchar_t *pszRefDomain = NULL;
1117         SID_NAME_USE snu = SidTypeGroup;
1118         clientchar_t * secSidString = NULL;
1119         DWORD gle;
1120
1121         /*
1122          * The specified smbname is may not be a SID for the user.
1123          * See if we can obtain the SID for the specified name.
1124          * If we can, use that instead of the name provided.
1125          */
1126
1127         LookupAccountNameW( NULL /* System Name to begin Search */,
1128                             smbname,
1129                             NULL, &dwSize1,
1130                             NULL, &dwSize2,
1131                             &snu);
1132         gle = GetLastError();
1133         if (gle == ERROR_INSUFFICIENT_BUFFER) {
1134             pSid = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, dwSize1);
1135             /*
1136              * Although dwSize2 is supposed to include the terminating
1137              * NUL character, on Win7 it does not.
1138              */
1139             pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
1140         }
1141
1142         if ( pSid && pszRefDomain ) {
1143             if (LookupAccountNameW( NULL /* System Name to begin Search */,
1144                                     smbname,
1145                                     pSid, &dwSize1,
1146                                     pszRefDomain, &dwSize2,
1147                                     &snu))
1148                 ConvertSidToStringSidW(pSid, &secSidString);
1149         }
1150
1151         if (secSidString) {
1152             userp = smb_FindCMUserBySID( secSidString, ioctlp->fidp->vcp->rname,
1153                                          SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1154             LocalFree(secSidString);
1155         } else {
1156             /* Free the SID so we can reuse the variable */
1157             if (pSid) {
1158                 LocalFree(pSid);
1159                 pSid = NULL;
1160             }
1161
1162             /*
1163              * If the SID for the name could not be found,
1164              * perhaps it already is a SID
1165              */
1166             if (!ConvertStringSidToSidW( smbname, &pSid)) {
1167                 userp = smb_FindCMUserBySID( smbname, ioctlp->fidp->vcp->rname,
1168                                              SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1169             } else {
1170                 userp = smb_FindCMUserByName( smbname, ioctlp->fidp->vcp->rname,
1171                                               SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
1172             }
1173         }
1174
1175         if (pSid)
1176             LocalFree(pSid);
1177         if (pszRefDomain)
1178             free(pszRefDomain);
1179
1180         release_userp = 1;
1181     }
1182
1183     /* store the token */
1184     lock_ObtainMutex(&userp->mx);
1185     ucellp = cm_GetUCell(userp, cellp);
1186     osi_Log1(smb_logp,"smb_IoctlSetToken ucellp %lx", ucellp);
1187     ucellp->ticketLen = ticketLen;
1188     if (ucellp->ticketp)
1189         free(ucellp->ticketp);  /* Discard old token if any */
1190     ucellp->ticketp = malloc(ticketLen);
1191     memcpy(ucellp->ticketp, ticket, ticketLen);
1192     /*
1193      * Get the session key from the RPC, rather than from the pioctl.
1194      */
1195     /*
1196     memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1197     */
1198     memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1199     ucellp->kvno = ct.AuthHandle;
1200     ucellp->expirationTime = ct.EndTimestamp;
1201     ucellp->gen++;
1202 #ifdef QUERY_AFSID
1203     ucellp->uid = ANONYMOUSID;
1204 #endif
1205     if (uname) {
1206         cm_ClientStringToFsString(uname, -1, ucellp->userName, MAXKTCNAMELEN);
1207 #ifdef QUERY_AFSID
1208         cm_UsernameToId(uname, ucellp, &ucellp->uid);
1209 #endif
1210     }
1211     _InterlockedOr(&ucellp->flags, CM_UCELLFLAG_RXKAD);
1212     lock_ReleaseMutex(&userp->mx);
1213
1214     if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
1215         ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
1216     }
1217
1218     cm_ResetACLCache(cellp, userp);
1219
1220   done:
1221     SecureZeroMemory(sessionKey, sizeof(sessionKey));
1222
1223     if (release_userp)
1224         cm_ReleaseUser(userp);
1225
1226     if (uname)
1227         free(uname);
1228
1229     if (smbname)
1230         free(smbname);
1231
1232     return code;
1233 }
1234
1235
1236
1237 afs_int32
1238 smb_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1239 {
1240     smb_user_t *uidp = ioctlp->uidp;
1241
1242     if (uidp && uidp->unp) {
1243         int cch;
1244
1245         cch = cm_ClientStringToUtf8(uidp->unp->name,
1246                                     -1,
1247                                     ioctlp->ioctl.outDatap,
1248                                     (int)(SMB_IOCTL_MAXDATA -
1249                                      (ioctlp->ioctl.outDatap - ioctlp->ioctl.outAllocp))
1250                                     / sizeof(cm_utf8char_t));
1251
1252         ioctlp->ioctl.outDatap += cch * sizeof(cm_utf8char_t);
1253     }
1254
1255     return 0;
1256 }
1257
1258 afs_int32
1259 smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1260 {
1261     cm_scache_t *scp;
1262     afs_int32 code;
1263     cm_req_t req;
1264     cm_ioctlQueryOptions_t *optionsp;
1265     afs_uint32 flags = 0;
1266
1267     smb_InitReq(&req);
1268
1269     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1270     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1271         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1272
1273     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1274         cm_fid_t fid;
1275         cm_SkipIoctlPath(&ioctlp->ioctl);
1276         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1277                   optionsp->fid.vnode, optionsp->fid.unique);
1278         code = cm_GetSCache(&fid, &scp, userp, &req);
1279     } else {
1280         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1281     }
1282
1283     if (code)
1284         return code;
1285
1286     code = cm_IoctlGetACL(&ioctlp->ioctl, userp, scp, &req);
1287
1288     cm_ReleaseSCache(scp);
1289     return code;
1290 }
1291
1292 afs_int32
1293 smb_IoctlSetACL(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1294 {
1295     cm_scache_t *scp;
1296     afs_int32 code;
1297     cm_req_t req;
1298     afs_uint32 flags = 0;
1299
1300     smb_InitReq(&req);
1301
1302     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1303     if (code)
1304         return code;
1305
1306     code = cm_IoctlSetACL(&ioctlp->ioctl, userp, scp, &req);
1307
1308     cm_ReleaseSCache(scp);
1309     return code;
1310 }
1311
1312 afs_int32
1313 smb_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1314 {
1315     afs_int32 code;
1316     cm_scache_t *scp;
1317     cm_req_t req;
1318     cm_ioctlQueryOptions_t *optionsp;
1319     afs_uint32 flags = 0;
1320
1321     smb_InitReq(&req);
1322
1323     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1324     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1325         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1326
1327     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1328         cm_fid_t fid;
1329         cm_SkipIoctlPath(&ioctlp->ioctl);
1330         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1331                   optionsp->fid.vnode, optionsp->fid.unique);
1332         code = cm_GetSCache(&fid, &scp, userp, &req);
1333     } else {
1334         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1335     }
1336     if (code)
1337         return code;
1338
1339     code = cm_IoctlGetFileCellName(&ioctlp->ioctl, userp, scp, &req);
1340
1341     cm_ReleaseSCache(scp);
1342
1343     return code;
1344 }
1345
1346 afs_int32
1347 smb_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1348 {
1349     cm_req_t req;
1350
1351     smb_InitReq(&req);
1352
1353     cm_SkipIoctlPath(&ioctlp->ioctl);   /* we don't care about the path */
1354
1355     return cm_IoctlFlushAllVolumes(&ioctlp->ioctl, userp, &req);
1356 }
1357
1358 afs_int32
1359 smb_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1360 {
1361     afs_int32 code;
1362     cm_scache_t *scp;
1363     cm_req_t req;
1364     cm_ioctlQueryOptions_t *optionsp;
1365     afs_uint32 flags = 0;
1366
1367     smb_InitReq(&req);
1368
1369     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1370     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1371         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1372
1373     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1374         cm_fid_t fid;
1375         cm_SkipIoctlPath(&ioctlp->ioctl);
1376         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1377                   optionsp->fid.vnode, optionsp->fid.unique);
1378         code = cm_GetSCache(&fid, &scp, userp, &req);
1379     } else {
1380         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1381     }
1382     if (code)
1383         return code;
1384
1385     code = cm_IoctlFlushVolume(&ioctlp->ioctl, userp, scp, &req);
1386
1387     cm_ReleaseSCache(scp);
1388
1389     return code;
1390 }
1391
1392 afs_int32
1393 smb_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1394 {
1395     afs_int32 code;
1396     cm_scache_t *scp;
1397     cm_req_t req;
1398     cm_ioctlQueryOptions_t *optionsp;
1399     afs_uint32 flags = 0;
1400
1401     smb_InitReq(&req);
1402
1403     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1404     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1405         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1406
1407     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1408         cm_fid_t fid;
1409         cm_SkipIoctlPath(&ioctlp->ioctl);
1410         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1411                   optionsp->fid.vnode, optionsp->fid.unique);
1412         code = cm_GetSCache(&fid, &scp, userp, &req);
1413     } else {
1414         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1415     }
1416     if (code)
1417         return code;
1418
1419     code = cm_IoctlFlushFile(&ioctlp->ioctl, userp, scp, &req);
1420
1421     cm_ReleaseSCache(scp);
1422     return code;
1423 }
1424
1425 afs_int32
1426 smb_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1427 {
1428     afs_int32 code;
1429     cm_scache_t *scp;
1430     cm_req_t req;
1431
1432     smb_InitReq(&req);
1433
1434     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, 0);
1435     if (code) return code;
1436
1437     code = cm_IoctlSetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1438     cm_ReleaseSCache(scp);
1439
1440     return code;
1441 }
1442
1443 afs_int32
1444 smb_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1445 {
1446     afs_int32 code;
1447     cm_scache_t *scp;
1448     cm_ioctlQueryOptions_t *optionsp;
1449     afs_uint32 flags = 0;
1450     cm_req_t req;
1451
1452     smb_InitReq(&req);
1453
1454     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1455     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1456         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1457
1458     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1459         cm_fid_t fid;
1460         cm_SkipIoctlPath(&ioctlp->ioctl);
1461         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1462                   optionsp->fid.vnode, optionsp->fid.unique);
1463         code = cm_GetSCache(&fid, &scp, userp, &req);
1464     } else {
1465         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1466     }
1467     if (code)
1468         return code;
1469
1470     code = cm_IoctlGetVolumeStatus(&ioctlp->ioctl, userp, scp, &req);
1471
1472     cm_ReleaseSCache(scp);
1473
1474     return code;
1475 }
1476
1477 afs_int32
1478 smb_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1479 {
1480     afs_int32 code;
1481     cm_scache_t *scp;
1482     cm_req_t req;
1483     cm_ioctlQueryOptions_t * optionsp;
1484     afs_uint32 flags = 0;
1485
1486     smb_InitReq(&req);
1487
1488     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1489     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1490         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1491
1492     code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1493     if (code)
1494         return code;
1495
1496     code = cm_IoctlGetFid(&ioctlp->ioctl, userp, scp, &req);
1497
1498     cm_ReleaseSCache(scp);
1499
1500     return code;
1501 }
1502
1503 afs_int32
1504 smb_IoctlGetFileType(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1505 {
1506     afs_int32 code;
1507     cm_scache_t *scp;
1508     cm_req_t req;
1509     cm_ioctlQueryOptions_t * optionsp;
1510     afs_uint32 flags = 0;
1511
1512     smb_InitReq(&req);
1513
1514     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1515     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1516         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1517
1518     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1519         cm_fid_t fid;
1520         cm_SkipIoctlPath(&ioctlp->ioctl);
1521         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1522                   optionsp->fid.vnode, optionsp->fid.unique);
1523         code = cm_GetSCache(&fid, &scp, userp, &req);
1524     } else {
1525         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1526     }
1527     if (code)
1528         return code;
1529
1530     code = cm_IoctlGetFileType(&ioctlp->ioctl, userp, scp, &req);
1531
1532     cm_ReleaseSCache(scp);
1533
1534     return code;
1535 }
1536
1537 afs_int32
1538 smb_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1539 {
1540     afs_int32 code;
1541     cm_scache_t *scp;
1542     cm_req_t req;
1543     cm_ioctlQueryOptions_t *optionsp;
1544     afs_uint32 flags = 0;
1545
1546     smb_InitReq(&req);
1547
1548     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1549     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1550         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1551
1552     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1553         cm_fid_t fid;
1554         cm_SkipIoctlPath(&ioctlp->ioctl);
1555         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1556                   optionsp->fid.vnode, optionsp->fid.unique);
1557         code = cm_GetSCache(&fid, &scp, userp, &req);
1558     } else {
1559         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1560     }
1561     if (code)
1562         return code;
1563
1564     code = cm_IoctlGetOwner(&ioctlp->ioctl, userp, scp, &req);
1565
1566     cm_ReleaseSCache(scp);
1567
1568     return code;
1569 }
1570
1571 afs_int32
1572 smb_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1573 {
1574     afs_int32 code;
1575     cm_scache_t *scp;
1576     cm_req_t req;
1577     cm_ioctlQueryOptions_t *optionsp;
1578     afs_uint32 flags = 0;
1579
1580     smb_InitReq(&req);
1581
1582     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1583     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1584         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1585
1586     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1587         cm_fid_t fid;
1588         cm_SkipIoctlPath(&ioctlp->ioctl);
1589         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1590                   optionsp->fid.vnode, optionsp->fid.unique);
1591         code = cm_GetSCache(&fid, &scp, userp, &req);
1592     } else {
1593         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1594     }
1595     if (code)
1596         return code;
1597
1598     code = cm_IoctlWhereIs(&ioctlp->ioctl, userp, scp, &req);
1599
1600     cm_ReleaseSCache(scp);
1601
1602     return code;
1603 }
1604
1605
1606 afs_int32
1607 smb_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1608 {
1609     afs_int32 code;
1610     cm_scache_t *dscp;
1611     cm_req_t req;
1612
1613     smb_InitReq(&req);
1614
1615     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1616     if (code)
1617         return code;
1618
1619     code = cm_IoctlStatMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1620
1621     cm_ReleaseSCache(dscp);
1622
1623     return code;
1624 }
1625
1626 afs_int32
1627 smb_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1628 {
1629     afs_int32 code;
1630     cm_scache_t *dscp;
1631     cm_req_t req;
1632
1633     smb_InitReq(&req);
1634
1635     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1636     if (code)
1637         return code;
1638
1639     code = cm_IoctlDeleteMountPoint(&ioctlp->ioctl, userp, dscp, &req);
1640
1641     cm_ReleaseSCache(dscp);
1642
1643     return code;
1644 }
1645
1646 afs_int32
1647 smb_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1648 {
1649     cm_SkipIoctlPath(&ioctlp->ioctl);   /* we don't care about the path */
1650
1651     return cm_IoctlCheckServers(&ioctlp->ioctl, userp);
1652 }
1653
1654 afs_int32
1655 smb_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1656 {
1657     /* we don't print anything superfluous, so we don't support the gag call */
1658     return CM_ERROR_INVAL;
1659 }
1660
1661 afs_int32
1662 smb_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1663 {
1664     cm_SkipIoctlPath(&ioctlp->ioctl);
1665
1666     return cm_IoctlCheckVolumes(&ioctlp->ioctl, userp);
1667 }
1668
1669 afs_int32 smb_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1670 {
1671     cm_SkipIoctlPath(&ioctlp->ioctl);
1672
1673     return cm_IoctlSetCacheSize(&ioctlp->ioctl, userp);
1674 }
1675
1676
1677 afs_int32
1678 smb_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1679 {
1680     cm_SkipIoctlPath(&ioctlp->ioctl);
1681
1682     return cm_IoctlTraceControl(&ioctlp->ioctl, userp);
1683 }
1684
1685 afs_int32
1686 smb_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1687 {
1688     cm_SkipIoctlPath(&ioctlp->ioctl);
1689
1690     return cm_IoctlGetCacheParms(&ioctlp->ioctl, userp);
1691 }
1692
1693 afs_int32
1694 smb_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1695 {
1696     cm_SkipIoctlPath(&ioctlp->ioctl);
1697
1698     return cm_IoctlGetCell(&ioctlp->ioctl, userp);
1699 }
1700
1701 afs_int32
1702 smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1703 {
1704     cm_SkipIoctlPath(&ioctlp->ioctl);
1705
1706     return cm_IoctlNewCell(&ioctlp->ioctl, userp);
1707 }
1708
1709 afs_int32
1710 smb_IoctlNewCell2(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1711 {
1712     cm_SkipIoctlPath(&ioctlp->ioctl);
1713
1714     return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
1715 }
1716
1717 afs_int32
1718 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags)
1719 {
1720     cm_SkipIoctlPath(&ioctlp->ioctl);
1721
1722     return cm_IoctlGetWsCell(&ioctlp->ioctl, userp);
1723 }
1724
1725 afs_int32
1726 smb_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1727 {
1728     cm_SkipIoctlPath(&ioctlp->ioctl);
1729
1730     return cm_IoctlSysName(&ioctlp->ioctl, userp);
1731 }
1732
1733 afs_int32
1734 smb_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1735 {
1736     cm_SkipIoctlPath(&ioctlp->ioctl);
1737
1738     return cm_IoctlGetCellStatus(&ioctlp->ioctl, userp);
1739 }
1740
1741 afs_int32
1742 smb_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1743 {
1744     cm_SkipIoctlPath(&ioctlp->ioctl);
1745
1746     return cm_IoctlSetCellStatus(&ioctlp->ioctl, userp);
1747 }
1748
1749 afs_int32
1750 smb_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1751 {
1752     cm_SkipIoctlPath(&ioctlp->ioctl);
1753
1754     return cm_IoctlSetSPrefs(&ioctlp->ioctl, userp);
1755 }
1756
1757 afs_int32
1758 smb_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1759 {
1760     cm_SkipIoctlPath(&ioctlp->ioctl);
1761
1762     return cm_IoctlGetSPrefs(&ioctlp->ioctl, userp);
1763 }
1764
1765 afs_int32
1766 smb_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1767 {
1768     /* we ignore default asynchrony since we only have one way
1769      * of doing this today.
1770      */
1771     return 0;
1772 }
1773
1774 afs_int32
1775 smb_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1776 {
1777     afs_int32 code;
1778     cm_scache_t *dscp;
1779     clientchar_t leaf[LEAF_SIZE];
1780     cm_req_t req;
1781
1782     smb_InitReq(&req);
1783
1784     code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1785     if (code)
1786         return code;
1787
1788     code = cm_IoctlCreateMountPoint(&ioctlp->ioctl, userp, dscp, &req, leaf);
1789
1790     cm_ReleaseSCache(dscp);
1791     return code;
1792 }
1793
1794 afs_int32
1795 smb_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1796 {
1797     afs_int32 code;
1798     cm_scache_t *dscp;
1799     clientchar_t leaf[LEAF_SIZE];
1800     cm_req_t req;
1801
1802     smb_InitReq(&req);
1803
1804     code = smb_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1805     if (code) return code;
1806
1807     code = cm_IoctlSymlink(&ioctlp->ioctl, userp, dscp, &req, leaf);
1808
1809     cm_ReleaseSCache(dscp);
1810
1811     return code;
1812 }
1813
1814 afs_int32
1815 smb_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1816 {
1817     afs_int32 code;
1818     cm_scache_t *dscp;
1819     cm_req_t req;
1820
1821     smb_InitReq(&req);
1822
1823     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1824     if (code) return code;
1825
1826     code = cm_IoctlListlink(&ioctlp->ioctl, userp, dscp, &req);
1827
1828     cm_ReleaseSCache(dscp);
1829     return code;
1830 }
1831
1832 afs_int32
1833 smb_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1834 {/*CHECK FOR VALID SYMLINK*/
1835     afs_int32 code;
1836     cm_scache_t *dscp;
1837     cm_req_t req;
1838
1839     smb_InitReq(&req);
1840
1841     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1842     if (code) return code;
1843
1844     code = cm_IoctlIslink(&ioctlp->ioctl, userp, dscp, &req);
1845
1846     cm_ReleaseSCache(dscp);
1847
1848     return code;
1849 }
1850
1851 afs_int32
1852 smb_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1853 {
1854     afs_int32 code;
1855     cm_scache_t *dscp;
1856     cm_req_t req;
1857
1858     smb_InitReq(&req);
1859
1860     code = smb_ParseIoctlPath(ioctlp, userp, &req, &dscp, 0);
1861     if (code) return code;
1862
1863     code = cm_IoctlDeletelink(&ioctlp->ioctl, userp, dscp, &req);
1864
1865     cm_ReleaseSCache(dscp);
1866
1867     return code;
1868 }
1869
1870 afs_int32
1871 smb_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1872 {
1873     cm_SkipIoctlPath(&ioctlp->ioctl);
1874
1875     return cm_IoctlGetTokenIter(&ioctlp->ioctl, userp);
1876 }
1877
1878 afs_int32
1879 smb_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1880 {
1881     cm_SkipIoctlPath(&ioctlp->ioctl);
1882
1883     return cm_IoctlGetToken(&ioctlp->ioctl, userp);
1884 }
1885
1886
1887 afs_int32
1888 smb_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1889 {
1890     cm_SkipIoctlPath(&ioctlp->ioctl);
1891
1892     return cm_IoctlDelToken(&ioctlp->ioctl, userp);
1893 }
1894
1895
1896 afs_int32
1897 smb_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1898 {
1899     cm_SkipIoctlPath(&ioctlp->ioctl);
1900
1901     return cm_IoctlDelAllToken(&ioctlp->ioctl, userp);
1902 }
1903
1904
1905 afs_int32
1906 smb_IoctlMakeSubmount(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1907 {
1908     cm_SkipIoctlPath(&ioctlp->ioctl);
1909
1910     return cm_IoctlMakeSubmount(&ioctlp->ioctl, userp);
1911 }
1912
1913 afs_int32
1914 smb_IoctlGetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1915 {
1916     cm_SkipIoctlPath(&ioctlp->ioctl);
1917
1918     return cm_IoctlGetRxkcrypt(&ioctlp->ioctl, userp);
1919 }
1920
1921 afs_int32
1922 smb_IoctlSetRxkcrypt(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1923 {
1924     cm_SkipIoctlPath(&ioctlp->ioctl);
1925
1926     return cm_IoctlSetRxkcrypt(&ioctlp->ioctl, userp);
1927 }
1928
1929 afs_int32
1930 smb_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1931 {
1932     cm_SkipIoctlPath(&ioctlp->ioctl);
1933
1934     return cm_IoctlRxStatProcess(&ioctlp->ioctl, userp);
1935 }
1936
1937
1938 afs_int32
1939 smb_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1940 {
1941     cm_SkipIoctlPath(&ioctlp->ioctl);
1942
1943     return cm_IoctlRxStatPeer(&ioctlp->ioctl, userp);
1944 }
1945
1946 afs_int32
1947 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1948 {
1949     cm_SkipIoctlPath(&ioctlp->ioctl);
1950
1951     return cm_IoctlUnicodeControl(&ioctlp->ioctl, userp);
1952 }
1953
1954 afs_int32
1955 smb_IoctlUUIDControl(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1956 {
1957     cm_SkipIoctlPath(&ioctlp->ioctl);
1958
1959     return cm_IoctlUUIDControl(&ioctlp->ioctl, userp);
1960 }
1961
1962
1963 afs_int32
1964 smb_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1965 {
1966     cm_SkipIoctlPath(&ioctlp->ioctl);
1967
1968     return cm_IoctlMemoryDump(&ioctlp->ioctl, userp);
1969 }
1970
1971 afs_int32
1972 smb_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
1973 {
1974     afs_int32 code;
1975     cm_scache_t *scp;
1976     cm_req_t req;
1977     cm_ioctlQueryOptions_t *optionsp;
1978     afs_uint32 flags = 0;
1979
1980     smb_InitReq(&req);
1981
1982     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
1983     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
1984         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
1985
1986     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
1987         cm_fid_t fid;
1988         cm_SkipIoctlPath(&ioctlp->ioctl);
1989         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
1990                   optionsp->fid.vnode, optionsp->fid.unique);
1991         code = cm_GetSCache(&fid, &scp, userp, &req);
1992     } else {
1993         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
1994     }
1995     if (code)
1996         return code;
1997
1998     code = cm_IoctlPathAvailability(&ioctlp->ioctl, userp, scp, &req);
1999     cm_ReleaseSCache(scp);
2000     return code;
2001 }
2002
2003 afs_int32
2004 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2005 {
2006     cm_req_t req;
2007
2008     smb_InitReq(&req);
2009
2010     cm_SkipIoctlPath(&ioctlp->ioctl);
2011
2012     return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
2013 }
2014
2015 /*
2016  * VIOC_SETOWNER
2017  *
2018  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2019  *
2020  */
2021 afs_int32
2022 smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2023 {
2024     afs_int32 code;
2025     cm_scache_t *scp;
2026     cm_req_t req;
2027     cm_ioctlQueryOptions_t *optionsp;
2028     afs_uint32 flags = 0;
2029
2030     smb_InitReq(&req);
2031
2032     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2033     if (optionsp) {
2034         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2035             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2036
2037         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2038             cm_fid_t fid;
2039             cm_SkipIoctlPath(&ioctlp->ioctl);
2040             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2041                        optionsp->fid.vnode, optionsp->fid.unique);
2042             code = cm_GetSCache(&fid, &scp, userp, &req);
2043         } else {
2044             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2045         }
2046         if (code)
2047             return code;
2048
2049         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2050     }
2051
2052     code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
2053
2054     cm_ReleaseSCache(scp);
2055
2056     return code;
2057 }
2058
2059 /*
2060  * VIOC_SETGROUP
2061  *
2062  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2063  *
2064  */
2065 afs_int32
2066 smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2067 {
2068     afs_int32 code;
2069     cm_scache_t *scp;
2070     cm_req_t req;
2071     cm_ioctlQueryOptions_t *optionsp;
2072     afs_uint32 flags = 0;
2073
2074     smb_InitReq(&req);
2075
2076     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2077     if (optionsp) {
2078         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2079             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2080
2081         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2082             cm_fid_t fid;
2083             cm_SkipIoctlPath(&ioctlp->ioctl);
2084             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2085                        optionsp->fid.vnode, optionsp->fid.unique);
2086             code = cm_GetSCache(&fid, &scp, userp, &req);
2087         } else {
2088             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2089         }
2090         if (code)
2091             return code;
2092
2093         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2094     }
2095
2096     code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
2097
2098     cm_ReleaseSCache(scp);
2099
2100     return code;
2101 }
2102
2103
2104 afs_int32
2105 smb_IoctlGetUnixMode(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2106 {
2107     afs_int32 code;
2108     cm_scache_t *scp;
2109     cm_req_t req;
2110     cm_ioctlQueryOptions_t *optionsp;
2111     afs_uint32 flags = 0;
2112
2113     smb_InitReq(&req);
2114
2115     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2116     if (optionsp && CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2117         flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2118
2119     if (optionsp && CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2120         cm_fid_t fid;
2121         cm_SkipIoctlPath(&ioctlp->ioctl);
2122         cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2123                   optionsp->fid.vnode, optionsp->fid.unique);
2124         code = cm_GetSCache(&fid, &scp, userp, &req);
2125     } else {
2126         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2127     }
2128     if (code)
2129         return code;
2130
2131     code = cm_IoctlGetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2132
2133     cm_ReleaseSCache(scp);
2134
2135     return code;
2136 }
2137
2138
2139 /*
2140  * VIOC_SETUNIXMODE
2141  *
2142  * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
2143  */
2144 afs_int32
2145 smb_IoctlSetUnixMode(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags)
2146 {
2147     afs_int32 code;
2148     cm_scache_t *scp;
2149     cm_req_t req;
2150     cm_ioctlQueryOptions_t *optionsp;
2151     afs_uint32 flags = 0;
2152
2153     smb_InitReq(&req);
2154
2155     optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
2156     if (optionsp) {
2157         if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
2158             flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
2159
2160         if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
2161             cm_fid_t fid;
2162             cm_SkipIoctlPath(&ioctlp->ioctl);
2163             cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
2164                        optionsp->fid.vnode, optionsp->fid.unique);
2165             code = cm_GetSCache(&fid, &scp, userp, &req);
2166         } else {
2167             code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
2168         }
2169         if (code)
2170             return code;
2171
2172         cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
2173     }
2174
2175     code = cm_IoctlSetUnixMode(&ioctlp->ioctl, userp, scp, &req);
2176
2177     cm_ReleaseSCache(scp);
2178
2179     return code;
2180 }
2181