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