1 /* $OpenBSD: print-smb.c,v 1.3 2007/10/07 16:41:05 deraadt Exp $ */ 2 3 /* 4 Copyright (C) Andrew Tridgell 1995-1999 5 6 This software may be distributed either under the terms of the 7 BSD-style license that accompanies tcpdump or the GNU GPL version 2 8 or later */ 9 10 #ifdef HAVE_CONFIG_H 11 #include "config.h" 12 #endif 13 14 #ifndef lint 15 static const char rcsid[] = 16 "@(#) $Id: print-smb.c,v 1.3 2007/10/07 16:41:05 deraadt Exp $"; 17 #endif 18 19 #include <stdio.h> 20 #include <string.h> 21 #include <sys/types.h> 22 23 #include "interface.h" 24 #include "smb.h" 25 26 static int request=0; 27 28 const uchar *startbuf=NULL; 29 30 struct smbdescript 31 { 32 char *req_f1; 33 char *req_f2; 34 char *rep_f1; 35 char *rep_f2; 36 void (*fn)(); /* sometimes (u_char *, u_char *, u_char *, u_char *) 37 and sometimes (u_char *, u_char *, int, int) */ 38 }; 39 40 struct smbfns 41 { 42 int id; 43 char *name; 44 int flags; 45 struct smbdescript descript; 46 }; 47 48 #define DEFDESCRIPT {NULL,NULL,NULL,NULL,NULL} 49 50 #define FLG_CHAIN (1<<0) 51 52 static struct smbfns *smbfind(int id,struct smbfns *list) 53 { 54 int sindex; 55 56 for (sindex=0;list[sindex].name;sindex++) 57 if (list[sindex].id == id) return(&list[sindex]); 58 59 return(&list[0]); 60 } 61 62 static void trans2_findfirst(uchar *param,uchar *data,int pcnt,int dcnt) 63 { 64 char *fmt; 65 66 if (request) { 67 fmt = "attr [A] searchcnt [d] flags [w] level [dP5] file [S] "; 68 } else { 69 fmt = "handle [w] cnt [d] eos [w] eoffset [d] lastnameofs [w] "; 70 } 71 72 fdata(param,fmt,param+pcnt); 73 } 74 75 static void trans2_qfsinfo(uchar *param,uchar *data,int pcnt,int dcnt) 76 { 77 static int level=0; 78 char *fmt=""; 79 80 if (request) { 81 level = SVAL(param,0); 82 fmt = "info level [d] "; 83 fdata(param,fmt,param+pcnt); 84 } else { 85 switch (level) { 86 case 1: 87 fmt = "fsid [W] sectorunit [D] unit [D] avail [D] sectorsize [d] "; 88 break; 89 case 2: 90 fmt = "creat [T2] volnamelen [B] volume [s12] "; 91 break; 92 case 0x105: 93 fmt = "capabilities [W] maxfilelen [D] volnamelen [D] volume [S] "; 94 break; 95 default: 96 fmt = "unknown level "; 97 } 98 fdata(data,fmt,data+dcnt); 99 } 100 } 101 102 struct smbfns trans2_fns[] = { 103 {0,"TRANSACT2_OPEN",0, 104 {"flags2 [w] mode [w] searchattr [A] attr [A] time [T2] ofun [w] size [D] res [w,w,w,w,w] path [S]",NULL, 105 "handle [d] attr [A] time [T2] size [D] access [w] type [w] state [w] action [w] inode [W] offerr [d] |ealen [d] ",NULL,NULL}}, 106 107 {1,"TRANSACT2_FINDFIRST",0, 108 {NULL,NULL,NULL,NULL,trans2_findfirst}}, 109 110 {2,"TRANSACT2_FINDNEXT",0,DEFDESCRIPT}, 111 112 {3,"TRANSACT2_QFSINFO",0, 113 {NULL,NULL,NULL,NULL,trans2_qfsinfo}}, 114 115 {4,"TRANSACT2_SETFSINFO",0,DEFDESCRIPT}, 116 {5,"TRANSACT2_QPATHINFO",0,DEFDESCRIPT}, 117 {6,"TRANSACT2_SETPATHINFO",0,DEFDESCRIPT}, 118 {7,"TRANSACT2_QFILEINFO",0,DEFDESCRIPT}, 119 {8,"TRANSACT2_SETFILEINFO",0,DEFDESCRIPT}, 120 {9,"TRANSACT2_FSCTL",0,DEFDESCRIPT}, 121 {10,"TRANSACT2_IOCTL",0,DEFDESCRIPT}, 122 {11,"TRANSACT2_FINDNOTIFYFIRST",0,DEFDESCRIPT}, 123 {12,"TRANSACT2_FINDNOTIFYNEXT",0,DEFDESCRIPT}, 124 {13,"TRANSACT2_MKDIR",0,DEFDESCRIPT}, 125 {-1,NULL,0,DEFDESCRIPT}}; 126 127 128 static void print_trans2(uchar *words,uchar *dat,uchar *buf,uchar *maxbuf) 129 { 130 static struct smbfns *fn = &trans2_fns[0]; 131 uchar *data,*param; 132 uchar *f1=NULL,*f2=NULL; 133 int pcnt,dcnt; 134 135 if (request) { 136 fn = smbfind(SVAL(words+1,14*2),trans2_fns); 137 data = buf+SVAL(words+1,12*2); 138 param = buf+SVAL(words+1,10*2); 139 pcnt = SVAL(words+1,9*2); 140 dcnt = SVAL(words+1,11*2); 141 } else { 142 data = buf+SVAL(words+1,7*2); 143 param = buf+SVAL(words+1,4*2); 144 pcnt = SVAL(words+1,3*2); 145 dcnt = SVAL(words+1,6*2); 146 } 147 148 printf("%s paramlen %d datalen %d ", 149 fn->name,pcnt,dcnt); 150 151 if (request) { 152 if (CVAL(words,0) == 8) { 153 fdata(words+1,"trans2secondary totparam [d] totdata [d] paramcnt [d] paramoff [d] paramdisp [d] datacnt [d] dataoff [d] datadisp [d] handle [d] ",maxbuf); 154 return; 155 } else { 156 fdata(words+1,"totparam [d] totdata [d] maxparam [d] maxdata [d] maxsetup [d] flags [w] timeout [D] res1 [w] paramcnt [d] paramoff [d] datacnt=[d] dataoff [d] setupcnt [d] ",words+1+14*2); 157 fdata(data+1,"transname [S] %",maxbuf); 158 } 159 f1 = fn->descript.req_f1; 160 f2 = fn->descript.req_f2; 161 } else { 162 if (CVAL(words,0) == 0) { 163 printf("trans2interim "); 164 return; 165 } else { 166 fdata(words+1,"totparam [d] totdata [d] res1 [w] paramcnt [d] paramoff [d] paramdisp [d] datacnt [d] dataoff [d] datadisp [d] setupcnt [d] ",words+1+10*2); 167 } 168 f1 = fn->descript.rep_f1; 169 f2 = fn->descript.rep_f2; 170 } 171 172 if (fn->descript.fn) { 173 fn->descript.fn(param,data,pcnt,dcnt); 174 } else { 175 fdata(param,f1?f1:(uchar*)"params ",param+pcnt); 176 fdata(data,f2?f2:(uchar*)"data ",data+dcnt); 177 } 178 } 179 180 181 static void print_browse(uchar *param,int paramlen,const uchar *data,int datalen) 182 { 183 const uchar *maxbuf = data + datalen; 184 int command = CVAL(data,0); 185 186 fdata(param,"browse |param ",param+paramlen); 187 188 switch (command) { 189 case 0xF: 190 data = fdata(data,"browse [B] (LocalMasterAnnouncement) updatecnt [w] res1 [B] announceintv [d] name [n2] version [B].[B] servertype [W] electionversion [w] browserconst [w] ",maxbuf); 191 break; 192 193 case 0x1: 194 data = fdata(data,"browse [B] (HostAnnouncement) updatecnt [w] res1 [B] announceintv [d] name [n2] version [B].[B] servertype [W] electionversion [w] browserconst [w] ",maxbuf); 195 break; 196 197 case 0x2: 198 data = fdata(data,"browse [B] (AnnouncementRequest) flags [B] replysysname [S] ",maxbuf); 199 break; 200 201 case 0xc: 202 data = fdata(data,"browse [B] (WorkgroupAnnouncement) updatecnt [w] res1 [B] announceintv [d] name [n2] version [B].[B] servertype [W] commentptr [W] servername [S] ",maxbuf); 203 break; 204 205 case 0x8: 206 data = fdata(data,"browse [B] (ElectionFrame) electionversion [B] ossummary [W] uptime [(W,W)] servername [S] ",maxbuf); 207 break; 208 209 case 0xb: 210 data = fdata(data,"browse [B] (BecomeBackupBrowser) name [S] ",maxbuf); 211 break; 212 213 case 0x9: 214 data = fdata(data,"browse [B] (GetBackupList) listcnt? [B] token? [B] ",maxbuf); 215 break; 216 217 case 0xa: 218 data = fdata(data,"browse [B] (BackupListResponse) servercnt? [B] token? [B] *name [S] ",maxbuf); 219 break; 220 221 case 0xd: 222 data = fdata(data,"browse [B] (MasterAnnouncement) master-name [S] ",maxbuf); 223 break; 224 225 case 0xe: 226 data = fdata(data,"browse [B] (ResetBrowser) options [B] ",maxbuf); 227 break; 228 229 default: 230 data = fdata(data,"browse unknown-frame",maxbuf); 231 break; 232 } 233 } 234 235 236 static void print_ipc(uchar *param,int paramlen,uchar *data,int datalen) 237 { 238 if (paramlen) 239 fdata(param,"cmd [w] str1 [S] str2 [S] ",param+paramlen); 240 if (datalen) 241 fdata(data,"IPC ",data+datalen); 242 } 243 244 245 static void print_trans(uchar *words,uchar *data1,uchar *buf,uchar *maxbuf) 246 { 247 uchar *f1,*f2,*f3,*f4; 248 uchar *data,*param; 249 int datalen,paramlen; 250 251 if (request) { 252 paramlen = SVAL(words+1,9*2); 253 param = buf + SVAL(words+1,10*2); 254 datalen = SVAL(words+1,11*2); 255 data = buf + SVAL(words+1,12*2); 256 f1 = " totparamcnt [d] totdatacnt [d] maxparmcnt [d] maxdatacnt [d] maxscnt [d] transflags [w] res [w] [w] [w] paramcnt [d] paramoff [d] datacnt [d] dataoff [d] sucnt [d] "; 257 f2 = "|[S] "; 258 f3 = "|param "; 259 f4 = "|data "; 260 } else { 261 paramlen = SVAL(words+1,3*2); 262 param = buf + SVAL(words+1,4*2); 263 datalen = SVAL(words+1,6*2); 264 data = buf + SVAL(words+1,7*2); 265 f1 = "totparamcnt [d] totdatacnt [d] res1 [d] paramcnt [d] paramoff [d] res2 [d] datacnt [d] dataoff [d] res3 [d] Lsetup [d] "; 266 f2 = "|unk "; 267 f3 = "|param "; 268 f4 = "|data "; 269 } 270 271 fdata(words+1,f1,MIN(words+1+2*CVAL(words,0),maxbuf)); 272 fdata(data1+2,f2,maxbuf - (paramlen + datalen)); 273 274 if (!strcmp(data1+2,"\\MAILSLOT\\BROWSE")) { 275 print_browse(param,paramlen,data,datalen); 276 return; 277 } 278 279 if (!strcmp(data1+2,"\\PIPE\\LANMAN")) { 280 print_ipc(param,paramlen,data,datalen); 281 return; 282 } 283 284 if (paramlen) fdata(param,f3,MIN(param+paramlen,maxbuf)); 285 if (datalen) fdata(data,f4,MIN(data+datalen,maxbuf)); 286 } 287 288 289 290 static void print_negprot(uchar *words,uchar *data,uchar *buf,uchar *maxbuf) 291 { 292 uchar *f1=NULL,*f2=NULL; 293 294 if (request) { 295 f2 = "*|dialect [Z] "; 296 } else { 297 if (CVAL(words,0) == 1) { 298 f1 = "core-proto dialect index [d]"; 299 } else if (CVAL(words,0) == 17) { 300 f1 = "NT1-proto dialect index [d] secmode [B] maxmux [d] numvcs [d] maxbuf [D] rawsize [D] sesskey [W] capabilities [W] servertime [T3] tz [d] cryptkey "; 301 } else if (CVAL(words,0) == 13) { 302 f1 = "coreplus/lanman1/lanman2-proto dialect index [d] secmode [w] maxxmit [d] maxmux [d] maxvcs [d] blkmode [w] sesskey [W] servertime [T1] tz [d] res [W] cryptkey "; 303 } 304 } 305 306 if (f1) 307 fdata(words+1,f1,MIN(words + 1 + CVAL(words,0)*2,maxbuf)); 308 309 if (f2) 310 fdata(data+2,f2,MIN(data + 2 + SVAL(data,0),maxbuf)); 311 } 312 313 static void print_sesssetup(uchar *words,uchar *data,uchar *buf,uchar *maxbuf) 314 { 315 int wcnt = CVAL(words,0); 316 uchar *f1=NULL,*f2=NULL; 317 318 if (request) { 319 if (wcnt==10) { 320 f1 = "com2 [w] off2 [d] bufsize [d] maxmpx [d] vcnum [d] sesskey [W] passlen [d] cryptlen [d] cryptoff [d] pass&name "; 321 } else { 322 f1 = "com2 [B] res1 [B] off2 [d] maxbuf [d] maxmpx [d] vcnum [d] sesskey [W] case-insensitive-passlen [d] case-sensitive-passlen [d] res [W] capabilities [W] pass1&pass2&account&domain&os&lanman "; 323 } 324 } else { 325 if (CVAL(words,0) == 3) { 326 f1 = "com2 [w] off2 [d] action [w] "; 327 } else if (CVAL(words,0) == 13) { 328 f1 = "com2 [B] res [B] off2 [d] action [w] "; 329 f2 = "native-os [S] nativelanman [S] primarydomain [S] "; 330 } 331 } 332 333 if (f1) 334 fdata(words+1,f1,MIN(words + 1 + CVAL(words,0)*2,maxbuf)); 335 336 if (f2) 337 fdata(data+2,f2,MIN(data + 2 + SVAL(data,0),maxbuf)); 338 } 339 340 341 static struct smbfns smb_fns[] = 342 { 343 {-1,"SMBunknown",0,DEFDESCRIPT}, 344 345 {SMBtcon,"SMBtcon",0, 346 {NULL,"path [Z] pass [Z] dev [Z] ", "xmitmax [d] treeid [d] ",NULL, NULL}}, 347 348 349 {SMBtdis,"SMBtdis",0,DEFDESCRIPT}, 350 {SMBexit,"SMBexit",0,DEFDESCRIPT}, 351 {SMBioctl,"SMBioctl",0,DEFDESCRIPT}, 352 353 {SMBecho,"SMBecho",0, 354 {"reverbcount [d] ",NULL, "seqnum [d] ",NULL, NULL}}, 355 356 {SMBulogoffX, "SMBulogoffX",FLG_CHAIN,DEFDESCRIPT}, 357 358 {SMBgetatr,"SMBgetatr",0, {NULL,"path [Z] ", 359 "attr [A] time [T2] size [D] res ([w,w,w,w,w]) ",NULL, NULL}}, 360 361 {SMBsetatr,"SMBsetatr",0, 362 {"attr [A] time [T2] res ([w,w,w,w,w]) ","path [Z] ", NULL,NULL,NULL}}, 363 364 {SMBchkpth,"SMBchkpth",0, {NULL,"path [Z] ",NULL,NULL,NULL}}, 365 366 {SMBsearch,"SMBsearch",0, 367 {"cnt [d] attr [A] ","path [Z] blktype [B] blklen [d] |res1 [B] mask [s11] srv1 [B] dirindex [d] srv2 [w] res2 [W] ", 368 "cnt [d] ","blktype [B] blklen [d] * res1 [B] mask [s11] srv1 [B] dirindex [d] srv2 [w] res2 [W] attr [a] time [T1] size [D] name [s13] ",NULL}}, 369 370 {SMBopen,"SMBopen",0, {"mode [w] attr [A] ","path [Z] ", "handle [d] oattr [A] time [T2] size [D] access [w] ",NULL, NULL}}, 371 372 {SMBcreate,"SMBcreate",0, {"attr [A] time [T2]","path [Z] ", "handle [d]",NULL, NULL}}, 373 374 {SMBmknew,"SMBmknew",0, {"attr [A] time [T2]","path [Z] ", "handle [d] ",NULL, NULL}}, 375 376 {SMBunlink,"SMBunlink",0, {"attr [A] ","path [Z] ",NULL,NULL,NULL}}, 377 378 {SMBread,"SMBread",0, {"handle [d] bytecnt [d] offset [D] cntleft [d] ",NULL, "cnt [d] res ([w,w,w,w]) ",NULL,NULL}}, 379 380 {SMBwrite,"SMBwrite",0, {"handle [d] bytecnt [d] offset [D] cntleft [d] ",NULL, "cnt [d] ",NULL,NULL}}, 381 382 {SMBclose,"SMBclose",0, {"handle [d] time [T2]",NULL,NULL,NULL,NULL}}, 383 384 {SMBmkdir,"SMBmkdir",0, {NULL,"path [Z] ",NULL,NULL,NULL}}, 385 386 {SMBrmdir,"SMBrmdir",0, {NULL,"path [Z] ",NULL,NULL,NULL}}, 387 388 {SMBdskattr,"SMBdskattr",0, {NULL,NULL, "totalunits [d] blks/unit [d] blksize [d] freeunits [d] media [w] ", NULL,NULL}}, 389 390 {SMBmv,"SMBmv",0, {"attr [A] ","oldpath [Z] newpath [Z] ",NULL,NULL,NULL}}, 391 392 /* this is a Pathworks specific call, allowing the 393 changing of the root path */ 394 {pSETDIR,"SMBsetdir",0, {NULL,"path [Z] ",NULL,NULL,NULL}}, 395 396 {SMBlseek,"SMBlseek",0, {"handle [d] mode [w] offset [D] ","offset [D] ",NULL,NULL}}, 397 398 {SMBflush,"SMBflush",0, {"handle [d] ",NULL,NULL,NULL,NULL}}, 399 400 {SMBsplopen,"SMBsplopen",0, {"setuplen [d] mode [w] ","ident [Z] ","handle [d] ",NULL,NULL}}, 401 402 {SMBsplclose,"SMBsplclose",0, {"handle [d] ",NULL,NULL,NULL,NULL}}, 403 404 {SMBsplretq,"SMBsplretq",0, {"maxcnt [d] startindex [d] ",NULL, "cnt [d] index [d] ", "*time [T2] status [B] jobid [d] size [D] res [B] name [s16] ", NULL}}, 405 406 {SMBsplwr,"SMBsplwr",0, {"handle [d] ",NULL,NULL,NULL,NULL}}, 407 408 {SMBlock,"SMBlock",0, {"handle [d] count [D] offset [D] ",NULL,NULL,NULL,NULL}}, 409 410 {SMBunlock,"SMBunlock",0, {"handle [d] count [D] offset [D] ",NULL,NULL,NULL,NULL}}, 411 412 /* CORE+ PROTOCOL FOLLOWS */ 413 414 {SMBreadbraw,"SMBreadbraw",0, {"handle [d] offset [D] maxcnt [d] mincnt [d] timeout [D] res [d] ", NULL,NULL,NULL,NULL}}, 415 416 {SMBwritebraw,"SMBwritebraw",0, {"handle [d] totalcnt [d] res [w] offset [D] timeout [D] wmode [w] res2 [W] |datasize [d] dataoff [d] ", NULL,"write-raw-ack",NULL,NULL}}, 417 418 {SMBwritec,"SMBwritec",0, {NULL,NULL,"count [d] ",NULL,NULL}}, 419 420 {SMBwriteclose,"SMBwriteclose",0, {"handle [d] count [d] offset [D] time [T2] res ([w,w,w,w,w,w])",NULL, "count [d] ",NULL,NULL}}, 421 422 {SMBlockread,"SMBlockread",0, {"handle [d] bytecnt [d] offset [D] cntleft [d] ",NULL, "count [d] res ([w,w,w,w]) ",NULL,NULL}}, 423 424 {SMBwriteunlock,"SMBwriteunlock",0, {"handle [d] bytecnt [d] offset [D] cntleft [d] ",NULL, "count [d] ",NULL,NULL}}, 425 426 {SMBreadBmpx,"SMBreadBmpx",0, {"handle [d] offset [D] maxcnt [d] mincnt [d] timeout [D] res [w] ", NULL, "offset [D] totcnt [d] remain [d] res ([w,w]) datasize [d] dataoff [d] ", NULL,NULL}}, 427 428 {SMBwriteBmpx,"SMBwriteBmpx",0, {"handle [d] totcnt [d] res [w] offset [D] timeout [D] wmode [w] res2 [W] datasize [d] dataoff [d] ",NULL, "remain [d] ",NULL,NULL}}, 429 430 {SMBwriteBs,"SMBwriteBs",0, {"handle [d] totcnt [d] offset [D] res [W] datasize [d] dataoff [d] ",NULL, "count [d] ",NULL,NULL}}, 431 432 {SMBsetattrE,"SMBsetattrE",0, {"handle [d] ctime [T2] atime [T2] mtime [T2]",NULL, NULL,NULL,NULL}}, 433 434 {SMBgetattrE,"SMBgetattrE",0, {"handle [d] ",NULL, "ctime [T2] atime [T2] mtime [T2] size [D] allocsize [D] attr [A] ",NULL,NULL}}, 435 436 {SMBtranss,"SMBtranss",0,DEFDESCRIPT}, 437 {SMBioctls,"SMBioctls",0,DEFDESCRIPT}, 438 439 {SMBcopy,"SMBcopy",0, {"treeid2 [d] ofun [w] flags [w] ","path [S] newpath [S] ", "copycnt [d] ","|errstr [S] ",NULL}}, 440 441 {SMBmove,"SMBmove",0, {"treeid2 [d] ofun [w] flags [w] ","path [S] newpath [S] ", "movecnt [d] ","|errstr [S] ",NULL}}, 442 443 {SMBopenX,"SMBopenX",FLG_CHAIN, {"com2 [w] off2 [d] flags [w] mode [w] searchattr [A] attr [A] time [T2] ofun [w] size [D] timeout [D] res [W] ","path [S] ", "com2 [w] off2 [d] handle [d] attr [A] time [T2] size [D] access [w] type [w] state [w] action [w] fileid [W] res [w] ",NULL,NULL}}, 444 445 {SMBreadX,"SMBreadX",FLG_CHAIN, {"com2 [w] off2 [d] handle [d] offset [D] maxcnt [d] mincnt [d] timeout [D] cntleft [d] ",NULL, "com2 [w] off2 [d] remain [d] res [W] datasize [d] dataoff [d] res ([w,w,w,w]) ",NULL,NULL}}, 446 447 {SMBwriteX,"SMBwriteX",FLG_CHAIN, {"com2 [w] off2 [d] handle [d] offset [D] timeout [D] wmode [w] cntleft [d] res [w] datasize [d] dataoff [d] ",NULL, "com2 [w] off2 [d] count [d] remain [d] res [W] ",NULL,NULL}}, 448 449 {SMBlockingX,"SMBlockingX",FLG_CHAIN, {"com2 [w] off2 [d] handle [d] locktype [w] timeout [D] unlockcnt [d] lockcnt [d] ", "*process [d] offset [D] len [D] ", "com2 [w] off2 [d] "}}, 450 451 {SMBffirst,"SMBffirst",0, {"count [d] attr [A] ","path [Z] blktype [B] blklen [d] |res1 [B] mask [s11] srv2 [B] dirindex [d] srv2 [w] ", "count [d] ","blktype [B] blklen [d] * res1 [B] mask [s11] srv1 [B] dirindex [d] srv2 [w] res2 [W] attr [a] time [T1] size [D] name [s13] ",NULL}}, 452 453 {SMBfunique,"SMBfunique",0, {"count [d] attr [A] ","path [Z] blktype [B] blklen [d] |res1 [B] mask [s11] srv1 [B] dirindex [d] srv2 [w] ", "count [d] ","blktype [B] blklen [d] * res1 [B] mask [s11] srv1 [B] dirindex [d] srv2 [w] res2 [W] attr [a] time [T1] size [D] name [s13] ",NULL}}, 454 455 {SMBfclose,"SMBfclose",0, {"count [d] attr [A] ","path [Z] blktype [B] blklen [d] |res1 [B] mask [s11] srv1 [B] dirindex [d] srv2 [w] ", "count [d] ","blktype [B] blklen [d] * res1 [B] mask [s11] srv1 [B] dirindex [d] srv2 [w] res2 [W] attr [a] time [T1] size [D] name [s13] ",NULL}}, 456 457 {SMBfindnclose, "SMBfindnclose", 0, {"handle [d] ",NULL,NULL,NULL,NULL}}, 458 459 {SMBfindclose, "SMBfindclose", 0, {"handle [d] ",NULL,NULL,NULL,NULL}}, 460 461 {SMBsends,"SMBsends",0, {NULL,"src [Z] dst [Z] ",NULL,NULL,NULL}}, 462 463 {SMBsendstrt,"SMBsendstrt",0, {NULL,"src [Z] dst [Z] ","groupid [d] ",NULL,NULL}}, 464 465 {SMBsendend,"SMBsendend",0, {"groupid [d] ",NULL,NULL,NULL,NULL}}, 466 467 {SMBsendtxt,"SMBsendtxt",0, {"groupid [d] ",NULL,NULL,NULL,NULL}}, 468 469 {SMBsendb,"SMBsendb",0, {NULL,"src [Z] dst [Z] ",NULL,NULL,NULL}}, 470 471 {SMBfwdname,"SMBfwdname",0,DEFDESCRIPT}, 472 {SMBcancelf,"SMBcancelf",0,DEFDESCRIPT}, 473 {SMBgetmac,"SMBgetmac",0,DEFDESCRIPT}, 474 475 {SMBnegprot,"SMBnegprot",0, {NULL,NULL,NULL,NULL,print_negprot}}, 476 477 {SMBsesssetupX,"SMBsesssetupX",FLG_CHAIN,{NULL,NULL,NULL,NULL,print_sesssetup}}, 478 479 {SMBtconX,"SMBtconX",FLG_CHAIN, {"com2 [w] off2 [d] flags [w] passlen [d] passwd&path&dev ",NULL, "com2 [w] off2 [d] ","servicetype [S] ",NULL}}, 480 481 {SMBtrans2, "SMBtrans2",0,{NULL,NULL,NULL,NULL,print_trans2}}, 482 483 {SMBtranss2, "SMBtranss2", 0,DEFDESCRIPT}, 484 {SMBctemp,"SMBctemp",0,DEFDESCRIPT}, 485 {SMBreadBs,"SMBreadBs",0,DEFDESCRIPT}, 486 {SMBtrans,"SMBtrans",0,{NULL,NULL,NULL,NULL,print_trans}}, 487 488 {SMBnttrans,"SMBnttrans", 0, DEFDESCRIPT}, 489 {SMBnttranss,"SMBnttranss", 0, DEFDESCRIPT}, 490 491 {SMBntcreateX,"SMBntcreateX", FLG_CHAIN, {"com2 [w] off2 [d] res [b] namelen [d] flags [W] rootdirfid [D] accessmask [W] allocsize [L] extfileattr [W] shareaccess [W] createdisposition [W] createopts [W] impersonallevel [W] securityflags [b] ","path [S] ", "com2 [w] off2 [d] oplocklvl [b] fid [d] createaction [W] createtime [T3] lastaccesstime [T3] lastwritetime [T3] ctime [T3]extfileattr [W] allocsize [L] eof [L] filetype [w] devstate [w] dir [b] ", NULL}}, 492 493 {SMBntcancel,"SMBntcancel", 0, DEFDESCRIPT}, 494 495 {-1,NULL,0,DEFDESCRIPT}}; 496 497 498 /******************************************************************* 499 print a SMB message 500 ********************************************************************/ 501 static void print_smb(const uchar *buf, const uchar *maxbuf) 502 { 503 int command; 504 const uchar *words, *data; 505 struct smbfns *fn; 506 char *fmt_smbheader = 507 "[P4] cmd [B] error [BP1]/[d] flags [B] [B][P13] treeid [d] procid [d] uid [d] mid [d] wordcnt [b] "; 508 509 request = (CVAL(buf,9)&0x80)?0:1; 510 511 command = CVAL(buf,4); 512 513 fn = smbfind(command,smb_fns); 514 515 printf("%s-%s",fn->name,request?"request":"reply"); 516 517 if (vflag == 0) return; 518 519 /* print out the header */ 520 fdata(buf,fmt_smbheader,buf+33); 521 522 if (CVAL(buf,5)) { 523 int class = CVAL(buf,5); 524 int num = SVAL(buf,7); 525 printf("SMBError %s ",smb_errstr(class,num)); 526 } 527 528 words = buf+32; 529 data = words + 1 + CVAL(words,0)*2; 530 531 532 while (words && data) 533 { 534 char *f1,*f2; 535 int wct = CVAL(words,0); 536 537 if (request) { 538 f1 = fn->descript.req_f1; 539 f2 = fn->descript.req_f2; 540 } else { 541 f1 = fn->descript.rep_f1; 542 f2 = fn->descript.rep_f2; 543 } 544 545 if (fn->descript.fn) { 546 fn->descript.fn(words,data,buf,maxbuf); 547 } else { 548 if (f1) { 549 printf("smbvwv[]="); 550 fdata(words+1,f1,words + 1 + wct*2); 551 } else if (wct) { 552 int i; 553 int v; 554 printf("smbvwv[]="); 555 for (i=0;i<wct;i++) { 556 v = SVAL(words+1,2*i); 557 printf("smb_vwv[%d]=%d (0x%X) ",i,v,v); 558 } 559 } 560 561 if (f2) { 562 printf("smbbuf[]="); 563 fdata(data+2,f2,maxbuf); 564 } else { 565 int bcc = SVAL(data,0); 566 printf("smb_bcc=%d",bcc); 567 } 568 } 569 570 if ((fn->flags & FLG_CHAIN) && CVAL(words,0) && SVAL(words,1)!=0xFF) { 571 command = SVAL(words,1); 572 words = buf + SVAL(words,3); 573 data = words + 1 + CVAL(words,0)*2; 574 575 fn = smbfind(command,smb_fns); 576 577 printf("chained-%s-%s ",fn->name,request?"request":"reply"); 578 } else { 579 words = data = NULL; 580 } 581 } 582 } 583 584 585 /* 586 print a NBT packet received across tcp on port 139 587 */ 588 void nbt_tcp_print(const uchar *data,int length) 589 { 590 const uchar *maxbuf = data + length; 591 int flags = CVAL(data,0); 592 int nbt_len = RSVAL(data,2); 593 594 startbuf = data; 595 if (maxbuf <= data) return; 596 597 printf(": nbt "); 598 599 switch (flags) { 600 case 1: 601 printf("flags 0x%x ", flags); 602 case 0: 603 data = fdata(data,"session flags [rw] len [rd] ",data+4); 604 if (data == NULL) 605 break; 606 if (memcmp(data,"\377SMB",4)==0) { 607 if (nbt_len>PTR_DIFF(maxbuf,data)) 608 printf("[|nbt]"); 609 print_smb(data,maxbuf>data+nbt_len?data+nbt_len:maxbuf); 610 } else { 611 printf("session packet :(raw data?) "); 612 } 613 break; 614 615 case 0x81: 616 data = fdata(data,"session-request flags [rW] dst [n1] src [n1] ",maxbuf); 617 break; 618 619 case 0x82: 620 data = fdata(data,"sessionr-granted flags [rW] ",maxbuf); 621 break; 622 623 case 0x83: 624 { 625 int ecode = CVAL(data,4); 626 data = fdata(data,"session-reject flags [rW] reason [B] ",maxbuf); 627 switch (ecode) { 628 case 0x80: 629 printf("(Not listening on called name) "); 630 break; 631 case 0x81: 632 printf("(Not listening for calling name) "); 633 break; 634 case 0x82: 635 printf("(Called name not present) "); 636 break; 637 case 0x83: 638 printf("(Insufficient resources) "); 639 break; 640 default: 641 printf("(Unspecified error 0x%X) ",ecode); 642 break; 643 } 644 } 645 break; 646 647 case 0x85: 648 data = fdata(data,"keepalive flags [rW] ",maxbuf); 649 break; 650 651 default: 652 printf("flags=0x%x ", flags); 653 data = fdata(data,"unknown packet type [rW] ",maxbuf); 654 } 655 fflush(stdout); 656 } 657 658 659 /* 660 print a NBT packet received across udp on port 137 661 */ 662 void nbt_udp137_print(const uchar *data, int length) 663 { 664 const uchar *maxbuf = data + length; 665 int name_trn_id = RSVAL(data,0); 666 int response = (CVAL(data,2)>>7); 667 int opcode = (CVAL(data,2) >> 3) & 0xF; 668 int nm_flags = ((CVAL(data,2) & 0x7) << 4) + (CVAL(data,3)>>4); 669 int rcode = CVAL(data,3) & 0xF; 670 int qdcount = RSVAL(data,4); 671 int ancount = RSVAL(data,6); 672 int nscount = RSVAL(data,8); 673 int arcount = RSVAL(data,10); 674 char *opcodestr; 675 const char *p; 676 677 startbuf = data; 678 679 if (maxbuf <= data) return; 680 681 switch (opcode) { 682 case 0: opcodestr = "query"; break; 683 case 5: opcodestr = "registration"; break; 684 case 6: opcodestr = "release"; break; 685 case 7: opcodestr = "wack"; break; 686 case 8: opcodestr = "refresh(8)"; break; 687 case 9: opcodestr = "refresh"; break; 688 default: opcodestr = "unknown"; break; 689 } 690 printf("nbt-%s", opcodestr); 691 if (response) { 692 if (rcode) 693 printf("-negative"); 694 else 695 printf("-positive"); 696 printf("-resp"); 697 } else 698 printf("-req"); 699 700 if (nm_flags&1) 701 printf("-bcast"); 702 703 if (vflag == 0) return; 704 705 printf(" transid 0x%X opcode %d nmflags 0x%X rcode %d querycnt %d answercnt %d authoritycnt %d addrreccnt %d ", name_trn_id,opcode,nm_flags,rcode,qdcount,ancount,nscount,arcount); 706 707 p = data + 12; 708 709 { 710 int total = ancount+nscount+arcount; 711 int i; 712 713 if (qdcount>100 || total>100) { 714 printf("(corrupt packet?) "); 715 return; 716 } 717 718 if (qdcount) { 719 printf("question: "); 720 for (i=0;i<qdcount;i++) 721 p = fdata(p,"|name [n1] type [rw] class [rw] #",maxbuf); 722 if (p == NULL) 723 return; 724 } 725 726 if (total) { 727 printf("rr: "); 728 for (i=0;i<total;i++) { 729 int rdlen; 730 int restype; 731 p = fdata(p,"name [n1] #",maxbuf); 732 if (p == NULL) 733 return; 734 restype = RSVAL(p,0); 735 p = fdata(p,"type [rw] class [rw] ttl [rD] ",p+8); 736 if (p == NULL) 737 return; 738 rdlen = RSVAL(p,0); 739 printf("len %d data ",rdlen); 740 p += 2; 741 if (rdlen == 6) { 742 p = fdata(p,"addrtype [rw] addr [b.b.b.b] ",p+rdlen); 743 if (p == NULL) 744 return; 745 } else { 746 if (restype == 0x21) { 747 int numnames = CVAL(p,0); 748 p = fdata(p,"numnames [B] ",p+1); 749 if (p == NULL) 750 return; 751 while (numnames--) { 752 p = fdata(p,"name [n2] #",maxbuf); 753 if (p[0] & 0x80) printf("<GROUP> "); 754 switch (p[0] & 0x60) { 755 case 0x00: printf("B "); break; 756 case 0x20: printf("P "); break; 757 case 0x40: printf("M "); break; 758 case 0x60: printf("_ "); break; 759 } 760 if (p[0] & 0x10) printf("<DEREGISTERING> "); 761 if (p[0] & 0x08) printf("<CONFLICT> "); 762 if (p[0] & 0x04) printf("<ACTIVE> "); 763 if (p[0] & 0x02) printf("<PERMANENT> "); 764 p += 2; 765 } 766 } else 767 p += rdlen; 768 } 769 } 770 } 771 } 772 773 if ((uchar*)p < maxbuf) { 774 fdata(p,"extra: ",maxbuf); 775 } 776 777 fflush(stdout); 778 } 779 780 781 782 /* 783 print a NBT packet received across udp on port 138 784 */ 785 void nbt_udp138_print(const uchar *data, int length) 786 { 787 const uchar *maxbuf = data + length; 788 startbuf = data; 789 if (maxbuf <= data) return; 790 791 /* EMF - figure out how to skip fields inside maxbuf easily, IP and PORT here are bloody redundant */ 792 data = fdata(data,"nbt res [rw] id [rw] ip [b.b.b.b] port [rd] len [rd] res2 [rw] srcname [n1] dstname [n1] #",maxbuf); 793 794 if (data != NULL) 795 print_smb(data,maxbuf); 796 797 fflush(stdout); 798 } 799 800 801 802 /* 803 print netbeui frames 804 */ 805 void netbeui_print(u_short control, const uchar *data, const uchar *maxbuf) 806 { 807 int len = SVAL(data,0); 808 int command = CVAL(data,4); 809 const uchar *data2 = data + len; 810 int is_truncated = 0; 811 812 if (data2 >= maxbuf) { 813 data2 = maxbuf; 814 is_truncated = 1; 815 } 816 817 startbuf = data; 818 819 printf("NetBeui type 0x%X ", control); 820 data = fdata(data,"len [d] signature [w] cmd [B] #",maxbuf); 821 if (data == NULL) 822 return; 823 824 switch (command) { 825 case 0xA: 826 data = fdata(data,"namequery [P1] sessnum [B] nametype [B][P2] respcorrelator [w] dst [n2] src [n2] ",data2); 827 break; 828 829 case 0x8: 830 data = fdata(data,"netbios dgram [P7] dst [n2] src [n2] ",data2); 831 break; 832 833 case 0xE: 834 data = fdata(data,"namerecognize [P1] data2 [w] xmitcorrelator [w] respcorrelator [w] dst [n2] src [n2] ",data2); 835 break; 836 837 case 0x19: 838 data = fdata(data,"sessinit data1 [B] data2 [w] xmitcorrelator [w] respcorrelator [w] remsessnum [B] lclsessnum [B] ",data2); 839 break; 840 841 case 0x17: 842 data = fdata(data,"sessconf data1 [B] data2 [w] xmitcorrelator [w] respcorrelator [w] remsessnum [B] lclsessnum [B] ",data2); 843 break; 844 845 case 0x16: 846 data = fdata(data,"netbios data only last flags [{|NO_ACK|PIGGYBACK_ACK_ALLOWED|PIGGYBACK_ACK_INCLUDED|}] resyncindicator [w][P2] respcorrelator [w] remsessnum [B] lclsessnum [B] ",data2); 847 break; 848 849 case 0x14: 850 data = fdata(data,"netbios data ack [P3] xmitcorrelator [w][P2] remsessnum [B] lclsessnum [B] ",data2); 851 break; 852 853 case 0x18: 854 data = fdata(data,"end session [P1] data2 [w][P4] remsessnum [B] lclsessnum [B] ",data2); 855 break; 856 857 case 0x1f: 858 data = fdata(data,"session alive ",data2); 859 break; 860 861 default: 862 data = fdata(data,"unknown netbios command ",data2); 863 break; 864 } 865 if (data == NULL) 866 return; 867 868 if (is_truncated) { 869 /* data2 was past the end of the buffer */ 870 return; 871 } 872 873 if (memcmp(data2,"\377SMB",4)==0) { 874 print_smb(data2,maxbuf); 875 } else { 876 int i; 877 for (i=0;i<128;i++) { 878 if (&data2[i] >= maxbuf) 879 break; 880 if (memcmp(&data2[i],"\377SMB",4)==0) { 881 printf("smb @ %d", i); 882 print_smb(&data2[i],maxbuf); 883 break; 884 } 885 } 886 } 887 } 888 889 890 /* 891 print IPX-Netbios frames 892 */ 893 void ipx_netbios_print(const uchar *data, const uchar *maxbuf) 894 { 895 /* this is a hack till I work out how to parse the rest of the IPX stuff */ 896 int i; 897 startbuf = data; 898 for (i=0;i<128;i++) 899 if (memcmp(&data[i],"\377SMB",4)==0) { 900 fdata(data,"IPX ",&data[i]); 901 print_smb(&data[i],maxbuf); 902 fflush(stdout); 903 break; 904 } 905 if (i==128) 906 fdata(data,"unknown IPX ",maxbuf); 907 } 908