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