nat-1.0.orig/0040700000175000017500000000000007475250072014133 5ustar jfernandezjfernandeznat-1.0.orig/version.h0100600000175000017500000000017006301746754015772 0ustar jfernandezjfernandez#ifdef SCANNER #define VERSION "X" #else #define VERSION "vaguely resembling 1.9.15p8 but with many grody hacks" #endif nat-1.0.orig/util.c0100600000175000017500000032565607453010423015262 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. Samba utility functions Copyright (C) Andrew Tridgell 1992-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" #include "loadparm.h" #ifdef _WIN32 #include #endif pstring scope = ""; int DEBUGLEVEL = 0; BOOL passive = False; int Protocol = PROTOCOL_COREPLUS; int serverzone=0; /* a default finfo structure to ensure all fields are sensible */ file_info def_finfo = {-1,0,0,0,0,0,0,""}; /* these are some file handles where debug info will be stored */ FILE *dbf = NULL; /* the client file descriptor */ int Client = -1; /* info on the client */ struct from_host Client_info= {"UNKNOWN","0.0.0.0",NULL}; /* the last IP received from */ struct in_addr lastip; /* the last port received from */ int lastport=0; /* my IP, the broadcast IP and the Netmask */ struct in_addr myip; struct in_addr bcast_ip; struct in_addr Netmask; int trans_num = 0; /* case handling on filenames */ int case_default = CASE_LOWER; /* size of reads during a direct file to file transfer */ int ReadSize = 16*1024; pstring debugf = "/tmp/log.samba"; int syslog_level; /* the following control case operations - they are put here so the client can link easily */ BOOL case_sensitive; BOOL case_preserve; BOOL use_mangled_map = False; BOOL short_case_preserve; BOOL case_mangle; fstring remote_machine=""; fstring local_machine=""; fstring remote_arch="UNKNOWN"; fstring remote_proto="UNKNOWN"; pstring myhostname=""; pstring user_socket_options=""; pstring sesssetup_user=""; static char *filename_dos(char *path,char *buf); static BOOL stdout_logging = False; #ifdef SCANNER #undef exit #define exit(x) return(0) #endif /* SCANNER */ /******************************************************************* get ready for syslog stuff ******************************************************************/ void setup_logging(char *pname,BOOL interactive) { #ifdef SYSLOG if (!interactive) { char *p = strrchr(pname,'/'); if (p) pname = p+1; openlog(pname, LOG_PID, LOG_DAEMON); } #endif if (interactive) { stdout_logging = True; dbf = stdout; } } BOOL append_log=False; /******************************************************************* write an debug message on the debugfile. This is called by the DEBUG macro ********************************************************************/ #ifdef __STDC__ int Debug1(char *format_str, ...) { #else int Debug1(va_alist) va_dcl { char *format_str; #endif va_list ap; #ifdef __STDC__ va_start(ap, format_str); #else va_start(ap); format_str = va_arg(ap,char *); #endif if (stdout_logging) { vfprintf(dbf,format_str,ap); va_end(ap); return(0); } #ifndef SCANNER { static int debug_count=0; debug_count++; if (debug_count == 100) { int maxlog = lp_max_log_size() * 1024; if (dbf && maxlog > 0) { struct stat st; if (fstat(fileno(dbf),&st) == 0 && st.st_size > maxlog) { fclose(dbf); dbf = NULL; reopen_logs(); if (dbf && file_size(debugf) > maxlog) { pstring name; fclose(dbf); dbf = NULL; sprintf(name,"%s.old",debugf); sys_rename(debugf,name); reopen_logs(); } } } debug_count=0; } } #ifdef SYSLOG if (!lp_syslog_only()) #endif { if (!dbf) { dbf = fopen(debugf,"w"); if (dbf) setbuf(dbf,NULL); else return(0); } } #ifdef SYSLOG if (syslog_level < lp_syslog()) { /* * map debug levels to syslog() priorities * note that not all DEBUG(0, ...) calls are * necessarily errors */ static int priority_map[] = { LOG_ERR, /* 0 */ LOG_WARNING, /* 1 */ LOG_NOTICE, /* 2 */ LOG_INFO, /* 3 */ }; int priority; pstring msgbuf; if (syslog_level >= sizeof(priority_map) / sizeof(priority_map[0]) || syslog_level < 0) priority = LOG_DEBUG; else priority = priority_map[syslog_level]; vsprintf(msgbuf, format_str, ap); msgbuf[255] = '\0'; syslog(priority, "%s", msgbuf); } #endif #ifdef SYSLOG if (!lp_syslog_only()) #endif { vfprintf(dbf,format_str,ap); fflush(dbf); } va_end(ap); return(0); #endif /* SCANNER */ } /**************************************************************************** routine to do file locking ****************************************************************************/ BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type) { #if HAVE_FCNTL_LOCK struct flock lock; int ret; #if 1 uint32 mask = 0xC0000000; /* make sure the count is reasonable, we might kill the lockd otherwise */ count &= ~mask; /* the offset is often strange - remove 2 of its bits if either of the top two bits are set. Shift the top ones by two bits. This still allows OLE2 apps to operate, but should stop lockd from dieing */ if ((offset & mask) != 0) offset = (offset & ~mask) | ((offset & mask) >> 2); #else unsigned long mask = ((unsigned)1<<31); /* interpret negative counts as large numbers */ if (count < 0) count &= ~mask; /* no negative offsets */ offset &= ~mask; /* count + offset must be in range */ while ((offset < 0 || (offset + count < 0)) && mask) { offset &= ~mask; mask = mask >> 1; } #endif DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type)); lock.l_type = type; lock.l_whence = SEEK_SET; lock.l_start = (int)offset; lock.l_len = (int)count; lock.l_pid = 0; errno = 0; ret = fcntl(fd,op,&lock); if (errno != 0) DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); /* a lock query */ if (op == F_GETLK) { if ((ret != -1) && (lock.l_type != F_UNLCK) && (lock.l_pid != 0) && (lock.l_pid != getpid())) { DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid)); return(True); } /* it must be not locked or locked by me */ return(False); } /* a lock set or unset */ if (ret == -1) { DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n", offset,count,op,type,strerror(errno))); /* perhaps it doesn't support this sort of locking?? */ if (errno == EINVAL) { DEBUG(3,("locking not supported? returning True\n")); return(True); } return(False); } /* everything went OK */ DEBUG(5,("Lock call successful\n")); return(True); #else return(False); #endif } /******************************************************************* lock a file - returning a open file descriptor or -1 on failure The timeout is in seconds. 0 means no timeout ********************************************************************/ int file_lock(char *name,int timeout) { int fd = open(name,O_RDWR|O_CREAT,0666); time_t t=0; if (fd < 0) return(-1); #if HAVE_FCNTL_LOCK if (timeout) t = time(NULL); while (!timeout || (time(NULL)-t < timeout)) { if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd); msleep(LOCK_RETRY_TIMEOUT); } return(-1); #else return(fd); #endif } /******************************************************************* unlock a file locked by file_lock ********************************************************************/ void file_unlock(int fd) { if (fd<0) return; #if HAVE_FCNTL_LOCK fcntl_lock(fd,F_SETLK,0,1,F_UNLCK); #endif close(fd); } /******************************************************************* a gettimeofday wrapper ********************************************************************/ void GetTimeOfDay(struct timeval *tval) { #ifdef GETTIMEOFDAY1 gettimeofday(tval); #else gettimeofday(tval,NULL); #endif } int extra_time_offset = 0; static int timediff = 0; /******************************************************************* init the time differences ********************************************************************/ void TimeInit(void) { struct tm tm_utc,tm_local; time_t t; t = time(NULL); tm_utc = *(gmtime(&t)); tm_local = *(localtime(&t)); #ifdef HAVE_GMTOFF timediff = -tm_local.tm_gmtoff; #else timediff = mktime(&tm_utc) - mktime(&tm_local); #endif if (serverzone == 0) { serverzone = timediff - DSTDiff(t); DEBUG(4,("Serverzone is %d\n",serverzone)); } } /******************************************************************* return the DST offset for a particular time We keep a table of DST offsets to prevent calling localtime() on each call of this function. This saves a LOT of time on many unixes. ********************************************************************/ int DSTDiff(time_t t) { static struct dst_table {time_t start,end; BOOL is_dst;} *dst_table = NULL; static int table_size = 0; int i; BOOL is_dst = False; if (t == 0) t = time(NULL); #ifndef NO_ISDST for (i=0;i= dst_table[i].start && t <= dst_table[i].end) break; if (itm_isdst?True:False);; dst_table[i].start = dst_table[i].end = t; /* no entry will cover more than 6 months */ low = t - 3*30*24*60*60; high = t + 3*30*24*60*60; /* widen the new entry using two bisection searches */ while (low+60*60 < dst_table[i].start) { t = low + (dst_table[i].start-low)/2; if ((localtime(&t)->tm_isdst?True:False) == is_dst) dst_table[i].start = t; else low = t; } while (high-60*60 > dst_table[i].end) { t = high + (high-dst_table[i].end)/2; if ((localtime(&t)->tm_isdst?True:False) == is_dst) dst_table[i].end = t; else high = t; } /* DEBUG(1,("Added DST entry from %s ", asctime(localtime(&dst_table[i].start)))); DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)), dst_table[i].is_dst)); */ } #endif return((is_dst?60*60:0) - (extra_time_offset*60)); } /**************************************************************************** return the difference between local and GMT time ****************************************************************************/ int TimeDiff(time_t t) { static BOOL initialised = False; if (!initialised) {initialised=True; TimeInit();} return(timediff - DSTDiff(t)); } /**************************************************************************** try to optimise the localtime call, it can be quite expenive on some machines timemul is normally LOCAL_TO_GMT, GMT_TO_LOCAL or 0 ****************************************************************************/ struct tm *LocalTime(time_t *t,int timemul) { time_t t2 = *t; if (timemul) t2 += timemul * TimeDiff(t2); return(gmtime(&t2)); } /**************************************************************************** determine if a file descriptor is in fact a socket ****************************************************************************/ BOOL is_a_socket(int fd) { int v,l; l = sizeof(int); #ifdef _WIN32 /* evil, but it works */ return(0); #else return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0); #endif } /**************************************************************************** Get the next token from a string, return False if none found handles double-quotes. Based on a routine by GJC@VILLAGE.COM. Extensively modified by Andrew.Tridgell@anu.edu.au ****************************************************************************/ BOOL next_token(char **ptr,char *buff,char *sep) { static char *last_ptr=NULL; char *s; BOOL quoted; if (!ptr) ptr = &last_ptr; if (!ptr) return(False); s = *ptr; /* default to simple separators */ if (!sep) sep = " \t\n\r"; /* find the first non sep char */ while(*s && strchr(sep,*s)) s++; /* nothing left? */ if (! *s) return(False); /* copy over the token */ for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++) { if (*s == '\"') quoted = !quoted; else *buff++ = *s; } *ptr = (*s) ? s+1 : s; *buff = 0; last_ptr = *ptr; return(True); } /******************************************************************* safely copies memory, ensuring no overlap problems. this is only used if the machine does not have it's own memmove(). this is not the fastest algorithm in town, but it will do for our needs. ********************************************************************/ void *MemMove(void *dest,void *src,int size) { unsigned long d,s; int i; if (dest==src || !size) return(dest); d = (unsigned long)dest; s = (unsigned long)src; if ((d >= (s+size)) || (s >= (d+size))) { /* no overlap */ memcpy(dest,src,size); return(dest); } if (d < s) { /* we can forward copy */ if (s-d >= sizeof(int) && !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) { /* do it all as words */ int *idest = (int *)dest; int *isrc = (int *)src; size /= sizeof(int); for (i=0;i= sizeof(int) && !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) { /* do it all as words */ int *idest = (int *)dest; int *isrc = (int *)src; size /= sizeof(int); for (i=size-1;i>=0;i--) idest[i] = isrc[i]; } else { /* simplest */ char *cdest = (char *)dest; char *csrc = (char *)src; for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; } } return(dest); } /**************************************************************************** prompte a dptr (to make it recently used) ****************************************************************************/ void array_promote(char *array,int elsize,int element) { char *p; if (element == 0) return; p = (char *)malloc(elsize); if (!p) { DEBUG(5,("Ahh! Can't malloc\n")); return; } memcpy(p,array + element * elsize, elsize); memmove(array + elsize,array,elsize*element); memcpy(array,p,elsize); free(p); } enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; struct { char *name; int level; int option; int value; int opttype; } socket_options[] = { {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, #ifdef TCP_NODELAY {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL}, #endif #ifdef IPTOS_LOWDELAY {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON}, #endif #ifdef IPTOS_THROUGHPUT {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON}, #endif #ifdef SO_SNDBUF {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT}, #endif #ifdef SO_RCVBUF {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT}, #endif #ifdef SO_SNDLOWAT {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT}, #endif #ifdef SO_RCVLOWAT {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT}, #endif {NULL,0,0,0,0}}; /**************************************************************************** set user socket options ****************************************************************************/ void set_socket_options(int fd, char *options) { string tok; while (next_token(&options,tok," \t,")) { int ret=0,i; int value = 1; char *p; BOOL got_value = False; if ((p = strchr(tok,'='))) { *p = 0; value = atoi(p+1); got_value = True; } for (i=0;socket_options[i].name;i++) if (strequal(socket_options[i].name,tok)) break; if (!socket_options[i].name) { DEBUG(0,("Unknown socket option %s\n",tok)); continue; } switch (socket_options[i].opttype) { case OPT_BOOL: case OPT_INT: ret = setsockopt(fd,socket_options[i].level, socket_options[i].option,(char *)&value,sizeof(int)); break; case OPT_ON: if (got_value) DEBUG(0,("syntax error - %s does not take a value\n",tok)); { int on = socket_options[i].value; ret = setsockopt(fd,socket_options[i].level, socket_options[i].option,(char *)&on,sizeof(int)); } break; } if (ret != 0) DEBUG(0,("Failed to set socket option %s\n",tok)); } } /**************************************************************************** close the socket communication ****************************************************************************/ void close_sockets(void ) { close(Client); #ifdef SCANNER Client = -1; #else Client = 0; #endif /* SCANNER */ } /**************************************************************************** return the date and time as a string ****************************************************************************/ char *timestring(void ) { static char TimeBuf[100]; time_t t; t = time(NULL); #ifdef NO_STRFTIME strcpy(TimeBuf, asctime(LocalTime(&t,GMT_TO_LOCAL))); #elif defined(CLIX) || defined(CONVEX) strftime(TimeBuf,100,"%m/%d/%y %I:%M:%S %p",LocalTime(&t,GMT_TO_LOCAL)); #elif defined(AMPM) strftime(TimeBuf,100,"%D %r",LocalTime(&t,GMT_TO_LOCAL)); #elif defined(TZ_TIME) { strftime(TimeBuf,100,"%D:%T",LocalTime(&t,0)); sprintf(TimeBuf+strlen(TimeBuf)," %+03d%02d", -TimeDiff(t)/(60*60),-(TimeDiff(t)/60)%60); } #else strftime(TimeBuf,100,"%D %T",LocalTime(&t,GMT_TO_LOCAL)); #endif return(TimeBuf); } /**************************************************************************** determine whether we are in the specified group ****************************************************************************/ BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups) { int i; if (group == current_gid) return(True); for (i=0;i 30 || len<1) return(0); while (len--) { if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') { *out = 0; return(0); } *out = ((in[0]-'A')<<4) + (in[1]-'A'); in += 2; out++; } *out = 0; ret = out[-1]; #ifdef NETBIOS_SCOPE /* Handle any scope names */ while(*in) { *out++ = '.'; /* Scope names are separated by periods */ len = *(unsigned char *)in++; StrnCpy(out, in, len); out += len; *out=0; in += len; } #endif return(ret); } /**************************************************************************** mangle a name into netbios format ****************************************************************************/ int name_mangle(char *In,char *Out,char name_type) { fstring name; char buf[20]; char *in = (char *)&buf[0]; char *out = (char *)Out; char *p, *label; int i; #ifdef SCANNER if ((In[0] == '*') && (In[1] == '\0')) { buf[0]='*'; memset(&buf[1],0,16); } else { StrnCpy(name,In,sizeof(name)-1); sprintf(buf,"%-15.15s%c",name,name_type); } #else if (In[0] != '*') { StrnCpy(name,In,sizeof(name)-1); sprintf(buf,"%-15.15s%c",name,name_type); } else { buf[0]='*'; memset(&buf[1],0,16); } #endif /* SCANNER */ *out++ = 32; for (i=0;i<16;i++) { char c = toupper(in[i]); out[i*2] = (c>>4) + 'A'; out[i*2+1] = (c & 0xF) + 'A'; } out[32]=0; out += 32; label = scope; while (*label) { p = strchr(label, '.'); if (p == 0) p = label + strlen(label); *out++ = p - label; memcpy(out, label, p - label); out += p - label; label += p - label + (*p == '.'); } *out = 0; return(name_len(Out)); } /******************************************************************* check if a file exists ********************************************************************/ BOOL file_exist(char *fname,struct stat *sbuf) { struct stat st; if (!sbuf) sbuf = &st; if (sys_stat(fname,sbuf) != 0) return(False); return(S_ISREG(sbuf->st_mode)); } /******************************************************************* check a files mod time ********************************************************************/ time_t file_modtime(char *fname) { struct stat st; if (sys_stat(fname,&st) != 0) return(0); return(st.st_mtime); } /******************************************************************* check if a directory exists ********************************************************************/ BOOL directory_exist(char *dname,struct stat *st) { struct stat st2; if (!st) st = &st2; if (sys_stat(dname,st) != 0) return(False); return(S_ISDIR(st->st_mode)); } /******************************************************************* returns the size in bytes of the named file ********************************************************************/ uint32 file_size(char *file_name) { struct stat buf; buf.st_size = 0; sys_stat(file_name,&buf); return(buf.st_size); } /**************************************************************************** check if it's a null mtime ****************************************************************************/ static BOOL null_mtime(time_t mtime) { if (mtime == 0 || mtime == 0xFFFFFFFF) return(True); return(False); } /******************************************************************* create a 16 bit dos packed date ********************************************************************/ static uint16 make_dos_date1(time_t unixdate,struct tm *t) { uint16 ret=0; ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); return(ret); } /******************************************************************* create a 16 bit dos packed time ********************************************************************/ static uint16 make_dos_time1(time_t unixdate,struct tm *t) { uint16 ret=0; ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3)); ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); return(ret); } /******************************************************************* create a 32 bit dos packed date/time from some parameters This takes a GMT time and returns a packed localtime structure ********************************************************************/ static uint32 make_dos_date(time_t unixdate) { struct tm *t; uint32 ret=0; t = LocalTime(&unixdate,GMT_TO_LOCAL); ret = make_dos_date1(unixdate,t); ret = ((ret&0xFFFF)<<16) | make_dos_time1(unixdate,t); return(ret); } /******************************************************************* put a dos date into a buffer (time/date format) This takes GMT time and puts local time in the buffer ********************************************************************/ void put_dos_date(char *buf,int offset,time_t unixdate) { uint32 x = make_dos_date(unixdate); SIVAL(buf,offset,x); } /******************************************************************* put a dos date into a buffer (date/time format) This takes GMT time and puts local time in the buffer ********************************************************************/ void put_dos_date2(char *buf,int offset,time_t unixdate) { uint32 x = make_dos_date(unixdate); x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(buf,offset,x); } /******************************************************************* put a dos 32 bit "unix like" date into a buffer. This routine takes GMT and converts it to LOCAL time before putting it (most SMBs assume localtime for this sort of date) ********************************************************************/ void put_dos_date3(char *buf,int offset,time_t unixdate) { if (!null_mtime(unixdate)) unixdate += GMT_TO_LOCAL*TimeDiff(unixdate); SIVAL(buf,offset,unixdate); } /******************************************************************* interpret a 32 bit dos packed date/time to some parameters ********************************************************************/ static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second) { uint32 p0,p1,p2,p3; p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; *second = 2*(p0 & 0x1F); *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3); *hour = (p1>>3)&0xFF; *day = (p2&0x1F); *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1; *year = ((p3>>1)&0xFF) + 80; } /******************************************************************* create a unix date (int GMT) from a dos date (which is actually in localtime) ********************************************************************/ time_t make_unix_date(void *date_ptr) { uint32 dos_date=0; struct tm t; time_t ret; dos_date = IVAL(date_ptr,0); if (dos_date == 0) return(0); interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); t.tm_wday = 1; t.tm_yday = 1; t.tm_isdst = -1; /* mktime() also does the local to GMT time conversion for us. XXXXX Do all unixes do this the same?? */ ret = mktime(&t); return(ret); } /******************************************************************* like make_unix_date() but the words are reversed ********************************************************************/ time_t make_unix_date2(void *date_ptr) { uint32 x,x2; x = IVAL(date_ptr,0); x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(&x,0,x2); return(make_unix_date((void *)&x)); } /******************************************************************* create a unix GMT date from a dos date in 32 bit "unix like" format these generally arrive as localtimes, with corresponding DST ********************************************************************/ time_t make_unix_date3(void *date_ptr) { time_t t = IVAL(date_ptr,0); if (!null_mtime(t)) t += LOCAL_TO_GMT*TimeDiff(t); return(t); } /******************************************************************* return a string representing an attribute for a file ********************************************************************/ char *attrib_string(int mode) { static char attrstr[10]; attrstr[0] = 0; if (mode & aVOLID) strcat(attrstr,"V"); if (mode & aDIR) strcat(attrstr,"D"); if (mode & aARCH) strcat(attrstr,"A"); if (mode & aHIDDEN) strcat(attrstr,"H"); if (mode & aSYSTEM) strcat(attrstr,"S"); if (mode & aRONLY) strcat(attrstr,"R"); return(attrstr); } /******************************************************************* case insensitive string compararison ********************************************************************/ int StrCaseCmp(char *s, char *t) { for (; tolower(*s) == tolower(*t); ++s, ++t) if (!*s) return 0; return tolower(*s) - tolower(*t); } /******************************************************************* case insensitive string compararison, length limited ********************************************************************/ int StrnCaseCmp(char *s, char *t, int n) { while (n-- && *s && *t) { if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t)); s++; t++; } if (n) return(tolower(*s) - tolower(*t)); return(0); } /******************************************************************* compare 2 strings ********************************************************************/ BOOL strequal(char *s1,char *s2) { if (!s1 || !s2) return(False); return(StrCaseCmp(s1,s2)==0); } /******************************************************************* compare 2 strings up to and including the nth char. ******************************************************************/ BOOL strnequal(char *s1,char *s2,int n) { if (!s1 || !s2 || !n) return(False); return(StrnCaseCmp(s1,s2,n)==0); } /******************************************************************* compare 2 strings (case sensitive) ********************************************************************/ BOOL strcsequal(char *s1,char *s2) { if (!s1 || !s2) return(False); return(strcmp(s1,s2)==0); } #ifdef SCANNER_NOT /* work around fucking BROKEN bfd libraries */ /* XXX: it was later found that calling charset_initialise fixed it */ void strlower (char * s) { register unsigned int c; while (*s) { c = (unsigned int) *s; if (isupper (c)) *s = tolower (c); s++; } } /* strlower */ void strupper (char * s) { register unsigned int c; while (*s) { c = (unsigned int) *s; if (islower (c)) *s = toupper (c); s++; } } /* strupper */ #else /* SCANNER */ /******************************************************************* convert a string to lower case ********************************************************************/ void strlower(char *s) { while (*s) { #ifdef KANJI if (is_shift_jis (*s)) { s += 2; } else if (is_kana (*s)) { s++; } else { if (isupper(*s)) *s = tolower(*s); s++; } #else if (isupper(*s)) *s = tolower(*s); s++; #endif /* KANJI */ } } /******************************************************************* convert a string to upper case ********************************************************************/ void strupper(char *s) { while (*s) { #ifdef KANJI if (is_shift_jis (*s)) { s += 2; } else if (is_kana (*s)) { s++; } else { if (islower(*s)) *s = toupper(*s); s++; } #else if (islower(*s)) *s = toupper(*s); s++; #endif } } #endif /* SCANNER */ /******************************************************************* convert a string to "normal" form ********************************************************************/ void strnorm(char *s) { if (case_default == CASE_UPPER) strupper(s); else strlower(s); } /******************************************************************* check if a string is in "normal" case ********************************************************************/ BOOL strisnormal(char *s) { if (case_default == CASE_UPPER) return(!strhaslower(s)); return(!strhasupper(s)); } /**************************************************************************** string replace ****************************************************************************/ void string_replace(char *s,char oldc,char newc) { while (*s) { #ifdef KANJI if (is_shift_jis (*s)) { s += 2; } else if (is_kana (*s)) { s++; } else { if (oldc == *s) *s = newc; s++; } #else if (oldc == *s) *s = newc; s++; #endif /* KANJI */ } } #ifndef SCANNER /**************************************************************************** make a file into unix format ****************************************************************************/ void unix_format(char *fname) { pstring namecopy; string_replace(fname,'\\','/'); #ifndef KANJI dos2unix_format(fname, True); #endif /* KANJI */ if (*fname == '/') { strcpy(namecopy,fname); strcpy(fname,"."); strcat(fname,namecopy); } } /**************************************************************************** make a file into dos format ****************************************************************************/ void dos_format(char *fname) { #ifndef KANJI unix2dos_format(fname, True); #endif /* KANJI */ string_replace(fname,'/','\\'); } #endif /* SCANNER */ /******************************************************************* show a smb message structure ********************************************************************/ void show_msg(char *buf) { int i; int bcc=0; if (DEBUGLEVEL < 5) return; DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n", smb_len(buf), (int)CVAL(buf,smb_com), (int)CVAL(buf,smb_rcls), (int)CVAL(buf,smb_reh), (int)SVAL(buf,smb_err), (int)CVAL(buf,smb_flg), (int)SVAL(buf,smb_flg2))); DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n", (int)SVAL(buf,smb_tid), (int)SVAL(buf,smb_pid), (int)SVAL(buf,smb_uid), (int)SVAL(buf,smb_mid), (int)CVAL(buf,smb_wct))); for (i=0;i<(int)CVAL(buf,smb_wct);i++) DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i, SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i))); bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct))); DEBUG(5,("smb_bcc=%d\n",bcc)); if (DEBUGLEVEL < 10) return; for (i=0;i>16; buf[2] = (len&0xFF00)>>8; buf[3] = len&0xFF; } /******************************************************************* set the length and marker of an smb packet ********************************************************************/ void smb_setlen(char *buf,int len) { _smb_setlen(buf,len); CVAL(buf,4) = 0xFF; CVAL(buf,5) = 'S'; CVAL(buf,6) = 'M'; CVAL(buf,7) = 'B'; } /******************************************************************* setup the word count and byte count for a smb message ********************************************************************/ int set_message(char *buf,int num_words,int num_bytes,BOOL zero) { if (zero) bzero(buf + smb_size,num_words*2 + num_bytes); CVAL(buf,smb_wct) = num_words; SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4); return (smb_size + num_words*2 + num_bytes); } /******************************************************************* return the number of smb words ********************************************************************/ int smb_numwords(char *buf) { return (CVAL(buf,smb_wct)); } /******************************************************************* return the size of the smb_buf region of a message ********************************************************************/ int smb_buflen(char *buf) { return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2)); } /******************************************************************* return a pointer to the smb_buf data area ********************************************************************/ int smb_buf_ofs(char *buf) { return (smb_size + CVAL(buf,smb_wct)*2); } /******************************************************************* return a pointer to the smb_buf data area ********************************************************************/ char *smb_buf(char *buf) { return (buf + smb_buf_ofs(buf)); } /******************************************************************* return the SMB offset into an SMB buffer ********************************************************************/ int smb_offset(char *p,char *buf) { return(PTR_DIFF(p,buf+4)); } /******************************************************************* skip past some strings in a buffer ********************************************************************/ char *skip_string(char *buf,int n) { while (n--) buf += strlen(buf) + 1; return(buf); } /******************************************************************* trim the specified elements off the front and back of a string ********************************************************************/ BOOL trim_string(char *s,char *front,char *back) { BOOL ret = False; while (front && *front && strncmp(s,front,strlen(front)) == 0) { char *p = s; ret = True; while (1) { if (!(*p = p[strlen(front)])) break; p++; } } while (back && *back && strlen(s) >= strlen(back) && (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0)) { ret = True; s[strlen(s)-strlen(back)] = 0; } return(ret); } /******************************************************************* reduce a file name, removing .. elements. ********************************************************************/ void dos_clean_name(char *s) { char *p=NULL; DEBUG(3,("dos_clean_name [%s]\n",s)); /* remove any double slashes */ string_sub(s, "\\\\", "\\"); while ((p = strstr(s,"\\..\\")) != NULL) { pstring s1; *p = 0; strcpy(s1,p+3); if ((p=strrchr(s,'\\')) != NULL) *p = 0; else *s = 0; strcat(s,s1); } trim_string(s,NULL,"\\.."); string_sub(s, "\\.\\", "\\"); } /******************************************************************* reduce a file name, removing .. elements. ********************************************************************/ void unix_clean_name(char *s) { char *p=NULL; DEBUG(3,("unix_clean_name [%s]\n",s)); /* remove any double slashes */ string_sub(s, "//","/"); while ((p = strstr(s,"/../")) != NULL) { pstring s1; *p = 0; strcpy(s1,p+3); if ((p=strrchr(s,'/')) != NULL) *p = 0; else *s = 0; strcat(s,s1); } trim_string(s,NULL,"/.."); } /******************************************************************* a wrapper for the normal chdir() function ********************************************************************/ int ChDir(char *path) { int res; static pstring LastDir=""; if (strcsequal(path,".")) return(0); if (*path == '/' && strcsequal(LastDir,path)) return(0); DEBUG(3,("chdir to %s\n",path)); res = sys_chdir(path); if (!res) strcpy(LastDir,path); return(res); } /******************************************************************* return the absolute current directory path. A dumb version. ********************************************************************/ static char *Dumb_GetWd(char *s) { #ifdef USE_GETCWD return ((char *)getcwd(s,sizeof(pstring))); #else return ((char *)getwd(s)); #endif } /* number of list structures for a caching GetWd function. */ #define MAX_GETWDCACHE (50) struct { ino_t inode; dev_t dev; char *text; BOOL valid; } ino_list[MAX_GETWDCACHE]; BOOL use_getwd_cache=True; /******************************************************************* return the absolute current directory path ********************************************************************/ char *GetWd(char *str) { pstring s; static BOOL getwd_cache_init = False; struct stat st, st2; int i; *s = 0; if (!use_getwd_cache) return(Dumb_GetWd(str)); /* init the cache */ if (!getwd_cache_init) { getwd_cache_init = True; for (i=0;i 8) { strcpy(mext,mbeg + 8); mbeg[8] = 0; } } if (*mbeg == 0) strcpy(mbeg,"????????"); if ((*mext == 0) && doext && !hasdot) strcpy(mext,"???"); /* expand *'s */ expand_one(mbeg,8); if (*mext) expand_one(mext,3); strcpy(Mask,dirpart); if (*dirpart || absolute) strcat(Mask,"\\"); strcat(Mask,mbeg); strcat(Mask,"."); strcat(Mask,mext); DEBUG(6,("Mask expanded to [%s]\n",Mask)); } /**************************************************************************** does a string have any uppercase chars in it? ****************************************************************************/ BOOL strhasupper(char *s) { while (*s) { #ifdef KANJI if (is_shift_jis (*s)) { s += 2; } else if (is_kana (*s)) { s++; } else { if (isupper(*s)) return(True); s++; } #else if (isupper(*s)) return(True); s++; #endif /* KANJI */ } return(False); } /**************************************************************************** does a string have any lowercase chars in it? ****************************************************************************/ BOOL strhaslower(char *s) { while (*s) { #ifdef KANJI if (is_shift_jis (*s)) { s += 2; } else if (is_kana (*s)) { s++; } else { if (islower(*s)) return(True); s++; } #else if (islower(*s)) return(True); s++; #endif /* KANJI */ } return(False); } /**************************************************************************** find the number of chars in a string ****************************************************************************/ int count_chars(char *s,char c) { int count=0; while (*s) { if (*s == c) count++; s++; } return(count); } /**************************************************************************** make a dir struct ****************************************************************************/ void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date) { char *p; pstring mask2; strcpy(mask2,mask); if ((mode & aDIR) != 0) size = 0; memset(buf+1,' ',11); if ((p = strchr(mask2,'.')) != NULL) { *p = 0; memcpy(buf+1,mask2,MIN(strlen(mask2),8)); memcpy(buf+9,p+1,MIN(strlen(p+1),3)); *p = '.'; } else memcpy(buf+1,mask2,MIN(strlen(mask2),11)); bzero(buf+21,DIR_STRUCT_SIZE-21); CVAL(buf,21) = mode; put_dos_date(buf,22,date); SSVAL(buf,26,size & 0xFFFF); SSVAL(buf,28,size >> 16); StrnCpy(buf+30,fname,12); if (!case_sensitive) strupper(buf+30); DEBUG(8,("put name [%s] into dir struct\n",buf+30)); } /******************************************************************* close the low 3 fd's and open dev/null in their place ********************************************************************/ void close_low_fds(void) { int fd; int i; close(0); close(1); close(2); /* try and use up these file descriptors, so silly library routines writing to stdout etc won't cause havoc */ for (i=0;i<3;i++) { fd = open("/dev/null",O_RDWR,0); if (fd < 0) fd = open("/dev/null",O_WRONLY,0); if (fd < 0) { DEBUG(0,("Can't open /dev/null\n")); return; } if (fd != i) { DEBUG(0,("Didn't get file descriptor %d\n",i)); return; } } } /**************************************************************************** write to a socket ****************************************************************************/ int write_socket(int fd,char *buf,int len) { int ret=0; if (passive) return(len); DEBUG(6,("write_socket(%d,%d)\n",fd,len)); ret = write_data(fd,buf,len); DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret)); return(ret); } /**************************************************************************** read from a socket ****************************************************************************/ int read_udp_socket(int fd,char *buf,int len) { int ret; struct sockaddr sock; int socklen; socklen = sizeof(sock); bzero((char *)&sock,socklen); bzero((char *)&lastip,sizeof(lastip)); ret = recvfrom(fd,buf,len,0,&sock,&socklen); if (ret <= 0) { DEBUG(2,("read socket failed. ERRNO=%d\n",errno)); return(0); } lastip = *(struct in_addr *) &sock.sa_data[2]; lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port); return(ret); } /**************************************************************************** Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, else if SYSV use O_NDELAY if BSD use FNDELAY ****************************************************************************/ int set_blocking(int fd, BOOL set) { int val; #ifdef O_NONBLOCK #define FLAG_TO_SET O_NONBLOCK #else #ifdef SYSV #define FLAG_TO_SET O_NDELAY #else /* BSD */ #define FLAG_TO_SET FNDELAY #endif #endif if((val = fcntl(fd, F_GETFL, 0))==-1) return -1; if(set) /* Turn blocking on - ie. clear nonblock flag */ val &= ~FLAG_TO_SET; else val |= FLAG_TO_SET; return fcntl( fd, F_SETFL, val); #undef FLAG_TO_SET } /**************************************************************************** Calculate the difference in timeout values. Return 1 if val1 > val2, 0 if val1 == val2, -1 if val1 < val2. Stores result in retval. retval may be == val1 or val2 ****************************************************************************/ static int tval_sub( struct timeval *retval, struct timeval *val1, struct timeval *val2) { int usecdiff = val1->tv_usec - val2->tv_usec; int secdiff = val1->tv_sec - val2->tv_sec; if(usecdiff < 0) { usecdiff = 1000000 + usecdiff; secdiff--; } retval->tv_sec = secdiff; retval->tv_usec = usecdiff; if(secdiff < 0) return -1; if(secdiff > 0) return 1; return (usecdiff < 0 ) ? -1 : ((usecdiff > 0 ) ? 1 : 0); } /**************************************************************************** read data from a device with a timout in msec. mincount = if timeout, minimum to read before returning maxcount = number to be read. ****************************************************************************/ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact) { fd_set fds; int selrtn; int readret; int nread = 0; struct timeval timeout, tval1, tval2, tvaldiff; /* just checking .... */ if (maxcnt <= 0) return(0); if(time_out == -2) time_out = DEFAULT_PIPE_TIMEOUT; /* Blocking read */ if(time_out < 0) { if (mincnt == 0) mincnt = maxcnt; while (nread < mincnt) { readret = read(fd, buf + nread, maxcnt - nread); if (readret <= 0) return(nread); nread += readret; } return(nread); } /* Non blocking read */ if(time_out == 0) { set_blocking(fd, False); nread = read_data(fd, buf, mincnt); if (nread < maxcnt) nread += read(fd,buf+nread,maxcnt-nread); if(nread == -1 && errno == EWOULDBLOCK) nread = 0; set_blocking(fd,True); return nread; } /* Most difficult - timeout read */ /* If this is ever called on a disk file and mincnt is greater then the filesize then system performance will suffer severely as select always return true on disk files */ /* Set initial timeout */ timeout.tv_sec = time_out / 1000; timeout.tv_usec = 1000 * (time_out % 1000); /* As most UNIXes don't modify the value of timeout when they return from select we need to get the timeofday (in usec) now, and also after the select returns so we know how much time has elapsed */ if (exact) GetTimeOfDay( &tval1); nread = 0; /* Number of bytes we have read */ for(;;) { FD_ZERO(&fds); FD_SET(fd,&fds); selrtn = sys_select(&fds,&timeout); /* Check if error */ if(selrtn == -1) { errno = EBADF; return -1; } /* Did we timeout ? */ if (selrtn == 0 ) { if (nread < mincnt) return -1; break; /* Yes */ } readret = read( fd, buf+nread, maxcnt-nread); if(readret <= 0) { /* force a particular error number for portability */ errno = EBADF; return -1; } if (readret == 0) break; nread += readret; /* If we have read more than mincnt then return */ if( nread >= mincnt ) break; /* We need to do another select - but first reduce the time_out by the amount of time already elapsed - if this is less than zero then return */ if (exact) { GetTimeOfDay( &tval2); (void)tval_sub( &tvaldiff, &tval2, &tval1); if( tval_sub( &timeout, &timeout, &tvaldiff) <= 0) { /* We timed out */ break; } } /* Save the time of day as we need to do the select again (saves a system call)*/ tval1 = tval2; } /* Return the number we got */ return(nread); } /**************************************************************************** read data from the client. Maxtime is in milliseconds ****************************************************************************/ int read_max_udp(int fd,char *buffer,int bufsize,int maxtime) { fd_set fds; int selrtn; int nread; struct timeval timeout; FD_ZERO(&fds); FD_SET(fd,&fds); timeout.tv_sec = maxtime / 1000; timeout.tv_usec = (maxtime % 1000) * 1000; selrtn = sys_select(&fds,maxtime>0?&timeout:NULL); if (!FD_ISSET(fd,&fds)) return 0; nread = read_udp_socket(fd, buffer, bufsize); /* return the number got */ return(nread); } /******************************************************************* find the difference in milliseconds between two struct timeval values ********************************************************************/ int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew) { return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000); } /**************************************************************************** send a keepalive packet (rfc1002) ****************************************************************************/ BOOL send_keepalive(int client) { unsigned char buf[4]; buf[0] = 0x85; buf[1] = buf[2] = buf[3] = 0; return(write_data(client,(char *)buf,4) == 4); } /**************************************************************************** read data from the client, reading exactly N bytes. ****************************************************************************/ int read_data(int fd,char *buffer,int N) { int ret; int total=0; while (total < N) { ret = read(fd,buffer + total,N - total); /* this is for portability */ if (ret < 0) errno = EBADF; if (ret <= 0) return total; total += ret; } return total; } /**************************************************************************** write data to a fd ****************************************************************************/ int write_data(int fd,char *buffer,int N) { int total=0; int ret; while (total < N) { ret = write(fd,buffer + total,N - total); if (ret <= 0) return total; total += ret; } return total; } /* variables used by the read prediction module */ int rp_fd = -1; int rp_offset = 0; int rp_length = 0; int rp_alloced = 0; int rp_predict_fd = -1; int rp_predict_offset = 0; int rp_predict_length = 0; int rp_timeout = 5; time_t rp_time = 0; char *rp_buffer = NULL; BOOL predict_skip=False; time_t smb_last_time=(time_t)0; /**************************************************************************** handle read prediction on a file ****************************************************************************/ int read_predict(int fd,int offset,char *buf,char **ptr,int num) { int ret = 0; int possible = rp_length - (offset - rp_offset); possible = MIN(possible,num); /* give data if possible */ if (fd == rp_fd && offset >= rp_offset && possible>0 && smb_last_time-rp_time < rp_timeout) { ret = possible; if (buf) memcpy(buf,rp_buffer + (offset-rp_offset),possible); else *ptr = rp_buffer + (offset-rp_offset); DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); } if (ret == num) { predict_skip = True; } else { predict_skip = False; /* prepare the next prediction */ rp_predict_fd = fd; rp_predict_offset = offset + num; rp_predict_length = num; } if (ret < 0) ret = 0; return(ret); } /**************************************************************************** pre-read some data ****************************************************************************/ void do_read_prediction() { if (predict_skip) return; if (rp_predict_fd == -1) return; rp_fd = rp_predict_fd; rp_offset = rp_predict_offset; rp_length = 0; rp_predict_fd = -1; rp_predict_length = MIN(rp_predict_length,2*ReadSize); rp_predict_length = MAX(rp_predict_length,1024); rp_offset = (rp_offset/1024)*1024; rp_predict_length = (rp_predict_length/1024)*1024; if (rp_predict_length > rp_alloced) { rp_buffer = Realloc(rp_buffer,rp_predict_length); rp_alloced = rp_predict_length; if (!rp_buffer) { DEBUG(0,("can't allocate read-prediction buffer\n")); rp_predict_fd = -1; rp_fd = -1; rp_alloced = 0; return; } } if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { rp_fd = -1; rp_predict_fd = -1; return; } rp_length = read(rp_fd,rp_buffer,rp_predict_length); rp_time = time(NULL); if (rp_length < 0) rp_length = 0; } /**************************************************************************** invalidate read-prediction on a fd ****************************************************************************/ void invalidate_read_prediction(int fd) { if (rp_fd == fd) rp_fd = -1; if (rp_predict_fd == fd) rp_predict_fd = -1; } /**************************************************************************** transfer some data between two fd's ****************************************************************************/ int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align) { static char *buf=NULL; char *buf1,*abuf; static int size = 0; int total = 0; DEBUG(4,("transfer_file %d (head=%d) called\n",n,headlen)); if ((size < ReadSize) && buf) { free(buf); buf = NULL; } size = MAX(ReadSize,1024); while (!buf && size>0) { buf = (char *)Realloc(buf,size+8); if (!buf) size /= 2; } if (!buf) { DEBUG(0,("Can't allocate transfer buffer!\n")); exit(1); } abuf = buf + (align%8); if (header) n += headlen; while (n > 0) { int s = MIN(n,size); int ret,ret2=0; ret = 0; if (header && (headlen >= MIN(s,1024))) { buf1 = header; s = headlen; ret = headlen; headlen = 0; header = NULL; } else { buf1 = abuf; } if (header && headlen > 0) { ret = MIN(headlen,size); memcpy(buf1,header,ret); headlen -= ret; header += ret; if (headlen <= 0) header = NULL; } if (s > ret) ret += read(infd,buf1+ret,s-ret); if (ret > 0) { ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret); if (ret2 > 0) total += ret2; /* if we can't write then dump excess data */ if (ret2 != ret) transfer_file(infd,-1,n-(ret+headlen),NULL,0,0); } if (ret <= 0 || ret2 != ret) return(total); n -= ret; } return(total); } /**************************************************************************** read 4 bytes of a smb packet and return the smb length of the packet possibly store the result in the buffer ****************************************************************************/ int read_smb_length(int fd,char *inbuf,int timeout) { char *buffer; char buf[4]; int len=0, msg_type; BOOL ok=False; if (inbuf) buffer = inbuf; else buffer = buf; while (!ok) { if (timeout > 0) ok = (read_with_timeout(fd,buffer,4,4,timeout,False) == 4); else ok = (read_data(fd,buffer,4) == 4); if (!ok) { if (timeout>0) { DEBUG(10,("select timeout (%d)\n", timeout)); return(-1); } else { DEBUG(6,("couldn't read from client\n")); exit(1); } } len = smb_len(buffer); msg_type = CVAL(buffer,0); if (msg_type == 0x85) { DEBUG(5,( "Got keepalive packet\n")); ok = False; } } DEBUG(10,("got smb length of %d\n",len)); return(len); } /**************************************************************************** read an smb from a fd and return it's length The timeout is in milli seconds ****************************************************************************/ BOOL receive_smb(int fd,char *buffer,int timeout) { int len; BOOL ok; bzero(buffer,smb_size + 100); len = read_smb_length(fd,buffer,timeout); if (len == -1) return(False); if (len > BUFFER_SIZE) { DEBUG(0,("Invalid packet length! (%d bytes)\n",len)); if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) exit(1); } ok = (read_data(fd,buffer+4,len) == len); if (!ok) { close_sockets(); exit(1); } return(True); } /**************************************************************************** send an smb to a fd ****************************************************************************/ BOOL send_smb(int fd,char *buffer) { int len; int ret,nwritten=0; len = smb_len(buffer) + 4; while (nwritten < len) { ret = write_socket(fd,buffer+nwritten,len - nwritten); if (ret <= 0) { DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret)); close_sockets(); exit(1); } nwritten += ret; } return True; } /**************************************************************************** find a pointer to a netbios name ****************************************************************************/ char *name_ptr(char *buf,int ofs) { unsigned char c = *(unsigned char *)(buf+ofs); if ((c & 0xC0) == 0xC0) { uint16 l; char p[2]; memcpy(p,buf+ofs,2); p[0] &= ~0xC0; l = RSVAL(p,0); DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l)); return(buf + l); } else return(buf+ofs); } /**************************************************************************** extract a netbios name from a buf ****************************************************************************/ int name_extract(char *buf,int ofs,char *name) { char *p = name_ptr(buf,ofs); int d = PTR_DIFF(p,buf+ofs); strcpy(name,""); if (d < -50 || d > 50) return(0); return(name_interpret(p,name)); } /**************************************************************************** return the total storage length of a mangled name ****************************************************************************/ int name_len(char *s) { char *s0=s; unsigned char c = *(unsigned char *)s; if ((c & 0xC0) == 0xC0) return(2); while (*s) s += (*s)+1; return(PTR_DIFF(s,s0)+1); } /**************************************************************************** send a single packet to a port on another machine ****************************************************************************/ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type) { BOOL ret; int out_fd; struct sockaddr_in sock_out; if (passive) return(True); /* create a socket to write to */ out_fd = socket(AF_INET, type, 0); if (out_fd == -1) { DEBUG(0,("socket failed")); return False; } /* set the address and port */ bzero((char *)&sock_out,sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)&ip); sock_out.sin_port = htons( port ); sock_out.sin_family = AF_INET; if (DEBUGLEVEL > 0) DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n", len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM")); /* send it */ ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0); if (!ret) DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n", inet_ntoa(ip),port,errno)); close(out_fd); return(ret); } /******************************************************************* sleep for a specified number of milliseconds ********************************************************************/ void msleep(int t) { int tdiff=0; struct timeval tval,t1,t2; fd_set fds; GetTimeOfDay(&t1); GetTimeOfDay(&t2); while (tdiff < t) { tval.tv_sec = (t-tdiff)/1000; tval.tv_usec = 1000*((t-tdiff)%1000); FD_ZERO(&fds); errno = 0; sys_select(&fds,&tval); GetTimeOfDay(&t2); tdiff = TvalDiff(&t1,&t2); } } /**************************************************************************** check if a string is part of a list ****************************************************************************/ BOOL in_list(char *s,char *list,BOOL casesensitive) { pstring tok; char *p=list; if (!list) return(False); while (next_token(&p,tok,LIST_SEP)) { if (casesensitive) { if (strcmp(tok,s) == 0) return(True); } else { if (StrCaseCmp(tok,s) == 0) return(True); } } return(False); } /* this is used to prevent lots of mallocs of size 1 */ static char *null_string = NULL; /**************************************************************************** set a string value, allocing the space for the string ****************************************************************************/ BOOL string_init(char **dest,char *src) { int l; if (!src) src = ""; l = strlen(src); if (l == 0) { if (!null_string) null_string = (char *)malloc(1); *null_string = 0; *dest = null_string; } else { *dest = (char *)malloc(l+1); strcpy(*dest,src); } return(True); } /**************************************************************************** free a string value ****************************************************************************/ void string_free(char **s) { if (!s || !(*s)) return; if (*s == null_string) *s = NULL; if (*s) free(*s); *s = NULL; } /**************************************************************************** set a string value, allocing the space for the string, and deallocating any existing space ****************************************************************************/ BOOL string_set(char **dest,char *src) { string_free(dest); return(string_init(dest,src)); } /**************************************************************************** substitute a string for a pattern in another string. Make sure there is enough room! This routine looks for pattern in s and replaces it with insert. It may do multiple replacements. return True if a substitution was done. ****************************************************************************/ BOOL string_sub(char *s,char *pattern,char *insert) { BOOL ret = False; char *p; int ls,lp,li; if (!insert || !pattern || !s) return(False); ls = strlen(s); lp = strlen(pattern); li = strlen(insert); if (!*pattern) return(False); while (lp <= ls && (p = strstr(s,pattern))) { ret = True; memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp)); memcpy(p,insert,li); s = p + li; ls = strlen(s); } return(ret); } /********************************************************* * Recursive routine that is called by mask_match. * Does the actual matching. *********************************************************/ BOOL do_match(char *str, char *regexp, int case_sig) { char *p; for( p = regexp; *p && *str; ) { switch(*p) { case '?': str++; p++; break; case '*': /* Look for a character matching the one after the '*' */ p++; if(!*p) return True; /* Automatic match */ while(*str) { while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str)))) str++; if(do_match(str,p,case_sig)) return True; if(!*str) return False; else str++; } return False; default: if(case_sig) { if(*str != *p) return False; } else { if(toupper(*str) != toupper(*p)) return False; } str++, p++; break; } } if(!*p && !*str) return True; if (!*p && str[0] == '.' && str[1] == 0) return(True); if (!*str && *p == '?') { while (*p == '?') p++; return(!*p); } if(!*str && (*p == '*' && p[1] == '\0')) return True; return False; } /********************************************************* * Routine to match a given string with a regexp - uses * simplified regexp that takes * and ? only. Case can be * significant or not. *********************************************************/ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) { char *p; pstring p1, p2; fstring ebase,eext,sbase,sext; BOOL matched; /* Make local copies of str and regexp */ StrnCpy(p1,regexp,sizeof(pstring)-1); StrnCpy(p2,str,sizeof(pstring)-1); if (!strchr(p2,'.')) { strcat(p2,"."); } /* if (!strchr(p1,'.')) { strcat(p1,"."); } */ #if 0 if (strchr(p1,'.')) { string_sub(p1,"*.*","*"); string_sub(p1,".*","*"); } #endif /* Remove any *? and ** as they are meaningless */ for(p = p1; *p; p++) while( *p == '*' && (p[1] == '?' ||p[1] == '*')) (void)strcpy( &p[1], &p[2]); if (strequal(p1,"*")) return(True); DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig)); if (trans2) { strcpy(ebase,p1); strcpy(sbase,p2); } else { if ((p=strrchr(p1,'.'))) { *p = 0; strcpy(ebase,p1); strcpy(eext,p+1); } else { strcpy(ebase,p1); eext[0] = 0; } if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) { *p = 0; strcpy(sbase,p2); strcpy(sext,p+1); } else { strcpy(sbase,p2); strcpy(sext,""); } } matched = do_match(sbase,ebase,case_sig) && (trans2 || do_match(sext,eext,case_sig)); DEBUG(5,("mask_match returning %d\n", matched)); return matched; } #ifndef SCANNER /**************************************************************************** become a daemon, discarding the controlling terminal ****************************************************************************/ void become_daemon(void) { #ifndef NO_FORK_DEBUG if (fork()) exit(0); /* detach from the terminal */ #ifdef USE_SETSID setsid(); #else #ifdef TIOCNOTTY { int i = open("/dev/tty", O_RDWR); if (i >= 0) { ioctl(i, (int) TIOCNOTTY, (char *)0); close(i); } } #endif #endif #endif } #endif /* SCANNER */ /**************************************************************************** calculate the default netmask for an address ****************************************************************************/ static void default_netmask(struct in_addr *inm, struct in_addr *iad) { unsigned long ad = ntohl(iad->s_addr); unsigned long nm; /* ** Guess a netmask based on the class of the IP address given. */ if ( (ad & 0x80000000) == 0 ) { /* class A address */ nm = 0xFF000000; } else if ( (ad & 0xC0000000) == 0x80000000 ) { /* class B address */ nm = 0xFFFF0000; } else if ( (ad & 0xE0000000) == 0xC0000000 ) { /* class C address */ nm = 0xFFFFFF00; } else { /* class D or E; netmask doesn't make much sense - guess 4 bits */ nm = 0xFFFFFFF0; } inm->s_addr = htonl(nm); } /**************************************************************************** get the broadcast address for our address (troyer@saifr00.ateng.az.honeywell.com) ****************************************************************************/ void get_broadcast(struct in_addr *if_ipaddr, struct in_addr *if_bcast, struct in_addr *if_nmask) { BOOL found = False; #ifndef NO_GET_BROADCAST int sock = -1; /* AF_INET raw socket desc */ char buff[1024]; struct ifreq *ifr=NULL; int i; #if defined(EVEREST) int n_interfaces; struct ifconf ifc; struct ifreq *ifreqs; #elif defined(USE_IFREQ) struct ifreq ifreq; struct strioctl strioctl; struct ifconf *ifc; #else struct ifconf ifc; #endif #endif /* get a default netmask and broadcast */ default_netmask(if_nmask, if_ipaddr); #ifndef NO_GET_BROADCAST /* Create a socket to the INET kernel. */ #if USE_SOCKRAW if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0) #else if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0) #endif { DEBUG(0,( "Unable to open socket to get broadcast address\n")); return; } /* Get a list of the configured interfaces */ #ifdef EVEREST /* This is part of SCO Openserver 5: The ioctls are no longer part if the lower level STREAMS interface glue. They are now real ioctl calls */ if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) { DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno))); } else { DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces)); ifc.ifc_len = sizeof(struct ifreq) * n_interfaces; ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len); if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno))); else { ifr = ifc.ifc_req; for (i = 0; i < n_interfaces; ++i) { if (if_ipaddr->s_addr == ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) { found = True; break; } } } } #elif defined(USE_IFREQ) ifc = (struct ifconf *)buff; ifc->ifc_len = BUFSIZ - sizeof(struct ifconf); strioctl.ic_cmd = SIOCGIFCONF; strioctl.ic_dp = (char *)ifc; strioctl.ic_len = sizeof(buff); if (ioctl(sock, I_STR, &strioctl) < 0) { DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno))); } else { ifr = (struct ifreq *)ifc->ifc_req; /* Loop through interfaces, looking for given IP address */ for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { if (if_ipaddr->s_addr == (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { found = True; break; } } } #elif defined(__FreeBSD__) || defined(NETBSD) || defined(OPENBSD) ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno))); } else { ifr = ifc.ifc_req; /* Loop through interfaces, looking for given IP address */ i = ifc.ifc_len; while (i > 0) { if (if_ipaddr->s_addr == (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { found = True; break; } i -= ifr->ifr_addr.sa_len + IFNAMSIZ; ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ); } } #else ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno))); } else { ifr = ifc.ifc_req; /* Loop through interfaces, looking for given IP address */ for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { #ifdef BSDI if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break; #endif if (if_ipaddr->s_addr == (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { found = True; break; } } } #endif if (!found) { DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr))); } else { /* Get the netmask address from the kernel */ #ifdef USE_IFREQ ifreq = *ifr; strioctl.ic_cmd = SIOCGIFNETMASK; strioctl.ic_dp = (char *)&ifreq; strioctl.ic_len = sizeof(struct ifreq); if (ioctl(sock, I_STR, &strioctl) < 0) DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno))); else *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; #else if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0) DEBUG(0,("SIOCGIFNETMASK failed\n")); else *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; #endif DEBUG(2,("Netmask for %s = %s\n", ifr->ifr_name, inet_ntoa(*if_nmask))); } /* Close up shop */ (void) close(sock); #endif /* sanity check on the netmask */ { unsigned long nm = ntohl(if_nmask->s_addr); if ((nm >> 24) != 0xFF) { DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask))); default_netmask(if_nmask, if_ipaddr); } } /* derive the broadcast assuming a 1's broadcast, as this is what all MS operating systems do, we have to comply even if the unix box is setup differently */ { unsigned long ad = ntohl(if_ipaddr->s_addr); unsigned long nm = ntohl(if_nmask->s_addr); unsigned long bc = (ad & nm) | (0xffffffff & ~nm); if_bcast->s_addr = htonl(bc); } DEBUG(2,("Derived broadcast address %s\n", inet_ntoa(*if_bcast))); } /* get_broadcast */ /**************************************************************************** put up a yes/no prompt ****************************************************************************/ BOOL yesno(char *p) { pstring ans; printf("%s",p); if (!fgets(ans,sizeof(ans)-1,stdin)) return(False); if (*ans == 'y' || *ans == 'Y') return(True); return(False); } /**************************************************************************** read a line from a file with possible \ continuation chars. Blanks at the start or end of a line are stripped. The string will be allocated if s2 is NULL ****************************************************************************/ char *fgets_slash(char *s2,int maxlen,FILE *f) { char *s=s2; int len = 0; int c; BOOL start_of_line = True; if (feof(f)) return(NULL); if (!s2) { maxlen = MIN(maxlen,8); s = (char *)Realloc(s,maxlen); } if (!s || maxlen < 2) return(NULL); *s = 0; while (len < maxlen-1) { c = getc(f); switch (c) { case '\r': break; case '\n': while (len > 0 && s[len-1] == ' ') { s[--len] = 0; } if (len > 0 && s[len-1] == '\\') { s[--len] = 0; start_of_line = True; break; } return(s); case EOF: if (len <= 0 && !s2) free(s); return(len>0?s:NULL); case ' ': if (start_of_line) break; default: start_of_line = False; s[len++] = c; s[len] = 0; } if (!s2 && len > maxlen-3) { maxlen *= 2; s = (char *)Realloc(s,maxlen); if (!s) return(NULL); } } return(s); } /**************************************************************************** set the length of a file from a filedescriptor. Returns 0 on success, -1 on failure. ****************************************************************************/ int set_filelen(int fd, long len) { /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot extend a file with ftruncate. Provide alternate implementation for this */ #if FTRUNCATE_CAN_EXTEND return ftruncate(fd, len); #else struct stat st; char c = 0; long currpos = lseek(fd, 0L, SEEK_CUR); if(currpos < 0) return -1; /* Do an fstat to see if the file is longer than the requested size (call ftruncate), or shorter, in which case seek to len - 1 and write 1 byte of zero */ if(fstat(fd, &st)<0) return -1; #ifdef S_ISFIFO if (S_ISFIFO(st.st_mode)) return 0; #endif if(st.st_size == len) return 0; if(st.st_size > len) return ftruncate(fd, len); if(lseek(fd, len-1, SEEK_SET) != len -1) return -1; if(write(fd, &c, 1)!=1) return -1; /* Seek to where we were */ lseek(fd, currpos, SEEK_SET); return 0; #endif } /**************************************************************************** return the byte checksum of some data ****************************************************************************/ int byte_checksum(char *buf,int len) { unsigned char *p = (unsigned char *)buf; int ret = 0; while (len--) ret += *p++; return(ret); } #ifdef HPUX /**************************************************************************** this is a version of setbuffer() for those machines that only have setvbuf ****************************************************************************/ void setbuffer(FILE *f,char *buf,int bufsize) { setvbuf(f,buf,_IOFBF,bufsize); } #endif /**************************************************************************** parse out a directory name from a path name. Assumes dos style filenames. ****************************************************************************/ char *dirname_dos(char *path,char *buf) { char *p = strrchr(path,'\\'); if (!p) strcpy(buf,path); else { *p = 0; strcpy(buf,path); *p = '\\'; } return(buf); } /**************************************************************************** parse out a filename from a path name. Assumes dos style filenames. ****************************************************************************/ static char *filename_dos(char *path,char *buf) { char *p = strrchr(path,'\\'); if (!p) strcpy(buf,path); else strcpy(buf,p+1); return(buf); } /**************************************************************************** expand a pointer to be a particular size ****************************************************************************/ void *Realloc(void *p,int size) { void *ret=NULL; if (!p) ret = (void *)malloc(size); else ret = (void *)realloc(p,size); if (!ret) DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size)); return(ret); } /**************************************************************************** set the time on a file ****************************************************************************/ BOOL set_filetime(char *fname,time_t mtime) { struct utimbuf times; if (null_mtime(mtime)) return(True); times.modtime = times.actime = mtime; if (sys_utime(fname,×)) { DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); } return(True); } #ifdef NOSTRDUP /**************************************************************************** duplicate a string ****************************************************************************/ char *strdup(char *s) { char *ret = NULL; if (!s) return(NULL); ret = (char *)malloc(strlen(s)+1); if (!ret) return(NULL); strcpy(ret,s); return(ret); } #endif #ifndef SCANNER /**************************************************************************** Signal handler for SIGPIPE (write on a disconnected socket) ****************************************************************************/ void Abort(void ) { DEBUG(0,("Probably got SIGPIPE\nExiting\n")); exit(2); } #endif /* SCANNER */ #ifdef REPLACE_STRLEN /**************************************************************************** a replacement strlen() that returns int for solaris ****************************************************************************/ int Strlen(char *s) { int ret=0; if (!s) return(0); while (*s++) ret++; return(ret); } #endif /**************************************************************************** return a time at the start of the current month ****************************************************************************/ time_t start_of_month(void) { time_t t = time(NULL); struct tm *t2; t2 = gmtime(&t); t2->tm_mday = 1; t2->tm_hour = 0; t2->tm_min = 0; t2->tm_sec = 0; return(mktime(t2)); } /******************************************************************* check for a sane unix date ********************************************************************/ BOOL sane_unix_date(time_t unixdate) { struct tm t,today; time_t t_today = time(NULL); t = *(LocalTime(&unixdate,LOCAL_TO_GMT)); today = *(LocalTime(&t_today,LOCAL_TO_GMT)); if (t.tm_year < 80) return(False); if (t.tm_year > today.tm_year) return(False); if (t.tm_year == today.tm_year && t.tm_mon > today.tm_mon) return(False); if (t.tm_year == today.tm_year && t.tm_mon == today.tm_mon && t.tm_mday > (today.tm_mday+1)) return(False); return(True); } #ifdef NO_FTRUNCATE /******************************************************************* ftruncate for operating systems that don't have it ********************************************************************/ int ftruncate(int f,long l) { struct flock fl; fl.l_whence = 0; fl.l_len = 0; fl.l_start = l; fl.l_type = F_WRLCK; return fcntl(f, F_FREESP, &fl); } #endif /**************************************************************************** get my own name and IP ****************************************************************************/ BOOL get_myname(char *myname,struct in_addr *ip) { struct hostent *hp; pstring hostname; *hostname = 0; /* get my host name */ if (gethostname(hostname, MAXHOSTNAMELEN) == -1) { DEBUG(0,("gethostname failed\n")); return False; } /* get host info */ if ((hp = Get_Hostbyname(hostname)) == 0) { DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname)); return False; } if (myname) { /* split off any parts after an initial . */ char *p = strchr(hostname,'.'); if (p) *p = 0; strcpy(myname,hostname); } if (ip) putip((char *)ip,(char *)hp->h_addr); return(True); } /**************************************************************************** true if two IP addresses are equal ****************************************************************************/ BOOL ip_equal(struct in_addr ip1,struct in_addr ip2) { unsigned long a1,a2; a1 = ntohl(ip1.s_addr); a2 = ntohl(ip2.s_addr); return(a1 == a2); } /**************************************************************************** open a socket of the specified type, port and address for incoming data ****************************************************************************/ int open_socket_in(int type, int port, int dlevel) { struct hostent *hp; struct sockaddr_in sock; pstring host_name; int res; #ifdef SCANNER /* skip all this lookup nonsense and just plug the stuff in like our IQ was normal, eh? */ bzero ((char *)&sock, sizeof (sock)); sock.sin_port = htons (port); sock.sin_family = AF_INET; sock.sin_addr.s_addr = INADDR_ANY; res = socket (AF_INET, type, 0); #else /* get my host name */ #ifdef MAXHOSTNAMELEN if (gethostname(host_name, MAXHOSTNAMELEN) == -1) #else if (gethostname(host_name, sizeof(host_name)) == -1) #endif { DEBUG(0,("gethostname failed\n")); return -1; } /* get host info */ if ((hp = Get_Hostbyname(host_name)) == 0) { DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name)); return -1; } bzero((char *)&sock,sizeof(sock)); memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length); #if defined(__FreeBSD__) || defined(NETBSD) || defined(OPENBSD) sock.sin_len = sizeof(sock); #endif sock.sin_port = htons( port ); sock.sin_family = hp->h_addrtype; sock.sin_addr.s_addr = INADDR_ANY; res = socket(hp->h_addrtype, type, 0); #endif /* SCANNER */ if (res == -1) { DEBUG(0,("socket failed\n")); return -1; } { int one=1; setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); } /* now we've got a socket - we need to bind it */ if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { if (port) { if (port == 139 || port == 137) DEBUG(dlevel,("bind failed on port %d (%s)\n", port,strerror(errno))); close(res); if (dlevel > 0 && port < 1000) port = 7999; if (port >= 1000 && port < 9000) return(open_socket_in(type,port+1,dlevel)); } return(-1); } DEBUG(3,("bind succeeded on port %d\n",port)); return res; } /**************************************************************************** create an outgoing socket **************************************************************************/ int open_socket_out(int type, struct in_addr *addr, int port ) { struct sockaddr_in sock_out; int res; /* create a socket to write to */ res = socket(PF_INET, type, 0); if (res == -1) { DEBUG(0,("socket error\n")); return -1; } if (type != SOCK_STREAM) return(res); bzero((char *)&sock_out,sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)addr); sock_out.sin_port = htons( port ); sock_out.sin_family = PF_INET; DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); /* and connect it to the destination */ if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0) { DEBUG(0,("connect error: %s\n",strerror(errno))); close(res); return(-1); } return res; } /**************************************************************************** interpret a protocol description string, with a default ****************************************************************************/ int interpret_protocol(char *str,int def) { if (strequal(str,"NT1")) return(PROTOCOL_NT1); if (strequal(str,"LANMAN2")) return(PROTOCOL_LANMAN2); if (strequal(str,"LANMAN1")) return(PROTOCOL_LANMAN1); if (strequal(str,"CORE")) return(PROTOCOL_CORE); if (strequal(str,"COREPLUS")) return(PROTOCOL_COREPLUS); if (strequal(str,"CORE+")) return(PROTOCOL_COREPLUS); DEBUG(0,("Unrecognised protocol level %s\n",str)); return(def); } /**************************************************************************** interpret a security level ****************************************************************************/ int interpret_security(char *str,int def) { if (strequal(str,"SERVER")) return(SEC_SERVER); if (strequal(str,"USER")) return(SEC_USER); if (strequal(str,"SHARE")) return(SEC_SHARE); DEBUG(0,("Unrecognised security level %s\n",str)); return(def); } /**************************************************************************** interpret an internet address or name into an IP address in 4 byte form ****************************************************************************/ unsigned long interpret_addr(char *str) { struct hostent *hp; unsigned long res; if (strcmp(str,"0.0.0.0") == 0) return(0); if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF); /* SCANNER: XXX: wrong assumption! what about 3com.com... */ /* should return struct in_addr, too, even if it *is* ulong */ /* if it's in the form of an IP address then get the lib to interpret it */ if (isdigit(str[0])) { res = inet_addr(str); } else { /* otherwise assume it's a network name of some sort and use Get_Hostbyname */ if ((hp = Get_Hostbyname(str)) == 0) { DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str)); return 0; } putip((char *)&res,(char *)hp->h_addr); } if (res == (unsigned long)-1) return(0); return(res); } #ifdef SCANNER #define GH_SLEAZE 1 #ifdef GH_SLEAZE #include jmp_buf gh_buf; static void tmx() { longjmp (gh_buf, 1); } #endif /* GH_SLEAZE */ char * Get_Hostbyaddr (struct in_addr ip) { static char outbuf [MAXHOSTNAMELEN + 4]; /* reused on every call */ struct hostent * hp; if (zero_ip (ip)) return (NULL); #ifdef GH_SLEAZE signal (SIGALRM, tmx); alarm (5); if (setjmp (gh_buf) > 0) return (NULL); #endif hp = gethostbyaddr ((char *) &ip, sizeof (struct in_addr), AF_INET); #ifdef GH_SLEAZE signal (SIGALRM, SIG_DFL); alarm (0); #endif if (hp && (hp->h_name)) { strncpy (outbuf, hp->h_name, MAXHOSTNAMELEN); outbuf[MAXHOSTNAMELEN] = '\0'; strupper (outbuf); return (outbuf); } return (NULL); } /* Get_Hostbyaddr */ #endif /* SCANNER */ /******************************************************************* a convenient addition to interpret_addr() ******************************************************************/ struct in_addr *interpret_addr2(char *str) { static struct in_addr ret; unsigned long a = interpret_addr(str); putip((char *)&ret,(char *)&a); return(&ret); } /******************************************************************* check if an IP is the 0.0.0.0 ******************************************************************/ BOOL zero_ip(struct in_addr ip) { unsigned long a; putip((char *)&a,(char *)&ip); return(a == 0); } #define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60)) /**************************************************************************** interpret an 8 byte "filetime" structure to a time_t It's originally in "100ns units since jan 1st 1601" It appears to be kludge-GMT (at least for file listings). This means its the GMT you get by taking a localtime and adding the serverzone. This is NOT the same as GMT in some cases. This routine converts this to real GMT. ****************************************************************************/ time_t interpret_long_date(char *p) { double d; time_t ret; uint32 tlow,thigh; tlow = IVAL(p,0); thigh = IVAL(p,4); if (thigh == 0) return(0); d = ((double)thigh)*4.0*(double)(1<<30); d += (tlow&0xFFF00000); d *= 1.0e-7; /* now adjust by 369 years to make the secs since 1970 */ d -= TIME_FIXUP_CONSTANT; if (d>=MAXINT) return(0); ret = (time_t)(d+0.5); /* this takes us from kludge-GMT to real GMT */ ret += TimeDiff(ret) - serverzone; return(ret); } /**************************************************************************** put a 8 byte filetime from a time_t This takes real GMT as input and converts to kludge-GMT ****************************************************************************/ void put_long_date(char *p,time_t t) { uint32 tlow,thigh; double d; if (t==0) { SIVAL(p,0,0); SIVAL(p,4,0); return; } /* this converts GMT to kludge-GMT */ t -= TimeDiff(t) - serverzone; d = (double) (t); d += TIME_FIXUP_CONSTANT; d *= 1.0e7; thigh = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); tlow = (uint32)(d - ((double)thigh)*4.0*(double)(1<<30)); SIVAL(p,0,tlow); SIVAL(p,4,thigh); } /******************************************************************* sub strings with useful parameters ********************************************************************/ void standard_sub_basic(char *s) { if (!strchr(s,'%')) return; string_sub(s,"%R",remote_proto); string_sub(s,"%a",remote_arch); string_sub(s,"%m",remote_machine); string_sub(s,"%L",local_machine); if (!strchr(s,'%')) return; string_sub(s,"%v",VERSION); string_sub(s,"%h",myhostname); string_sub(s,"%U",sesssetup_user); if (!strchr(s,'%')) return; string_sub(s,"%I",Client_info.addr); string_sub(s,"%M",Client_info.name); string_sub(s,"%T",timestring()); if (!strchr(s,'%')) return; { char pidstr[10]; sprintf(pidstr,"%d",(int)getpid()); string_sub(s,"%d",pidstr); } } /******************************************************************* write a string in unicoode format ********************************************************************/ void PutUniCode(char *dst,char *src) { while (*src) { dst[0] = src[0]; dst[1] = 0; dst += 2; src++; } dst[0] = dst[1] = 0; } /**************************************************************************** a wrapper for gethostbyname() that tries with all lower and all upper case if the initial name fails ****************************************************************************/ struct hostent *Get_Hostbyname(char *name) { char *name2 = strdup(name); struct hostent *ret; if (!name2) { DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n")); exit(0); } if (!isalnum(*name2)) { free(name2); return(NULL); } #ifdef GH_SLEAZE signal (SIGALRM, tmx); alarm (5); if (setjmp (gh_buf) > 0) return (NULL); #endif ret = gethostbyname(name2); #ifdef GH_SLEAZE signal (SIGALRM, SIG_DFL); alarm (0); #endif if (ret != NULL) { free(name2); return(ret); } /* try with all lowercase */ strlower(name2); ret = gethostbyname(name2); if (ret != NULL) { free(name2); return(ret); } /* try with all uppercase */ strupper(name2); ret = gethostbyname(name2); if (ret != NULL) { free(name2); return(ret); } /* nothing works :-( */ free(name2); return(NULL); } /**************************************************************************** check if a process exists. Does this work on all unixes? ****************************************************************************/ BOOL process_exists(int pid) { #ifdef LINUX fstring s; sprintf(s,"/proc/%d",pid); return(directory_exist(s,NULL)); #else { static BOOL tested=False; static BOOL ok=False; fstring s; if (!tested) { tested = True; sprintf(s,"/proc/%05d",getpid()); ok = file_exist(s,NULL); } if (ok) { sprintf(s,"/proc/%05d",pid); return(file_exist(s,NULL)); } } /* a best guess for non root access */ if (geteuid() != 0) return(True); /* otherwise use kill */ return(pid == getpid() || kill(pid,0) == 0); #endif } /******************************************************************* turn a uid into a user name ********************************************************************/ char *uidtoname(int uid) { static char name[20]; struct passwd *pass = getpwuid(uid); if (pass) return(pass->pw_name); sprintf(name,"%d",uid); return(name); } /******************************************************************* turn a gid into a group name ********************************************************************/ char *gidtoname(int gid) { static char name[20]; struct group *grp = getgrgid(gid); if (grp) return(grp->gr_name); sprintf(name,"%d",gid); return(name); } /******************************************************************* block sigs ********************************************************************/ void BlockSignals(BOOL block) { #ifdef USE_SIGBLOCK int block_mask = (sigmask(SIGTERM)|sigmask(SIGQUIT)|sigmask(SIGSEGV) |sigmask(SIGCHLD)|sigmask(SIGQUIT)|sigmask(SIGBUS)| sigmask(SIGINT)); if (block) sigblock(block_mask); else sigunblock(block_mask); #endif } #ifdef USE_DIRECT #define DIRECT direct #else #define DIRECT dirent #endif /******************************************************************* a readdir wrapper which just returns the file name also return the inode number if requested ********************************************************************/ char *readdirname(void *p) { struct DIRECT *ptr; char *dname; if (!p) return(NULL); ptr = (struct DIRECT *)readdir(p); if (!ptr) return(NULL); dname = ptr->d_name; #ifdef KANJI { static pstring buf; strcpy(buf, dname); unix_to_dos(buf, True); dname = buf; } #endif #ifdef NEXT2 if (telldir(p) < 0) return(NULL); #endif #ifdef SUNOS5 /* this handles a broken compiler setup, causing a mixture of BSD and SYSV headers and libraries */ { static BOOL broken_readdir = False; if (!broken_readdir && !(*(dname)) && strequal("..",dname-2)) { DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n")); broken_readdir = True; } if (broken_readdir) return(dname-2); } #endif return(dname); } #if (defined(SecureWare) && defined(SCO)) /* This is needed due to needing the nap() function but we don't want to include the Xenix libraries since that will break other things... BTW: system call # 0x0c28 is the same as calling nap() */ long nap(long milliseconds) { return syscall(0x0c28, milliseconds); } #endif #ifdef NO_INITGROUPS #include #include #include #ifndef NULL #define NULL (void *)0 #endif /**************************************************************************** some systems don't have an initgroups call ****************************************************************************/ int initgroups(char *name,gid_t id) { #ifdef NO_SETGROUPS /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ return(0); #else gid_t grouplst[NGROUPS_MAX]; int i,j; struct group *g; char *gr; grouplst[0] = id; i = 1; while (i < NGROUPS_MAX && ((g = (struct group *)getgrent()) != (struct group *)NULL)) { if (g->gr_gid == id) continue; j = 0; gr = g->gr_mem[0]; while (gr && (*gr != (char)NULL)) { if (strcmp(name,gr) == 0) { grouplst[i] = g->gr_gid; i++; gr = (char *)NULL; break; } gr = g->gr_mem[++j]; } } endgrent(); return(setgroups(i,grouplst)); #endif } #endif #if WRAP_MALLOC /* undo the wrapping temporarily */ #undef malloc #undef realloc #undef free /**************************************************************************** wrapper for malloc() to catch memory errors ****************************************************************************/ void *malloc_wrapped(int size,char *file,int line) { #ifdef xx_old_malloc void *res = xx_old_malloc(size); #else void *res = malloc(size); #endif DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n", file,line, size,(unsigned int)res)); return(res); } /**************************************************************************** wrapper for realloc() to catch memory errors ****************************************************************************/ void *realloc_wrapped(void *ptr,int size,char *file,int line) { #ifdef xx_old_realloc void *res = xx_old_realloc(ptr,size); #else void *res = realloc(ptr,size); #endif DEBUG(3,("Realloc\n")); DEBUG(3,("free called from %s(%d) with ptr=0x%X\n", file,line, (unsigned int)ptr)); DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n", file,line, size,(unsigned int)res)); return(res); } /**************************************************************************** wrapper for free() to catch memory errors ****************************************************************************/ void free_wrapped(void *ptr,char *file,int line) { #ifdef xx_old_free xx_old_free(ptr); #else free(ptr); #endif DEBUG(3,("free called from %s(%d) with ptr=0x%X\n", file,line,(unsigned int)ptr)); return; } /* and re-do the define for spots lower in this file */ #define malloc(size) malloc_wrapped(size,__FILE__,__LINE__) #define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__) #define free(ptr) free_wrapped(ptr,__FILE__,__LINE__) #endif #ifdef REPLACE_STRSTR /**************************************************************************** Mips version of strstr doesn't seem to work correctly. There is a #define in includes.h to redirect calls to this function. ****************************************************************************/ char *Strstr(char *s, char *p) { int len = strlen(p); while ( *s != '\0' ) { if ( strncmp(s, p, len) == 0 ) return s; s++; } return NULL; } #endif /* REPLACE_STRSTR */ #ifdef REPLACE_MKTIME /******************************************************************* a mktime() replacement for those who don't have it - contributed by C.A. Lademann ********************************************************************/ #define MINUTE 60 #define HOUR 60*MINUTE #define DAY 24*HOUR #define YEAR 365*DAY time_t Mktime(struct tm *t) { struct tm *u; time_t epoch = 0; int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, y, m, i; if(t->tm_year < 70) return((time_t)-1); epoch = (t->tm_year - 70) * YEAR + (t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY; y = t->tm_year; m = 0; for(i = 0; i < t->tm_mon; i++) { epoch += mon [m] * DAY; if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) epoch += DAY; if(++m > 11) { m = 0; y++; } } epoch += (t->tm_mday - 1) * DAY; epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; if((u = localtime(&epoch)) != NULL) { t->tm_sec = u->tm_sec; t->tm_min = u->tm_min; t->tm_hour = u->tm_hour; t->tm_mday = u->tm_mday; t->tm_mon = u->tm_mon; t->tm_year = u->tm_year; t->tm_wday = u->tm_wday; t->tm_yday = u->tm_yday; t->tm_isdst = u->tm_isdst; #ifndef NO_TM_NAME memcpy(t->tm_name, u->tm_name, LTZNMAX); #endif } return(epoch); } #endif /* REPLACE_MKTIME */ #ifdef REPLACE_RENAME /* Rename a file. (from libiberty in GNU binutils) */ int rename (zfrom, zto) const char *zfrom; const char *zto; { if (link (zfrom, zto) < 0) { if (errno != EEXIST) return -1; if (unlink (zto) < 0 || link (zfrom, zto) < 0) return -1; } return unlink (zfrom); } #endif #ifdef REPLACE_INNETGR /* * Search for a match in a netgroup. This replaces it on broken systems. */ int InNetGr(group, host, user, dom) char *group, *host, *user, *dom; { char *hst, *usr, *dm; setnetgrent(group); while (getnetgrent(&hst, &usr, &dm)) if (((host == 0) || (hst == 0) || !strcmp(host, hst)) && ((user == 0) || (usr == 0) || !strcmp(user, usr)) && ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) { endnetgrent(); return (1); } endnetgrent(); return (0); } #endif #if WRAP_MEMCPY #undef memcpy /******************************************************************* a wrapper around memcpy for diagnostic purposes ********************************************************************/ void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line) { if (l>64 && (((int)d)%4) != (((int)s)%4)) DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line)); #ifdef xx_old_memcpy return(xx_old_memcpy(d,s,l)); #else return(memcpy(d,s,l)); #endif } #define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__) #endif nat-1.0.orig/userlist.txt0100600000175000017500000000012006301746754016542 0ustar jfernandezjfernandezADMINISTRATOR GUEST BACKUP ROOT ADMIN USER DEMO TEST SYSTEM OPERATOR OPER LOCAL nat-1.0.orig/system.c0100600000175000017500000001400006301746754015621 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. Samba system utilities Copyright (C) Andrew Tridgell 1992-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" /* The idea is that this file will eventually have wrappers around all important system calls in samba. The aim is twofold: - to enable easier porting by putting OS dependent stuff in here - to allow for hooks into other "pseudo-filesystems" - to allow easier integration of things like the japanese extensions */ /******************************************************************* this replaces the normal select() system call return if some data has arrived on one of the file descriptors return -1 means error ********************************************************************/ #ifdef NO_SELECT static int pollfd(int fd) { int r=0; #ifdef HAS_RDCHK r = rdchk(fd); #endif #ifdef HAS_TCRDCHK (void)ioctl(fd, TCRDCHK, &r); #endif #ifdef HAS_FIONREAD (void)ioctl(fd, FIONREAD, &r); #endif return(r); } int sys_select(fd_set *fds,struct timeval *tval) { fd_set fds2; int counter=0; int found=0; FD_ZERO(&fds2); while (1) { int i; for (i=0;i<255;i++) { if (FD_ISSET(i,fds) && pollfd(i)>0) { found++; FD_SET(i,&fds2); } } if (found) { memcpy((void *)fds,(void *)&fds2,sizeof(fds2)); return(found); } if (tval && tval.tv_sec < counter) return(0); sleep(1); counter++; } } #else int sys_select(fd_set *fds,struct timeval *tval) { struct timeval t2; int selrtn; do { if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2)); errno = 0; selrtn = select(FD_SETSIZE,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL); } while (selrtn<0 && errno == EINTR); return(selrtn); } #endif /******************************************************************* just a unlink wrapper ********************************************************************/ int sys_unlink(char *fname) { return(unlink(dos_to_unix(fname,False))); } /******************************************************************* a simple open() wrapper ********************************************************************/ int sys_open(char *fname,int flags,int mode) { return(open(dos_to_unix(fname,False),flags,mode)); } /******************************************************************* a simple opendir() wrapper ********************************************************************/ DIR *sys_opendir(char *dname) { return(opendir(dos_to_unix(dname,False))); } /******************************************************************* and a stat() wrapper ********************************************************************/ int sys_stat(char *fname,struct stat *sbuf) { return(stat(dos_to_unix(fname,False),sbuf)); } /******************************************************************* don't forget lstat() ********************************************************************/ int sys_lstat(char *fname,struct stat *sbuf) { return(lstat(dos_to_unix(fname,False),sbuf)); } /******************************************************************* mkdir() gets a wrapper ********************************************************************/ int sys_mkdir(char *dname,int mode) { return(mkdir(dos_to_unix(dname,False),mode)); } /******************************************************************* do does rmdir() ********************************************************************/ int sys_rmdir(char *dname) { return(rmdir(dos_to_unix(dname,False))); } /******************************************************************* I almost forgot chdir() ********************************************************************/ int sys_chdir(char *dname) { return(chdir(dos_to_unix(dname,False))); } /******************************************************************* now for utime() ********************************************************************/ int sys_utime(char *fname,struct utimbuf *times) { return(utime(dos_to_unix(fname,False),times)); } /******************************************************************* for rename() ********************************************************************/ int sys_rename(char *from, char *to) { #ifdef KANJI pstring zfrom, zto; strcpy (zfrom, dos_to_unix (from, False)); strcpy (zto, dos_to_unix (to, False)); return rename (zfrom, zto); #else return rename (from, to); #endif /* KANJI */ } /******************************************************************* chown isn't used much but OS/2 doesn't have it ********************************************************************/ int sys_chown(char *fname,int uid,int gid) { #ifdef NO_CHOWN DEBUG(1,("Warning - chown(%s,%d,%d) not done\n",fname,uid,gid)); #else return(chown(fname,uid,gid)); #endif } /******************************************************************* os/2 also doesn't have chroot ********************************************************************/ int sys_chroot(char *dname) { #ifdef _WIN32 #define NO_CHROOT 1 #endif #ifdef NO_CHROOT #ifdef _WIN32 printf("chroot called and it's not done\n"); #else DEBUG(1,("Warning - chroot(%s) not done\n",dname)); #endif #else return(chroot(dname)); #endif } nat-1.0.orig/smbpass.h0100600000175000017500000000371406301746754015764 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ #ifndef _SMBPASS_H_ #define _SMBPASS_H_ /* Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup Copyright (C) Jeremy Allison 1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ struct smb_passwd { int smb_userid; char *smb_name; unsigned char *smb_passwd; /* Null if no password */ unsigned char *smb_nt_passwd; /* Null if no password */ /* Other fields / flags may be added later */ }; /* Return a smb_passwd struct given a user name, 0 if fails. */ struct smb_passwd *get_smbpwnam(char *user); #ifndef uchar #define uchar unsigned char #endif /* SMB Encryption functions. */ void str_to_key(unsigned char *str,unsigned char *key); void E_P16(uchar *p14,uchar *p16); void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); void E_md4hash(uchar *passwd,uchar *p16); void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); void SMB_nt_encrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); /* Password file lock/unlock routines */ int pw_file_lock(char *name, int type, int secs); int pw_file_unlock(int fd); #endif nat-1.0.orig/smb.h0100600000175000017500000010434107453010623015057 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup Copyright (C) Andrew Tridgell 1992-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _SMB_H #define _SMB_H #ifdef _WIN32 #include #endif #ifndef MAX_CONNECTIONS #define MAX_CONNECTIONS 127 #endif #ifndef MAX_OPEN_FILES #define MAX_OPEN_FILES 50 #endif #ifndef GUEST_ACCOUNT #define GUEST_ACCOUNT "nobody" #endif #define BUFFER_SIZE (0xFFFF) #define SAFETY_MARGIN 1024 #ifndef EXTERN # define EXTERN extern #endif #define False (0) #define True (1) #define BOOLSTR(b) ((b) ? "Yes" : "No") #define BITSETB(ptr,bit) ((((char *)ptr)[0] & (1<<(bit)))!=0) #define BITSETW(ptr,bit) ((SVAL(ptr,0) & (1<<(bit)))!=0) #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2))) typedef int BOOL; /* Samba needs type definitions for int16, int32, uint16 and uint32. Normally these are signed and unsigned 16 and 32 bit integers, but they actually only need to be at least 16 and 32 bits respectively. Thus if your word size is 8 bytes just defining them as signed and unsigned int will work. */ /* afs/stds.h defines int16 and int32 */ #ifndef AFS_AUTH typedef short int16; typedef int int32; #endif #ifndef uint16 typedef unsigned short uint16; #endif #ifndef uint32 typedef unsigned int uint32; #endif #define SIZEOFWORD 2 #ifndef DEF_CREATE_MASK #define DEF_CREATE_MASK (0755) #endif #ifndef DEFAULT_PIPE_TIMEOUT #define DEFAULT_PIPE_TIMEOUT 10000000 /* Ten seconds */ #endif /* debugging code */ #ifndef SYSLOG #define DEBUG(level,body) ((DEBUGLEVEL>=(level))?(Debug1 body):0) #else EXTERN int syslog_level; #define DEBUG(level,body) ((DEBUGLEVEL>=(level))? \ (syslog_level = (level), Debug1 body):0) #endif #define DIR_STRUCT_SIZE 43 /* these define all the command types recognised by the server - there are lots of gaps so probably there are some rare commands that are not implemented */ #define pSETDIR '\377' /* these define the attribute byte as seen by DOS */ #define aRONLY (1L<<0) #define aHIDDEN (1L<<1) #define aSYSTEM (1L<<2) #define aVOLID (1L<<3) #define aDIR (1L<<4) #define aARCH (1L<<5) /* deny modes */ #define DENY_DOS 0 #define DENY_ALL 1 #define DENY_WRITE 2 #define DENY_READ 3 #define DENY_NONE 4 #define DENY_FCB 7 /* share types */ #define STYPE_DISKTREE 0 /* Disk drive */ #define STYPE_PRINTQ 1 /* Spooler queue */ #define STYPE_DEVICE 2 /* Serial device */ #define STYPE_IPC 3 /* Interprocess communication (IPC) */ /* SMB X/Open error codes for the ERRdos error class */ #define ERRbadfunc 1 /* Invalid function (or system call) */ #define ERRbadfile 2 /* File not found (pathname error) */ #define ERRbadpath 3 /* Directory not found */ #define ERRnofids 4 /* Too many open files */ #define ERRnoaccess 5 /* Access denied */ #define ERRbadfid 6 /* Invalid fid */ #define ERRnomem 8 /* Out of memory */ #define ERRbadmem 9 /* Invalid memory block address */ #define ERRbadenv 10 /* Invalid environment */ #define ERRbadaccess 12 /* Invalid open mode */ #define ERRbaddata 13 /* Invalid data (only from ioctl call) */ #define ERRres 14 /* reserved */ #define ERRbaddrive 15 /* Invalid drive */ #define ERRremcd 16 /* Attempt to delete current directory */ #define ERRdiffdevice 17 /* rename/move across different filesystems */ #define ERRnofiles 18 /* no more files found in file search */ #define ERRbadshare 32 /* Share mode on file conflict with open mode */ #define ERRlock 33 /* Lock request conflicts with existing lock */ #define ERRfilexists 80 /* File in operation already exists */ #define ERRbadpipe 230 /* Named pipe invalid */ #define ERRpipebusy 231 /* All instances of pipe are busy */ #define ERRpipeclosing 232 /* named pipe close in progress */ #define ERRnotconnected 233 /* No process on other end of named pipe */ #define ERRmoredata 234 /* More data to be returned */ #define ERROR_EAS_DIDNT_FIT 275 /* Extended attributes didn't fit */ #define ERROR_EAS_NOT_SUPPORTED 282 /* Extended attributes not suppored */ #define ERRunknownlevel 124 #define ERRunknownipc 2142 /* here's a special one from observing NT */ #define ERRnoipc 66 /* don't support ipc */ /* Error codes for the ERRSRV class */ #define ERRerror 1 /* Non specific error code */ #define ERRbadpw 2 /* Bad password */ #define ERRbadtype 3 /* reserved */ #define ERRaccess 4 /* No permissions to do the requested operation */ #define ERRinvnid 5 /* tid invalid */ #define ERRinvnetname 6 /* Invalid servername */ #define ERRinvdevice 7 /* Invalid device */ #define ERRqfull 49 /* Print queue full */ #define ERRqtoobig 50 /* Queued item too big */ #define ERRinvpfid 52 /* Invalid print file in smb_fid */ #define ERRsmbcmd 64 /* Unrecognised command */ #define ERRsrverror 65 /* smb server internal error */ #define ERRfilespecs 67 /* fid and pathname invalid combination */ #define ERRbadlink 68 /* reserved */ #define ERRbadpermits 69 /* Access specified for a file is not valid */ #define ERRbadpid 70 /* reserved */ #define ERRsetattrmode 71 /* attribute mode invalid */ #define ERRpaused 81 /* Message server paused */ #define ERRmsgoff 82 /* Not receiving messages */ #define ERRnoroom 83 /* No room for message */ #define ERRrmuns 87 /* too many remote usernames */ #define ERRtimeout 88 /* operation timed out */ #define ERRnoresource 89 /* No resources currently available for request. */ #define ERRtoomanyuids 90 /* too many userids */ #define ERRbaduid 91 /* bad userid */ #define ERRuseMPX 250 /* temporarily unable to use raw mode, use MPX mode */ #define ERRuseSTD 251 /* temporarily unable to use raw mode, use standard mode */ #define ERRcontMPX 252 /* resume MPX mode */ #define ERRbadPW /* reserved */ #define ERRnosupport 0xFFFF #define ERRunknownsmb 22 /* from NT 3.5 response */ /* Error codes for the ERRHRD class */ #define ERRnowrite 19 /* read only media */ #define ERRbadunit 20 /* Unknown device */ #define ERRnotready 21 /* Drive not ready */ #define ERRbadcmd 22 /* Unknown command */ #define ERRdata 23 /* Data (CRC) error */ #define ERRbadreq 24 /* Bad request structure length */ #define ERRseek 25 #define ERRbadmedia 26 #define ERRbadsector 27 #define ERRnopaper 28 #define ERRwrite 29 /* write fault */ #define ERRread 30 /* read fault */ #define ERRgeneral 31 /* General hardware failure */ #define ERRwrongdisk 34 #define ERRFCBunavail 35 #define ERRsharebufexc 36 /* share buffer exceeded */ #define ERRdiskfull 39 typedef char pstring[1024]; typedef char fstring[128]; typedef fstring string; typedef struct { int size; int mode; int uid; int gid; /* these times are normally kept in GMT */ time_t mtime; time_t atime; time_t ctime; pstring name; } file_info; /* Structure used when SMBwritebmpx is active */ typedef struct { int wr_total_written; /* So we know when to discard this */ int32 wr_timeout; int32 wr_errclass; int32 wr_error; /* Cached errors */ BOOL wr_mode; /* write through mode) */ BOOL wr_discard; /* discard all further data */ } write_bmpx_struct; typedef struct { int cnum; int fd; int pos; int size; int mode; char *mmap_ptr; int mmap_size; write_bmpx_struct *wbmpx_ptr; time_t open_time; BOOL open; BOOL can_lock; BOOL can_read; BOOL can_write; BOOL share_mode; BOOL share_pending; BOOL print_file; char *name; } files_struct; struct uid_cache { int entries; int list[UID_CACHE_SIZE]; }; typedef struct { int service; BOOL force_user; int uid; /* uid of user who *opened* this connection */ int gid; /* gid of user who *opened* this connection */ struct uid_cache uid_cache; void *dirptr; BOOL open; BOOL printer; BOOL ipc; BOOL read_only; BOOL admin_user; char *dirpath; char *connectpath; char *origpath; char *user; /* name of user who *opened* this connection */ /* following groups stuff added by ih */ /* This groups info is valid for the user that *opened* the connection */ int ngroups; gid_t *groups; int *igroups; /* an integer version - some OSes are broken :-( */ time_t lastused; BOOL used; int num_files_open; } connection_struct; typedef struct { int uid; /* uid of a validated user */ int gid; /* gid of a validated user */ fstring name; /* name of a validated user */ BOOL guest; /* following groups stuff added by ih */ /* This groups info is needed for when we become_user() for this uid */ int user_ngroups; gid_t *user_groups; int *user_igroups; /* an integer version - some OSes are broken :-( */ } user_struct; enum {LPQ_QUEUED,LPQ_PAUSED,LPQ_SPOOLING,LPQ_PRINTING}; typedef struct { int job; int size; int status; int priority; time_t time; char user[30]; char file[100]; } print_queue_struct; enum {LPSTAT_OK, LPSTAT_STOPPED, LPSTAT_ERROR}; typedef struct { fstring message; int status; } print_status_struct; /* this is used for smbstatus */ struct connect_record { int magic; int pid; int cnum; int uid; int gid; char name[24]; char addr[24]; char machine[128]; time_t start; }; #define LOCKING_VERSION 2 /* these are useful macros for checking validity of handles */ #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_OPEN_FILES)) #define OPEN_FNUM(fnum) (VALID_FNUM(fnum) && Files[fnum].open) #define VALID_CNUM(cnum) (((cnum) >= 0) && ((cnum) < MAX_CONNECTIONS)) #define OPEN_CNUM(cnum) (VALID_CNUM(cnum) && Connections[cnum].open) #define IS_IPC(cnum) (VALID_CNUM(cnum) && Connections[cnum].ipc) #define FNUM_OK(fnum,c) (OPEN_FNUM(fnum) && (c)==Files[fnum].cnum) #define CHECK_FNUM(fnum,c) if (!FNUM_OK(fnum,c)) \ return(ERROR(ERRDOS,ERRbadfid)) #define CHECK_READ(fnum) if (!Files[fnum].can_read) \ return(ERROR(ERRDOS,ERRbadaccess)) #define CHECK_WRITE(fnum) if (!Files[fnum].can_write) \ return(ERROR(ERRDOS,ERRbadaccess)) #define CHECK_ERROR(fnum) if (HAS_CACHED_ERROR(fnum)) \ return(CACHED_ERROR(fnum)) /* translates a connection number into a service number */ #define SNUM(cnum) (Connections[cnum].service) /* access various service details */ #define SERVICE(snum) (lp_servicename(snum)) #define PRINTCAP (lp_printcapname()) #define PRINTCOMMAND(snum) (lp_printcommand(snum)) #define PRINTERNAME(snum) (lp_printername(snum)) #define CAN_WRITE(cnum) (OPEN_CNUM(cnum) && !Connections[cnum].read_only) #define VALID_SNUM(snum) (lp_snum_ok(snum)) #define GUEST_OK(snum) (VALID_SNUM(snum) && lp_guest_ok(snum)) #define GUEST_ONLY(snum) (VALID_SNUM(snum) && lp_guest_only(snum)) #define CAN_SETDIR(snum) (!lp_no_set_dir(snum)) #define CAN_PRINT(cnum) (OPEN_CNUM(cnum) && lp_print_ok(SNUM(cnum))) #define POSTSCRIPT(cnum) (OPEN_CNUM(cnum) && lp_postscript(SNUM(cnum))) #define MAP_HIDDEN(cnum) (OPEN_CNUM(cnum) && lp_map_hidden(SNUM(cnum))) #define MAP_SYSTEM(cnum) (OPEN_CNUM(cnum) && lp_map_system(SNUM(cnum))) #define MAP_ARCHIVE(cnum) (OPEN_CNUM(cnum) && lp_map_archive(SNUM(cnum))) #define CREATE_MODE(cnum) (lp_create_mode(SNUM(cnum)) | 0700) #ifdef SMB_PASSWD #define SMBENCRYPT() (lp_encrypted_passwords()) #else #define SMBENCRYPT() (False) #endif /* the basic packet size, assuming no words or bytes */ #define smb_size 39 /* offsets into message for common items */ #define smb_com 8 #define smb_rcls 9 #define smb_reh 10 #define smb_err 11 #define smb_flg 13 #define smb_flg2 14 #define smb_reb 13 #define smb_tid 28 #define smb_pid 30 #define smb_uid 32 #define smb_mid 34 #define smb_wct 36 #define smb_vwv 37 #define smb_vwv0 37 #define smb_vwv1 39 #define smb_vwv2 41 #define smb_vwv3 43 #define smb_vwv4 45 #define smb_vwv5 47 #define smb_vwv6 49 #define smb_vwv7 51 #define smb_vwv8 53 #define smb_vwv9 55 #define smb_vwv10 57 #define smb_vwv11 59 #define smb_vwv12 61 #define smb_vwv13 63 #define smb_vwv14 65 #define smb_vwv15 67 #define smb_vwv16 69 #define smb_vwv17 71 /* the complete */ #define SMBmkdir 0x00 /* create directory */ #define SMBrmdir 0x01 /* delete directory */ #define SMBopen 0x02 /* open file */ #define SMBcreate 0x03 /* create file */ #define SMBclose 0x04 /* close file */ #define SMBflush 0x05 /* flush file */ #define SMBunlink 0x06 /* delete file */ #define SMBmv 0x07 /* rename file */ #define SMBgetatr 0x08 /* get file attributes */ #define SMBsetatr 0x09 /* set file attributes */ #define SMBread 0x0A /* read from file */ #define SMBwrite 0x0B /* write to file */ #define SMBlock 0x0C /* lock byte range */ #define SMBunlock 0x0D /* unlock byte range */ #define SMBctemp 0x0E /* create temporary file */ #define SMBmknew 0x0F /* make new file */ #define SMBchkpth 0x10 /* check directory path */ #define SMBexit 0x11 /* process exit */ #define SMBlseek 0x12 /* seek */ #define SMBtcon 0x70 /* tree connect */ #define SMBtconX 0x75 /* tree connect and X*/ #define SMBtdis 0x71 /* tree disconnect */ #define SMBnegprot 0x72 /* negotiate protocol */ #define SMBdskattr 0x80 /* get disk attributes */ #define SMBsearch 0x81 /* search directory */ #define SMBsplopen 0xC0 /* open print spool file */ #define SMBsplwr 0xC1 /* write to print spool file */ #define SMBsplclose 0xC2 /* close print spool file */ #define SMBsplretq 0xC3 /* return print queue */ #define SMBsends 0xD0 /* send single block message */ #define SMBsendb 0xD1 /* send broadcast message */ #define SMBfwdname 0xD2 /* forward user name */ #define SMBcancelf 0xD3 /* cancel forward */ #define SMBgetmac 0xD4 /* get machine name */ #define SMBsendstrt 0xD5 /* send start of multi-block message */ #define SMBsendend 0xD6 /* send end of multi-block message */ #define SMBsendtxt 0xD7 /* send text of multi-block message */ /* Core+ protocol */ #define SMBlockread 0x13 /* Lock a range and read */ #define SMBwriteunlock 0x14 /* Unlock a range then write */ #define SMBreadbraw 0x1a /* read a block of data with no smb header */ #define SMBwritebraw 0x1d /* write a block of data with no smb header */ #define SMBwritec 0x20 /* secondary write request */ #define SMBwriteclose 0x2c /* write a file then close it */ /* dos extended protocol */ #define SMBreadBraw 0x1A /* read block raw */ #define SMBreadBmpx 0x1B /* read block multiplexed */ #define SMBreadBs 0x1C /* read block (secondary response) */ #define SMBwriteBraw 0x1D /* write block raw */ #define SMBwriteBmpx 0x1E /* write block multiplexed */ #define SMBwriteBs 0x1F /* write block (secondary request) */ #define SMBwriteC 0x20 /* write complete response */ #define SMBsetattrE 0x22 /* set file attributes expanded */ #define SMBgetattrE 0x23 /* get file attributes expanded */ #define SMBlockingX 0x24 /* lock/unlock byte ranges and X */ #define SMBtrans 0x25 /* transaction - name, bytes in/out */ #define SMBtranss 0x26 /* transaction (secondary request/response) */ #define SMBioctl 0x27 /* IOCTL */ #define SMBioctls 0x28 /* IOCTL (secondary request/response) */ #define SMBcopy 0x29 /* copy */ #define SMBmove 0x2A /* move */ #define SMBecho 0x2B /* echo */ #define SMBopenX 0x2D /* open and X */ #define SMBreadX 0x2E /* read and X */ #define SMBwriteX 0x2F /* write and X */ #define SMBsesssetupX 0x73 /* Session Set Up & X (including User Logon) */ #define SMBffirst 0x82 /* find first */ #define SMBfunique 0x83 /* find unique */ #define SMBfclose 0x84 /* find close */ #define SMBinvalid 0xFE /* invalid command */ /* Extended 2.0 protocol */ #define SMBtrans2 0x32 /* TRANS2 protocol set */ #define SMBtranss2 0x33 /* TRANS2 protocol set, secondary command */ #define SMBfindclose 0x34 /* Terminate a TRANSACT2_FINDFIRST */ #define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */ #define SMBulogoffX 0x74 /* user logoff */ /* these are the TRANS2 sub commands */ #define TRANSACT2_OPEN 0 #define TRANSACT2_FINDFIRST 1 #define TRANSACT2_FINDNEXT 2 #define TRANSACT2_QFSINFO 3 #define TRANSACT2_SETFSINFO 4 #define TRANSACT2_QPATHINFO 5 #define TRANSACT2_SETPATHINFO 6 #define TRANSACT2_QFILEINFO 7 #define TRANSACT2_SETFILEINFO 8 #define TRANSACT2_FSCTL 9 #define TRANSACT2_IOCTL 10 #define TRANSACT2_FINDNOTIFYFIRST 11 #define TRANSACT2_FINDNOTIFYNEXT 12 #define TRANSACT2_MKDIR 13 /* these are the trans2 sub fields for primary requests */ #define smb_tpscnt smb_vwv0 #define smb_tdscnt smb_vwv1 #define smb_mprcnt smb_vwv2 #define smb_mdrcnt smb_vwv3 #define smb_msrcnt smb_vwv4 #define smb_flags smb_vwv5 #define smb_timeout smb_vwv6 #define smb_pscnt smb_vwv9 #define smb_psoff smb_vwv10 #define smb_dscnt smb_vwv11 #define smb_dsoff smb_vwv12 #define smb_suwcnt smb_vwv13 #define smb_setup smb_vwv14 #define smb_setup0 smb_setup #define smb_setup1 (smb_setup+2) #define smb_setup2 (smb_setup+4) /* these are for the secondary requests */ #define smb_spscnt smb_vwv2 #define smb_spsoff smb_vwv3 #define smb_spsdisp smb_vwv4 #define smb_sdscnt smb_vwv5 #define smb_sdsoff smb_vwv6 #define smb_sdsdisp smb_vwv7 #define smb_sfid smb_vwv8 /* and these for responses */ #define smb_tprcnt smb_vwv0 #define smb_tdrcnt smb_vwv1 #define smb_prcnt smb_vwv3 #define smb_proff smb_vwv4 #define smb_prdisp smb_vwv5 #define smb_drcnt smb_vwv6 #define smb_droff smb_vwv7 #define smb_drdisp smb_vwv8 /* where to find the base of the SMB packet proper */ #define smb_base(buf) (((char *)(buf))+4) #define SUCCESS 0 /* The request was successful. */ #define ERRDOS 0x01 /* Error is from the core DOS operating system set. */ #define ERRSRV 0x02 /* Error is generated by the server network file manager.*/ #define ERRHRD 0x03 /* Error is an hardware error. */ #define ERRCMD 0xFF /* Command was not in the "SMB" format. */ /* structure used to hold the incoming hosts info */ struct from_host { char *name; /* host name */ char *addr; /* host address */ struct sockaddr_in *sin; /* their side of the link */ }; /* and a few prototypes */ BOOL user_ok(char *user,int snum); int sys_rename(char *from, char *to); int sys_select(fd_set *fds,struct timeval *tval); int sys_unlink(char *fname); int sys_open(char *fname,int flags,int mode); DIR *sys_opendir(char *dname); int sys_stat(char *fname,struct stat *sbuf); int sys_lstat(char *fname,struct stat *sbuf); int sys_mkdir(char *dname,int mode); int sys_rmdir(char *dname); int sys_chdir(char *dname); int sys_utime(char *fname,struct utimbuf *times); int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize); void lpq_reset(int); void status_printjob(int cnum,int snum,int jobid,int status); void DirCacheAdd(char *path,char *name,char *dname,int snum); char *DirCacheCheck(char *path,char *name,int snum); void DirCacheFlush(int snum); int interpret_character_set(char *str, int def); char *dos2unix_format(char *, BOOL); char *unix2dos_format(char *, BOOL); BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type); void BlockSignals(BOOL block); void msleep(int t); int file_lock(char *name,int timeout); void file_unlock(int fd); int find_service(char *service); int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew); int smb_offset(char *p,char *buf); void sync_file(int fnum); void PutUniCode(char *dst,char *src); void map_username(char *user); void close_low_fds(void); void clean_share_files(void); int write_socket(int fd,char *buf,int len); char *readdirname(void *p); int dos_chmod(int cnum,char *fname,int mode); int smb_numwords(char *buf); int get_share_mode(int cnum,struct stat *sbuf,int *pid); void del_share_mode(int fnum); BOOL set_share_mode(int fnum,int mode); int DSTDiff(time_t t); void TimeInit(void); void put_long_date(char *p,time_t t); time_t interpret_long_date(char *p); void dptr_idlecnum(int cnum); void dptr_closecnum(int cnum); void init_dptrs(void); void fault_setup(); void set_socket_options(int fd, char *options); void putip(void *dest,void *src); void standard_sub_basic(char *s); void *OpenDir(char *name); void CloseDir(void *p); char *ReadDirName(void *p); BOOL SeekDir(void *p,int pos); int TellDir(void *p); int write_data(int fd,char *buffer,int N); BOOL server_cryptkey(char *buf); BOOL server_validate(char *buf); BOOL become_service(int cnum,BOOL do_chdir); BOOL snum_used(int snum); BOOL reload_services(BOOL test); void reopen_logs(void); int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align); int str_checksum(char *s); time_t file_modtime(char *fname); BOOL do_match(char *str, char *regexp, int case_sig); BOOL is_a_socket(int fd); void _smb_setlen(char *buf,int len); void valid_initialise(void); BOOL is_8_3(char *fname); BOOL is_mangled(char *s); void standard_sub(int cnum,char *s); void del_printqueue(int cnum,int snum,int jobid); BOOL strisnormal(char *s); BOOL check_mangled_stack(char *s); int sys_chown(char *fname,int uid,int gid); int sys_chroot(char *dname); BOOL next_token(char **ptr,char *buff,char *sep); void invalidate_uid(int uid); char *fgets_slash(char *s,int maxlen,FILE *f); int read_udp_socket(int fd,char *buf,int len); void exit_server(char *reason); BOOL process_exists(int pid); BOOL chgpasswd(char *name,char *oldpass,char *newpass); void array_promote(char *array,int elsize,int element); void string_replace(char *s,char oldc,char newc); BOOL user_in_list(char *user,char *list); BOOL string_sub(char *s,char *pattern,char *insert); char *StrnCpy(char *dest,const char *src,int n); char *validated_username(int vuid); BOOL set_user_password(char *user,char *oldpass,char *newpass); int smb_buf_ofs(char *buf); char *skip_string(char *buf,int n); BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset); int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact); BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode); int seek_file(int fnum,int pos); BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode); int get_printqueue(int snum,int cnum,print_queue_struct **queue,print_status_struct *status); void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev); int setup_groups(char *user,int uid, int gid, int *p_ngroups, int **p_igroups, gid_t **p_groups); int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid); char *dptr_path(int key); char *dptr_wcard(int key); BOOL dptr_set_wcard(int key, char *wcard); BOOL dptr_set_attr(int key, uint16 attr); uint16 dptr_attr(int key); void dptr_close(int key); void dptr_closepath(char *path,int pid); int dptr_create(int cnum,char *path, BOOL expect_close,int pid); BOOL dptr_fill(char *buf,unsigned int key); BOOL dptr_zero(char *buf); void *dptr_fetch(char *buf,int *num); void *dptr_fetch_lanman2(char *params,int dptr_num); BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend); void open_file(int fnum,int cnum,char *fname,int flags,int mode); void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,int mode,int *Access,int *action); void close_file(int fnum); int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize); int reply_trans(char *inbuf,char *outbuf); char *ufc_crypt(char *key,char *salt); BOOL authorise_login(int snum,char *user,char *password, int pwlen, BOOL *guest,BOOL *force,int vuid); void add_session_user(char *user); int valid_uid(int uid); user_struct *get_valid_user_struct(int uid); BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL nt_password); void register_uid(int uid,int gid,char *name,BOOL guest); BOOL fromhost(int sock,struct from_host *f); BOOL strhasupper(char *s); BOOL strhaslower(char *s); int disk_free(char *path,int *bsize,int *dfree,int *dsize); char *uidtoname(int uid); char *gidtoname(int gid); int get_share_mode_byname(int cnum,char *fname,int *pid); int get_share_mode_by_fnum(int cnum,int fnum,int *pid); BOOL check_file_sharing(int cnum,char *fname); char *StrCpy(char *dest,char *src); int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line); time_t make_unix_date2(void *date_ptr); int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line); mode_t unix_mode(int cnum,int dosmode); BOOL check_name(char *name,int cnum); int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line); int find_free_file(void ); BOOL unix_convert(char *name,int cnum); void unix_convert_lanman2(char *s,char *home,BOOL case_is_sig); void print_file(int fnum); int read_smb_length(int fd,char *inbuf,int timeout); int read_predict(int fd,int offset,char *buf,char **ptr,int num); void invalidate_read_prediction(int fd); void do_read_prediction(); BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear); BOOL yield_connection(int cnum,char *name,int max_connections); int count_chars(char *s,char c); int smbrun(char *,char *); BOOL name_map_mangle(char *OutName,BOOL need83,int snum); struct hostent *Get_Hostbyname(char *name); struct passwd *Get_Pwnam(char *user,BOOL allow_change); void Abort(void); void *Realloc(void *p,int size); void smb_setlen(char *buf,int len); int set_message(char *buf,int num_words,int num_bytes,BOOL zero); BOOL check_access(int snum); BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups); BOOL string_set(char **dest,char *src); BOOL string_init(char **dest,char *src); void string_free(char **s); char *attrib_string(int mode); void unix_format(char *fname); BOOL directory_exist(char *dname,struct stat *st); time_t make_unix_date3(void *date_ptr); void put_dos_date3(char *buf,int offset,time_t unixdate); void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date); BOOL in_list(char *s,char *list,BOOL case_sensitive); void strupper(char *s); BOOL file_exist(char *fname,struct stat *sbuf); int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt, long time_out, BOOL exact); void close_sockets(void ); BOOL send_smb(int fd,char *buffer); BOOL send_keepalive(int client); int read_data(int fd,char *buffer,int N); int smb_len(char *buf); BOOL receive_smb(int fd,char *buffer,int timeout); void show_msg(char *buf); BOOL big_endian(void ); BOOL become_user(int cnum, int uid); BOOL unbecome_user(void); void become_daemon(void); BOOL reduce_name(char *s,char *dir,BOOL widelinks); void strlower(char *s); void strnorm(char *s); char *smb_buf(char *buf); char *smb_trans2_param(char *buf); char *smb_trans2_data(char *buf); BOOL strequal(char *,char *); BOOL strnequal(char *,char *,int n); BOOL strcsequal(char *,char *); BOOL mask_match( char *str, char *regexp, int case_sig, BOOL trans2); int dos_mode(int ,char *,struct stat *); char *timestring(); BOOL ip_equal(struct in_addr ip1,struct in_addr ip2); BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type); char *get_home_dir(char *); int set_filelen(int fd, long len); void put_dos_date(char *buf,int offset,time_t unixdate); void put_dos_date2(char *buf,int offset,time_t unixdate); int lp_keepalive(void); int name_len(char *s); void dos_clean_name(char *s); void unix_clean_name(char *s); time_t make_unix_date(void *date_ptr); BOOL lanman2_match( char *str, char *regexp, int case_sig, BOOL autoext); BOOL trim_string(char *s,char *front,char *back); int byte_checksum(char *buf,int len); BOOL yesno(char *p); uint32 file_size(char *file_name); void dos_format(char *fname); char *GetWd(char *s); int name_mangle(char *in,char *out,char name_type); int name_len(char *s); void create_mangled_stack(int size); int name_extract(char *buf,int ofs,char *name); void get_broadcast(struct in_addr *if_ipaddr, struct in_addr *if_bcast, struct in_addr *if_nmask); BOOL allow_access(char *deny_list,char *allow_list,struct from_host *client); #ifdef __STDC__ int Debug1(char *, ...); #else int Debug1(); #endif BOOL check_hosts_equiv(char *user); int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize); void close_cnum(int cnum,int uid); char *smb_errstr(char *inbuf); void GetTimeOfDay(struct timeval *tval); struct tm *LocalTime(time_t *t,int); int TimeDiff(time_t t); BOOL set_filetime(char *fname,time_t mtime); char *dirname_dos(char *path,char *buf); BOOL get_myname(char *myname,struct in_addr *ip); void expand_mask(char *Mask, BOOL); BOOL sane_unix_date(time_t unixdate); time_t start_of_month(void); char *smb_fn_name(int cnum); void get_machine_info(void); int open_socket_in(int type, int port, int dlevel); int open_socket_out(int type,struct in_addr *addr, int port ); struct in_addr *interpret_addr2(char *str); BOOL zero_ip(struct in_addr ip); int read_max_udp(int fd,char *buffer,int bufsize,int maxtime); int interpret_protocol(char *str,int def); int interpret_security(char *str,int def); int ChDir(char *path); int smb_buflen(char *buf); unsigned long interpret_addr(char *str); void mangle_name_83(char *s); BOOL lp_casesignames(void); void setup_logging(char *pname,BOOL interactive); #ifdef DFS_AUTH void dfs_unlogin(void); extern int dcelogin_atmost_once; #endif #if AJT void ajt_panic(void); #endif #ifdef NOSTRDUP char *strdup(char *s); #endif #ifdef REPLACE_STRLEN int Strlen(char *); #endif #ifdef REPLACE_STRSTR char *Strstr(char *s, char *p); #endif #ifndef MIN #define MIN(a,b) ((a)<(b)?(a):(b)) #endif #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif #ifndef ABS #define ABS(a) ((a)>0?(a):(-(a))) #endif #ifndef SIGNAL_CAST #define SIGNAL_CAST #endif #ifndef SELECT_CAST #define SELECT_CAST #endif /* Some POSIX definitions for those without */ #ifndef S_IFDIR #define S_IFDIR 0x4000 #endif #ifndef S_ISDIR #define S_ISDIR(mode) ((mode & 0xF000) == S_IFDIR) #endif #ifndef S_IRWXU #define S_IRWXU 00700 /* read, write, execute: owner */ #endif #ifndef S_IRUSR #define S_IRUSR 00400 /* read permission: owner */ #endif #ifndef S_IWUSR #define S_IWUSR 00200 /* write permission: owner */ #endif #ifndef S_IXUSR #define S_IXUSR 00100 /* execute permission: owner */ #endif #ifndef S_IRWXG #define S_IRWXG 00070 /* read, write, execute: group */ #endif #ifndef S_IRGRP #define S_IRGRP 00040 /* read permission: group */ #endif #ifndef S_IWGRP #define S_IWGRP 00020 /* write permission: group */ #endif #ifndef S_IXGRP #define S_IXGRP 00010 /* execute permission: group */ #endif #ifndef S_IRWXO #define S_IRWXO 00007 /* read, write, execute: other */ #endif #ifndef S_IROTH #define S_IROTH 00004 /* read permission: other */ #endif #ifndef S_IWOTH #define S_IWOTH 00002 /* write permission: other */ #endif #ifndef S_IXOTH #define S_IXOTH 00001 /* execute permission: other */ #endif /* these are used in NetServerEnum to choose what to receive */ #define SV_TYPE_WORKSTATION 0x00000001 #define SV_TYPE_SERVER 0x00000002 #define SV_TYPE_SQLSERVER 0x00000004 #define SV_TYPE_DOMAIN_CTRL 0x00000008 #define SV_TYPE_DOMAIN_BAKCTRL 0x00000010 #define SV_TYPE_TIME_SOURCE 0x00000020 #define SV_TYPE_AFP 0x00000040 #define SV_TYPE_NOVELL 0x00000080 #define SV_TYPE_DOMAIN_MEMBER 0x00000100 #define SV_TYPE_PRINTQ_SERVER 0x00000200 #define SV_TYPE_DIALIN_SERVER 0x00000400 #define SV_TYPE_SERVER_UNIX 0x00000800 #define SV_TYPE_NT 0x00001000 #define SV_TYPE_WFW 0x00002000 #define SV_TYPE_SERVER_MFPN 0x00004000 #define SV_TYPE_SERVER_NT 0x00008000 #define SV_TYPE_POTENTIAL_BROWSER 0x00010000 #define SV_TYPE_BACKUP_BROWSER 0x00020000 #define SV_TYPE_MASTER_BROWSER 0x00040000 #define SV_TYPE_DOMAIN_MASTER 0x00080000 #define SV_TYPE_SERVER_OSF 0x00100000 #define SV_TYPE_SERVER_VMS 0x00200000 #define SV_TYPE_ALTERNATE_XPORT 0x20000000 #define SV_TYPE_LOCAL_LIST_ONLY 0x40000000 #define SV_TYPE_DOMAIN_ENUM 0x80000000 #define SV_TYPE_ALL 0xFFFFFFFF /* protocol types. It assumes that higher protocols include lower protocols as subsets */ enum protocol_types {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANMAN1,PROTOCOL_LANMAN2,PROTOCOL_NT1}; /* security levels */ enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER}; /* printing types */ enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX,PRINT_QNX}; /* case handling */ enum case_handling {CASE_LOWER,CASE_UPPER}; /* Macros to get at offsets within smb_lkrng and smb_unlkrng structures. We cannot define these as actual structures due to possible differences in structure packing on different machines/compilers. */ #define SMB_LPID_OFFSET(indx) (10 * (indx)) #define SMB_LKOFF_OFFSET(indx) ( 2 + (10 * (indx))) #define SMB_LKLEN_OFFSET(indx) ( 6 + (10 * (indx))) /* Macro to cache an error in a write_bmpx_struct */ #define CACHE_ERROR(w,c,e) ((w)->wr_errclass = (c), (w)->wr_error = (e), \ w->wr_discard = True, -1) /* Macro to test if an error has been cached for this fnum */ #define HAS_CACHED_ERROR(fnum) (Files[(fnum)].open && \ Files[(fnum)].wbmpx_ptr && \ Files[(fnum)].wbmpx_ptr->wr_discard) /* Macro to turn the cached error into an error packet */ #define CACHED_ERROR(fnum) cached_error_packet(inbuf,outbuf,fnum,__LINE__) /* these are the datagram types */ #define DGRAM_DIRECT_UNIQUE 0x10 #define ERROR(class,x) error_packet(inbuf,outbuf,class,x,__LINE__) /* this is how errors are generated */ #define UNIXERROR(defclass,deferror) unix_error_packet(inbuf,outbuf,defclass,deferror,__LINE__) #define ROUNDUP(x,g) (((x)+((g)-1))&~((g)-1)) #endif /* _SMB_H */ nat-1.0.orig/passlist.txt0100600000175000017500000000017706301746754016546 0ustar jfernandezjfernandezADMINISTRATOR GUEST ROOT ADMIN PASSWORD TEMP SHARE WRITE FULL BOTH READ FILES DEMO TEST ACCESS USER BACKUP SYSTEM SERVER LOCAL nat-1.0.orig/parse_ip.h0100600000175000017500000000026306301746754016112 0ustar jfernandezjfernandez#include /* * Used for storing the list of IP addresses returned and used by * the parse_ip function. */ struct ipstr { char *name; struct ipstr *next; }; nat-1.0.orig/parse_ip.c0100600000175000017500000001213406301746754016105 0ustar jfernandezjfernandez#include #include #include #include #include #include #include #include #include "parse_ip.h" struct ipstr *parse_ip(char *); void add_parse_ip(struct ipstr **, char *); char *ip_ntoa(u_long in); /* * Parse list of IP address or hostnames to scan (comma deliminated) * * Sanity checking is done on every case and should not return any invalid * addresses. * * Valid data is: * * hostname anklebiter.secnet.com * ipaddress 127.0.0.1 * ipaddress-ipaddress 127.0.0.1-127.0.0.20 * ipaddress-digit 127.0.0.1-20 * digit 10 (expands to 127.0.0.10); * digit-digit 1-10 (expands to 127.0.0.1-127.0.0.10) * * For digit expansion, a CLASS C address must be present first somewhere, * for expansion to work. * * A valid line would be: * * anklebiter, 127.0.0.1-3,11, 14-16, 17,127.0.0.20-127.0.0.21 * * This would return * anklebiters IP, 127.0.0.1, 127.0.0.2, 127.0.0.3, 127.0.0.11, 127.0.0.14, * 127.0.0.15, 127.0.0.16, 127.0.0.17, 127.0.0.20, 127.0.0.21 * * Oliver */ struct ipstr *parse_ip(input) char *input; { char *one = NULL, *dup = NULL; /* a single specified address or range */ char *r1 = NULL, *r2 = NULL; /* for a range */ u_long ip1 = 0, ip2 = 0; u_char start = 0, stop = 0; struct hostent *hp = NULL; int count = 0; struct ipstr *ip = NULL; char tmpip[20]; dup = strdup(input); one = strtok(dup, ","); while (one) { while(isspace(*one) && *one) one++; /* * If first char is not a digit, assume this is a hostname */ if (*one && !isdigit(*one)) { hp = NULL; hp = gethostbyname(one); if (hp) { memcpy((char *)&ip1, hp->h_addr, sizeof(ip1)); sprintf(tmpip, "%s", ip_ntoa(ip1)); add_parse_ip(&ip, tmpip); count++; } else { /* * Invalid data, can't resolve hostname, what is this? */ natprintf("[*]--- Unknown host: %s\n", one); } one = strtok(NULL, ","); continue; } /* * If '-' is in the string, assume it's a range */ if (*one && strstr(one, "-")) { r1 = one; for (r2 = one; *r2 && *r2 != '-'; r2++); *r2 = '\0'; r2++; /* * A range specified as x.x.x.x-x.x.x.x */ if (r2 && *r2 && r1 && *r1 && strlen(r1) > 6) { ip1 = inet_addr(r1); ip2 = inet_addr(r2); if (ip1 != -1 && ip2 != -1) { start = (u_char)(ip1 >> 24); stop = (u_char)(ip2 >> 24); if (start <= stop && ip1 != -1 && ip2 != -1) { while (start <= stop && start > 0) { sprintf(tmpip, "%d.%d.%d.%d", (u_char)(ip1), (u_char)(ip1 >> 8), (u_char)(ip1 >> 16), start); add_parse_ip(&ip, tmpip); count++; start++; } } } } else { /* * A range specified as x-x (class C is prepended) * Make sure ip1 contains the beginning of a sensible class C */ if ((u_char)(ip1) != 0 && r2 && *r2 && r1 && *r1) { start = atoi(r1); stop = atoi(r2); if (start < stop) { while(start <= stop && start > 0) { sprintf(tmpip, "%d.%d.%d.%d", (u_char)(ip1), (u_char)(ip1 >> 8), (u_char)(ip1 >> 16), start); add_parse_ip(&ip, tmpip); count++; start++; } } } } one = strtok(NULL, ","); continue; } /* * If we're here, it's a lonely IP address, check to see if it's valid */ if (*one && (ip2 = inet_addr(one)) != -1 && strlen(one) > 6) { ip1 = ip2; sprintf(tmpip, "%s", ip_ntoa(ip1)); add_parse_ip(&ip, tmpip); count++; } else { if (!strstr(one, ".")) { sprintf(tmpip, "%d.%d.%d.%d", (u_char)(ip1), (u_char)(ip1 >> 8), (u_char)(ip1 >> 16), atoi(one)); add_parse_ip(&ip, tmpip); count++; } } one = strtok(NULL, ","); } return(ip); } /* * Adds the specified IP to an array of IP address strings */ void add_parse_ip(ip, new) struct ipstr **ip; char *new; { struct ipstr *newitem, *tmp; newitem = (struct ipstr *)malloc(sizeof(struct ipstr)); newitem->name = strdup(new); newitem->next = NULL; if (!*ip) { *ip = newitem; } else { for (tmp = *ip; tmp->next; tmp = tmp->next); tmp->next = newitem; } return; } char *ip_ntoa(in) u_long in; { static char b[18]; register char *p; p = (char *)∈ #define UC(b) (((int)b)&0xff) (void)sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); return (b); } nat-1.0.orig/nmb.c0100600000175000017500000007645706301746754015101 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. NBT netbios library routines Copyright (C) Andrew Tridgell 1994-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" #include "nameserv.h" #include "vulns.h" extern int DEBUGLEVEL; #ifdef SCANNER extern int cur_vuln; extern int fill_vuln(); static fstring tbuf; #endif /* SCANNER */ int Debug1(char *, ...); int Debug1(); int num_good_sends=0; int num_good_receives=0; static uint16 name_trn_id = 0; BOOL CanRecurse = True; extern pstring scope; /******************************************************************* handle "compressed" name pointers ******************************************************************/ static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length, BOOL *got_pointer,int *ret) { int loop_count=0; while ((ubuf[*offset] & 0xC0) == 0xC0) { if (!*got_pointer) (*ret) += 2; (*got_pointer)=True; (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1]; if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) { return(False); } } return(True); } /******************************************************************* parse a nmb name from "compressed" format to something readable return the space taken by the name, or 0 if the name is invalid ******************************************************************/ static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name) { int m,n=0; unsigned char *ubuf = (unsigned char *)inbuf; int ret = 0; BOOL got_pointer=False; if (length - offset < 2) return(0); /* handle initial name pointers */ if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0); m = ubuf[offset]; if (!m) return(0); if ((m & 0xC0) || offset+m+2 > length) return(0); bzero((char *)name,sizeof(*name)); /* the "compressed" part */ if (!got_pointer) ret += m + 2; offset++; while (m) { unsigned char c1,c2; c1 = ubuf[offset++]-'A'; c2 = ubuf[offset++]-'A'; if ((c1 & 0xF0) || (c2 & 0xF0)) return(0); name->name[n++] = (c1<<4) | c2; m -= 2; } name->name[n] = 0; if (n==16) { /* parse out the name type, its always in the 16th byte of the name */ name->name_type = name->name[15]; /* remove trailing spaces */ name->name[15] = 0; n = 14; while (n && name->name[n]==' ') name->name[n--] = 0; } /* now the domain parts (if any) */ n = 0; while ((m=ubuf[offset])) { /* we can have pointers within the domain part as well */ if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0); if (!got_pointer) ret += m+1; if (n) name->scope[n++] = '.'; if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0); offset++; while (m--) name->scope[n++] = (char)ubuf[offset++]; } name->scope[n++] = 0; return(ret); } /******************************************************************* put a compressed nmb name into a buffer. return the length of the compressed name compressed names are really weird. The "compression" doubles the size. The idea is that it also means that compressed names conform to the doman name system. See RFC1002. ******************************************************************/ static int put_nmb_name(char *buf,int offset,struct nmb_name *name) { int ret,m; fstring buf1; char *p; if (name->name[0] == '*') { /* special case for wildcard name */ bzero(buf1,20); buf1[0] = '*'; } else { sprintf(buf1,"%-15.15s%c",name->name,name->name_type); } buf[offset] = 0x20; ret = 34; for (m=0;m<16;m++) { buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF); buf[offset+2+2*m] = 'A' + (buf1[m]&0xF); } offset += 33; buf[offset] = 0; if (name->scope[0]) { /* XXXX this scope handling needs testing */ ret += strlen(name->scope) + 1; strcpy(&buf[offset+1],name->scope); p = &buf[offset+1]; while ((p = strchr(p,'.'))) { buf[offset] = PTR_DIFF(p,&buf[offset]); offset += buf[offset]; p = &buf[offset+1]; } buf[offset] = strlen(&buf[offset+1]); } return(ret); } /******************************************************************* useful for debugging messages ******************************************************************/ char *namestr(struct nmb_name *n) { static int i=0; static fstring ret[4]; char *p = ret[i]; if (!n->scope[0]) sprintf(p,"%s(%x)",n->name,n->name_type); else sprintf(p,"%s(%x).%s",n->name,n->name_type,n->scope); i = (i+1)%4; return(p); } /******************************************************************* allocate are parse some resource records ******************************************************************/ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length, struct res_rec **recs, int count) { int i; *recs = (struct res_rec *)malloc(sizeof(**recs)*count); if (!*recs) return(False); bzero(*recs,sizeof(**recs)*count); for (i=0;i length) { free(*recs); return(False); } (*recs)[i].rr_type = RSVAL(inbuf,(*offset)); (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2); (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4); (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8); (*offset) += 10; if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) || (*offset)+(*recs)[i].rdlength > length) { free(*recs); return(False); } memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength); (*offset) += (*recs)[i].rdlength; } return(True); } /******************************************************************* put a resource record into a packet ******************************************************************/ static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count) { int ret=0; int i; for (i=0;iheader.msg_type = CVAL(inbuf,0); flags = CVAL(inbuf,1); dgram->header.flags.node_type = (enum node_type)((flags>>2)&3); if (flags & 1) dgram->header.flags.more = True; if (flags & 2) dgram->header.flags.first = True; dgram->header.dgm_id = RSVAL(inbuf,2); putip((char *)&dgram->header.source_ip,inbuf+4); dgram->header.source_port = RSVAL(inbuf,8); dgram->header.dgm_length = RSVAL(inbuf,10); dgram->header.packet_offset = RSVAL(inbuf,12); offset = 14; if (dgram->header.msg_type == 0x10 || dgram->header.msg_type == 0x11 || dgram->header.msg_type == 0x12) { offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name); offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name); } if (offset >= length || (length-offset > sizeof(dgram->data))) return(False); dgram->datasize = length-offset; memcpy(dgram->data,inbuf+offset,dgram->datasize); return(True); } /******************************************************************* parse a nmb packet. Return False if the packet can't be parsed or is invalid for some reason, True otherwise ******************************************************************/ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb) { int nm_flags,offset; bzero((char *)nmb,sizeof(*nmb)); if (length < 12) return(False); /* parse the header */ nmb->header.name_trn_id = RSVAL(inbuf,0); nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF; nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False; nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4); nmb->header.nm_flags.bcast = (nm_flags&1)?True:False; nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False; nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False; nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False; nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False; nmb->header.rcode = CVAL(inbuf,3) & 0xF; nmb->header.qdcount = RSVAL(inbuf,4); nmb->header.ancount = RSVAL(inbuf,6); nmb->header.nscount = RSVAL(inbuf,8); nmb->header.arcount = RSVAL(inbuf,10); if (nmb->header.qdcount) { offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name); if (!offset) return(False); if (length - (12+offset) < 4) return(False); nmb->question.question_type = RSVAL(inbuf,12+offset); nmb->question.question_class = RSVAL(inbuf,12+offset+2); offset += 12+4; } else { offset = 12; } /* and any resource records */ if (nmb->header.ancount && !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers, nmb->header.ancount)) return(False); if (nmb->header.nscount && !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs, nmb->header.nscount)) return(False); if (nmb->header.arcount && !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional, nmb->header.arcount)) return(False); return(True); } /******************************************************************* free up any resources associated with an nmb packet ******************************************************************/ void free_nmb_packet(struct nmb_packet *nmb) { if (nmb->answers) free(nmb->answers); if (nmb->nsrecs) free(nmb->nsrecs); if (nmb->additional) free(nmb->additional); } /******************************************************************* free up any resources associated with a packet ******************************************************************/ void free_packet(struct packet_struct *packet) { if (packet->packet_type == NMB_PACKET) free_nmb_packet(&packet->packet.nmb); free(packet); } /******************************************************************* read a packet from a socket and parse it, returning a packet ready to be used or put on the queue. This assumes a UDP socket ******************************************************************/ struct packet_struct *read_packet(int fd,enum packet_type packet_type) { extern struct in_addr lastip; extern int lastport; struct packet_struct *packet; char buf[MAX_DGRAM_SIZE]; int length; BOOL ok=False; length = read_udp_socket(fd,buf,sizeof(buf)); if (length < MIN_DGRAM_SIZE) return(NULL); packet = (struct packet_struct *)malloc(sizeof(*packet)); if (!packet) return(NULL); packet->next = NULL; packet->prev = NULL; packet->ip = lastip; packet->port = lastport; packet->fd = fd; packet->timestamp = time(NULL); packet->packet_type = packet_type; switch (packet_type) { case NMB_PACKET: ok = parse_nmb(buf,length,&packet->packet.nmb); break; case DGRAM_PACKET: ok = parse_dgram(buf,length,&packet->packet.dgram); break; } if (!ok) { free(packet); return(NULL); } num_good_receives++; DEBUG(4,("%s received a packet of len %d from (%s) port %d\n", timestring(),length,inet_ntoa(packet->ip),packet->port)); return(packet); } /******************************************************************* send a udp packet on a already open socket ******************************************************************/ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port) { BOOL ret; struct sockaddr_in sock_out; /* set the address and port */ bzero((char *)&sock_out,sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)&ip); sock_out.sin_port = htons( port ); sock_out.sin_family = AF_INET; DEBUG(4,("%s sending a packet of len %d to (%s) on port %d\n", timestring(),len,inet_ntoa(ip),port)); ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out, sizeof(sock_out)) >= 0); if (!ret) DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n", inet_ntoa(ip),port,strerror(errno))); if (ret) num_good_sends++; return(ret); } /******************************************************************* build a dgram packet ready for sending XXXX This currently doesn't handle packets too big for one datagram. It should split them and use the packet_offset, more and first flags to handle the fragmentation. Yuck. ******************************************************************/ static int build_dgram(char *buf,struct packet_struct *p) { struct dgram_packet *dgram = &p->packet.dgram; unsigned char *ubuf = (unsigned char *)buf; int offset=0; /* put in the header */ ubuf[0] = dgram->header.msg_type; ubuf[1] = (((int)dgram->header.flags.node_type)<<2); if (dgram->header.flags.more) ubuf[1] |= 1; if (dgram->header.flags.first) ubuf[1] |= 2; RSSVAL(ubuf,2,dgram->header.dgm_id); putip(ubuf+4,(char *)&dgram->header.source_ip); RSSVAL(ubuf,8,dgram->header.source_port); RSSVAL(ubuf,12,dgram->header.packet_offset); offset = 14; if (dgram->header.msg_type == 0x10 || dgram->header.msg_type == 0x11 || dgram->header.msg_type == 0x12) { offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name); offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name); } memcpy(ubuf+offset,dgram->data,dgram->datasize); offset += dgram->datasize; /* automatically set the dgm_length */ dgram->header.dgm_length = offset; RSSVAL(ubuf,10,dgram->header.dgm_length); return(offset); } /******************************************************************* build a nmb name ******************************************************************/ void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope) { strcpy(n->name,name); strupper(n->name); n->name_type = type; strcpy(n->scope,this_scope); } /******************************************************************* build a nmb packet ready for sending XXXX this currently relies on not being passed something that expands to a packet too big for the buffer. Eventually this should be changed to set the trunc bit so the receiver can request the rest via tcp (when that becomes supported) ******************************************************************/ static int build_nmb(char *buf,struct packet_struct *p) { struct nmb_packet *nmb = &p->packet.nmb; unsigned char *ubuf = (unsigned char *)buf; int offset=0; /* put in the header */ RSSVAL(ubuf,offset,nmb->header.name_trn_id); ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3; if (nmb->header.response) ubuf[offset+2] |= (1<<7); if (nmb->header.nm_flags.authoritative) ubuf[offset+2] |= 0x4; if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2; if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1; if (nmb->header.nm_flags.recursion_available) ubuf[offset+3] |= 0x80; if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10; ubuf[offset+3] |= (nmb->header.rcode & 0xF); RSSVAL(ubuf,offset+4,nmb->header.qdcount); RSSVAL(ubuf,offset+6,nmb->header.ancount); RSSVAL(ubuf,offset+8,nmb->header.nscount); RSSVAL(ubuf,offset+10,nmb->header.arcount); offset += 12; if (nmb->header.qdcount) { /* XXXX this doesn't handle a qdcount of > 1 */ offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name); RSSVAL(ubuf,offset,nmb->question.question_type); RSSVAL(ubuf,offset+2,nmb->question.question_class); offset += 4; } if (nmb->header.ancount) offset += put_res_rec((char *)ubuf,offset,nmb->answers, nmb->header.ancount); if (nmb->header.nscount) offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs, nmb->header.nscount); if (nmb->header.arcount) offset += put_res_rec((char *)ubuf,offset,nmb->additional, nmb->header.arcount); return(offset); } /******************************************************************* send a packet_struct ******************************************************************/ BOOL send_packet(struct packet_struct *p) { char buf[1024]; int len=0; bzero(buf,sizeof(buf)); switch (p->packet_type) { case NMB_PACKET: len = build_nmb(buf,p); break; case DGRAM_PACKET: len = build_dgram(buf,p); break; } if (!len) return(False); return(send_udp(p->fd,buf,len,p->ip,p->port)); } /**************************************************************************** receive a packet with timeout on a open UDP filedescriptor The timeout is in milliseconds ***************************************************************************/ struct packet_struct *receive_packet(int fd,enum packet_type type,int t) { fd_set fds; struct timeval timeout; FD_ZERO(&fds); FD_SET(fd,&fds); timeout.tv_sec = t/1000; timeout.tv_usec = 1000*(t%1000); sys_select(&fds,&timeout); if (FD_ISSET(fd,&fds)) return(read_packet(fd,type)); return(NULL); } /**************************************************************************** interpret a node status response ****************************************************************************/ static void interpret_node_status(char *p, char *master,char *rname) { int level = (master||rname)?4:0; int numnames = CVAL(p,0); DEBUG(level,("received %d names\n",numnames)); if (rname) *rname = 0; if (master) *master = 0; p += 1; while (numnames--) { char qname[17]; int type; fstring flags; *flags = 0; StrnCpy(qname,p,15); type = CVAL(p,15); p += 16; if (p[0] & 0x80) strcat(flags," "); if ((p[0] & 0x60) == 0) strcat(flags,"B "); if ((p[0] & 0x60) == 1) strcat(flags,"P "); if ((p[0] & 0x60) == 2) strcat(flags,"M "); if ((p[0] & 0x60) == 3) strcat(flags,"_ "); if (p[0] & 0x10) strcat(flags," "); if (p[0] & 0x08) strcat(flags," "); if (p[0] & 0x04) strcat(flags," "); if (p[0] & 0x02) strcat(flags," "); if (master && !*master && type == 0x1d) { StrnCpy(master,qname,15); trim_string(master,NULL," "); } if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) { StrnCpy(rname,qname,15); trim_string(rname,NULL," "); } DEBUG(level,("\t%s (type=0x%x)\t%s\n",qname,type,flags)); p+=2; } DEBUG(level,("num_good_sends=%d num_good_receives=%d\n", IVAL(p,20),IVAL(p,24))); } /**************************************************************************** do a netbios name status query on a host the "master" parameter is a hack used for finding workgroups. **************************************************************************/ BOOL name_status(int fd,char *name,int name_type,BOOL recurse, struct in_addr to_ip,char *master,char *rname, void (*fn)()) { BOOL found=False; int retries = 2; int retry_time = 5000; struct timeval tval; struct packet_struct p; struct packet_struct *p2; struct nmb_packet *nmb = &p.packet.nmb; bzero((char *)&p,sizeof(p)); if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100); name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; nmb->header.name_trn_id = name_trn_id; nmb->header.opcode = 0; nmb->header.response = False; nmb->header.nm_flags.bcast = False; nmb->header.nm_flags.recursion_available = CanRecurse; nmb->header.nm_flags.recursion_desired = recurse; nmb->header.nm_flags.trunc = False; nmb->header.nm_flags.authoritative = False; nmb->header.rcode = 0; nmb->header.qdcount = 1; nmb->header.ancount = 0; nmb->header.nscount = 0; nmb->header.arcount = 0; make_nmb_name(&nmb->question.question_name,name,name_type,scope); nmb->question.question_type = 0x21; nmb->question.question_class = 0x1; p.ip = to_ip; p.port = NMB_PORT; p.fd = fd; p.timestamp = time(NULL); p.packet_type = NMB_PACKET; GetTimeOfDay(&tval); if (!send_packet(&p)) return(False); retries--; while (1) { struct timeval tval2; GetTimeOfDay(&tval2); if (TvalDiff(&tval,&tval2) > retry_time) { if (!retries) break; if (!found && !send_packet(&p)) return False; GetTimeOfDay(&tval); retries--; } if ((p2=receive_packet(fd,NMB_PACKET,90))) { struct nmb_packet *nmb2 = &p2->packet.nmb; if (nmb->header.name_trn_id != nmb2->header.name_trn_id || !nmb2->header.response) { /* its not for us - maybe deal with it later */ if (fn) fn(p2); else free_packet(p2); continue; } if (nmb2->header.opcode != 0 || nmb2->header.nm_flags.bcast || nmb2->header.rcode || !nmb2->header.ancount || nmb2->answers->rr_type != 0x21) { /* XXXX what do we do with this? could be a redirect, but we'll discard it for the moment */ free_packet(p2); continue; } interpret_node_status(&nmb2->answers->rdata[0], master,rname); free_packet(p2); return(True); } } DEBUG(0,("No status response (this is not unusual)\n")); return(False); } #ifdef STEPPING /* XXX: move these out to includes.h? */ extern int fill_block(); extern char * try_names[]; extern char * try_users[]; extern char * try_pass[]; /* * interpret a node status response, stuff into appropriate blocks. */ static void H_interpret_node_status(char *p) { /* int level = (master||rname)?4:0; */ int level = 0; /* always print */ int numnames = CVAL(p,0); DEBUG(level,("received %d names\n",numnames)); p += 1; if (numnames > 0) { cur_vuln = VULID_NAMETABLES; /* name tables */ fill_vuln ("Was able to obtain name tables:", ""); } #ifdef VERBOSE if (numnames > 0) natprintf("[*]--- Remote systems name tables:\n\n"); #endif while (numnames--) { char qname[17]; int type; fstring flags; *flags = 0; StrnCpy(qname,p,15); type = CVAL(p,15); p += 16; if (p[0] & 0x80) strcat(flags," "); if ((p[0] & 0x60) == 0) strcat(flags,"B "); if ((p[0] & 0x60) == 1) strcat(flags,"P "); if ((p[0] & 0x60) == 2) strcat(flags,"M "); if ((p[0] & 0x60) == 3) strcat(flags,"_ "); if (p[0] & 0x10) strcat(flags," "); if (p[0] & 0x08) strcat(flags," "); if (p[0] & 0x04) strcat(flags," "); if (p[0] & 0x02) strcat(flags," "); #ifdef SCANNER if (type == 0x1d) strcat (flags, " "); trim_string (qname, NULL, " "); fill_block (try_names, qname); /* for starting sessions */ /* add various nametypes to appropriate other lists, too, but skip stuff like master-browsers */ if ((type != 0x1d)) { fill_block (try_users, qname); /* might be a username */ fill_block (try_pass, qname); /* might be a lamer, too */ } #endif /* SCANNER */ #ifdef VERBOSE natprintf(" %s\n", qname); #endif #ifdef SCANNER cur_vuln = VULID_NAMETABLES; /* name tables */ sprintf (tbuf, "%s (type 0x%x) %s", qname, type, flags); fill_vuln ("Name: ", tbuf); #endif /* SCANNER */ DEBUG(level,("\t%s (type=0x%x)\t%s\n",qname,type,flags)); p+=2; } DEBUG(level,("num_good_sends=%d num_good_receives=%d\n", IVAL(p,20),IVAL(p,24))); } /* * do a netbios name status query on a host, and interpret names -> try_names * block on the fly right here. */ /* shortened arglist considerably... */ BOOL H_name_status (int fd,char *name,int name_type, struct in_addr to_ip) { BOOL found=False; int retries = 2; int retry_time = 5000; struct timeval tval; struct packet_struct p; struct packet_struct *p2; struct nmb_packet *nmb = &p.packet.nmb; int recurse = 0; bzero((char *)&p,sizeof(p)); if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100); name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; nmb->header.name_trn_id = name_trn_id; nmb->header.opcode = 0; nmb->header.response = False; nmb->header.nm_flags.bcast = False; nmb->header.nm_flags.recursion_available = CanRecurse; nmb->header.nm_flags.recursion_desired = recurse; nmb->header.nm_flags.trunc = False; nmb->header.nm_flags.authoritative = False; nmb->header.rcode = 0; nmb->header.qdcount = 1; nmb->header.ancount = 0; nmb->header.nscount = 0; nmb->header.arcount = 0; make_nmb_name(&nmb->question.question_name,name,name_type,scope); nmb->question.question_type = 0x21; nmb->question.question_class = 0x1; p.ip = to_ip; p.port = NMB_PORT; p.fd = fd; p.timestamp = time(NULL); p.packet_type = NMB_PACKET; GetTimeOfDay(&tval); if (!send_packet(&p)) return(False); retries--; while (1) { struct timeval tval2; GetTimeOfDay(&tval2); if (TvalDiff(&tval,&tval2) > retry_time) { if (!retries) break; if (!found && !send_packet(&p)) return False; GetTimeOfDay(&tval); retries--; } if ((p2=receive_packet(fd,NMB_PACKET,90))) { struct nmb_packet *nmb2 = &p2->packet.nmb; if (nmb->header.name_trn_id != nmb2->header.name_trn_id || !nmb2->header.response) { /* its not for us - drop it */ continue; } if (nmb2->header.opcode != 0 || nmb2->header.nm_flags.bcast || nmb2->header.rcode || !nmb2->header.ancount || nmb2->answers->rr_type != 0x21) { /* XXXX what do we do with this? could be a redirect, but we'll discard it for the moment */ free_packet(p2); continue; } H_interpret_node_status(&nmb2->answers->rdata[0]); free_packet(p2); return(True); } } #ifndef SCANNER DEBUG(0,("No status response (this is not unusual)\n")); #endif return(False); } #endif /* STEPPING */ /**************************************************************************** do a netbios name query to find someones IP ****************************************************************************/ BOOL name_query(int fd,char *name,int name_type, BOOL bcast,BOOL recurse, struct in_addr to_ip, struct in_addr *ip,void (*fn)()) { BOOL found=False; int retries = 3; int retry_time = bcast?250:2000; struct timeval tval; struct packet_struct p; struct packet_struct *p2; struct nmb_packet *nmb = &p.packet.nmb; bzero((char *)&p,sizeof(p)); if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100); name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; nmb->header.name_trn_id = name_trn_id; nmb->header.opcode = 0; nmb->header.response = False; nmb->header.nm_flags.bcast = bcast; nmb->header.nm_flags.recursion_available = CanRecurse; nmb->header.nm_flags.recursion_desired = recurse; nmb->header.nm_flags.trunc = False; nmb->header.nm_flags.authoritative = False; nmb->header.rcode = 0; nmb->header.qdcount = 1; nmb->header.ancount = 0; nmb->header.nscount = 0; nmb->header.arcount = 0; make_nmb_name(&nmb->question.question_name,name,name_type,scope); nmb->question.question_type = 0x20; nmb->question.question_class = 0x1; p.ip = to_ip; p.port = NMB_PORT; p.fd = fd; p.timestamp = time(NULL); p.packet_type = NMB_PACKET; GetTimeOfDay(&tval); if (!send_packet(&p)) return(False); retries--; while (1) { struct timeval tval2; GetTimeOfDay(&tval2); if (TvalDiff(&tval,&tval2) > retry_time) { if (!retries) break; if (!found && !send_packet(&p)) return False; GetTimeOfDay(&tval); retries--; } if ((p2=receive_packet(fd,NMB_PACKET,90))) { struct nmb_packet *nmb2 = &p2->packet.nmb; if (nmb->header.name_trn_id != nmb2->header.name_trn_id || !nmb2->header.response) { /* its not for us - maybe deal with it later (put it on the queue?) */ if (fn) fn(p2); else free_packet(p2); continue; } if (nmb2->header.opcode != 0 || nmb2->header.nm_flags.bcast || nmb2->header.rcode || !nmb2->header.ancount) { /* XXXX what do we do with this? could be a redirect, but we'll discard it for the moment */ free_packet(p2); continue; } if (ip) { putip((char *)ip,&nmb2->answers->rdata[2]); DEBUG(fn?3:2,("Got a positive name query response from %s", inet_ntoa(p2->ip))); DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip))); } found=True; retries=0; free_packet(p2); if (fn) break; } } return(found); } /**************************************************************************** construct and send a netbios DGRAM Note that this currently sends all answers to port 138. thats the wrong things to do! I should send to the requestors port. XXX **************************************************************************/ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len, char *srcname,char *dstname, int src_type,int dest_type, struct in_addr dest_ip, struct in_addr src_ip) { struct packet_struct p; struct dgram_packet *dgram = &p.packet.dgram; char *ptr,*p2; char tmp[4]; bzero((char *)&p,sizeof(p)); dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */ dgram->header.flags.node_type = M_NODE; dgram->header.flags.first = True; dgram->header.flags.more = False; dgram->header.dgm_id = name_trn_id++; dgram->header.source_ip = src_ip; dgram->header.source_port = DGRAM_PORT; dgram->header.dgm_length = 0; /* let build_dgram() handle this */ dgram->header.packet_offset = 0; make_nmb_name(&dgram->source_name,srcname,src_type,scope); make_nmb_name(&dgram->dest_name,dstname,dest_type,scope); ptr = &dgram->data[0]; /* now setup the smb part */ ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */ memcpy(tmp,ptr,4); set_message(ptr,17,17 + len,True); memcpy(ptr,tmp,4); CVAL(ptr,smb_com) = SMBtrans; SSVAL(ptr,smb_vwv1,len); SSVAL(ptr,smb_vwv11,len); SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); SSVAL(ptr,smb_vwv13,3); SSVAL(ptr,smb_vwv14,1); SSVAL(ptr,smb_vwv15,1); SSVAL(ptr,smb_vwv16,2); p2 = smb_buf(ptr); strcpy(p2,mailslot); p2 = skip_string(p2,1); memcpy(p2,buf,len); p2 += len; dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */ p.ip = dest_ip; p.port = DGRAM_PORT; p.fd = fd; p.timestamp = time(NULL); p.packet_type = DGRAM_PACKET; return(send_packet(&p)); } nat-1.0.orig/nat.c0100600000175000017500000001750206301746754015071 0ustar jfernandezjfernandez#include #include #include #include #ifdef _WIN32 #include #endif #ifdef __STDC__ #include #else #include #endif #include "parse_ip.h" extern char *optarg; extern int optind; extern int errno; char *outputfile = NULL; /* where to put output */ char *userfile = NULL; /* where to get usernames */ char *passfile = NULL; /* where to get passwords */ FILE *userfd = NULL; /* userlist file stream */ FILE *passfd = NULL; /* passlist file stream */ struct vuln_res { u_long vr_vulid; char **vr_output; struct vuln_res *vr_next; }; void natprintf(char *format, ...); struct vuln_res *module_16000(); int main(argc, argv) int argc; char **argv; { struct vuln_res *vr; u_long ipaddr; int opt; char *progname; struct ipstr *hosts; progname = strdup(argv[0]); while ((opt = getopt(argc, argv, "o:u:p:")) != -1) switch(opt) { case 'o': outputfile = strdup(optarg); break; case 'u': userfile = strdup(optarg); break; case 'p': passfile = strdup(optarg); break; default : exit(-1); } argc -= optind; argv += optind; if (argc < 1) { fprintf(stderr,"usage: %s [-o filename] [-u userlist] [-p passlist]"\ "
\n", progname); exit(1); } if (userfile) { if ((userfd = fopen(userfile, "r"))) natprintf("[*]--- Reading usernames from %s\n", userfile); else { natprintf("[*]--- Error: cannot open %s\n", userfile); exit(-1); } } if (passfile) { if ((passfd = fopen(passfile, "r"))) natprintf("[*]--- Reading passwords from %s\n", passfile); else { natprintf("[*]--- Error: cannot open %s\n", passfile); exit(-1); } } if ((passfile && !userfile) || (userfile && !passfile)) { natprintf("[*]--- Please specify both userlist and password list\n"); exit(-1); } for (hosts=(struct ipstr *)parse_ip(argv[0]); hosts; hosts=hosts->next) { natprintf("\n[*]--- Checking host: %s\n", hosts->name); if (userfd) rewind(userfd); if (passfd) rewind(passfd); /* * Run the checks */ if ((vr=module_16000(inet_addr(hosts->name)))==NULL) { natprintf("[*]--- Was not able to obtain any information from "\ "remote server\n"); } } if (userfd) fclose(userfd); if (passfd) fclose(passfd); #ifndef VERBOSE for (; vr; vr = vr->vr_next) { char **ptr; natprintf("\n"); for (ptr = vr->vr_output; *ptr; ptr++) natprintf("%lu: %s\n", vr->vr_vulid, *ptr); } #endif exit(0); } struct vuln_res * bugblk; /* generic one to build a chain thereof */ struct vuln_res * bughead; /* start of [malloced] chain */ struct vuln_res * prev_bugblk; /* temporary "backlink" pointer */ int ptr_vuln = 0; int idx_vuln = 1; int cur_vuln = 0; char * vuln_strings[128] = { "", "", "", "" /* will be filled in later on */ }; int vuln_ids [128]; /* corresponding bug-ID block */ char * vvr_strings[256]; /* ptr block for selected items */ int ptr_vvr = 0; /* and *its* index */ static u_long prev_ip = { 0L }; /* really shd be in_addr */ static int prev_res = 0; void donothing () {} /* printf / fprintf fakeout */ extern char * get_block(); extern int fill_block(); int fill_vuln (char * flag, char * str) { char buf [128]; register char * p; register int x; if (! flag) /* various safety checks */ return (0); if (cur_vuln <= 0) return (0); if (ptr_vuln > 127) return (0); StrnCpy (buf, flag, 40); x = strlen (buf); p = buf + x; x = 79 - x; StrnCpy (p, str, x); /* jam it in where we can */ buf[79] = '\0'; x = fill_block (vuln_strings, buf); if (x >= 0) { vuln_ids[x] = cur_vuln; /* stash bugid of this string, too */ ptr_vuln++; } return (x); /* preserve returned idx! */ } /* fill_vuln */ char * get_vuln (int id) { register int x; while (ptr_vuln < 127) { ptr_vuln++; /* preindex; first item is [1] */ if (vuln_ids[ptr_vuln] == id) { x = ptr_vuln; return (get_block (vuln_strings, x)); } } /* while ptr_vuln */ return (NULL); /* oops, no more vulns! */ } /* get_vuln */ int clear_block (blk, idx) char ** blk; int idx; { static char * nullstr = ""; register int x = idx; if (x <= 0) /* entry 0 is special */ goto cbbogus; if (! blk) goto cbbogus; while (x < 128) { /* more runaway protection */ if (blk[x] == NULL) break; /* done! */ if (blk[x][0]) { blk[x][0] = '\0'; /* zap any old content */ free (blk[x]); /* and throw this fish back in */ } blk[x] = nullstr; x++; } return (1); cbbogus: fprintf (stderr, "OOPS! clear_block tried to clear bogus entry %d @ %x\n", idx, blk); return (0); } /* clear_block */ struct vuln_res * module_16000(ipaddr) u_long ipaddr; { register int i; register char * pp; char *buf, **ptr; int strsize; if (ipaddr == 0L) return ((struct vuln_res *) -1); if (ipaddr != prev_ip) { /* got a new host to check? */ clear_block (vuln_strings, 1); /* in case it contains old stuff */ for (i = 1; i < 127; i++) { vuln_strings[i] = vuln_strings[0]; vuln_ids[i] = 0; } vuln_strings[127] = NULL; /* put in end-of-block indicator */ i = nas_step (ipaddr); /* summon the big ol' monster */ prev_ip = ipaddr; /* record the fact that we did */ prev_res = i; /* and the outcome */ } /* if new ipaddr */ if (prev_res == 0) return ((struct vuln_res *) NULL); /* no netbios there, buckaroo */ ptr_vvr = 0; prev_bugblk = NULL; bughead = NULL; for (i = 16000 ; i <= 16010 ; i++) { /* applicable bug-ID range */ ptr_vuln = 0; /* restart results index */ pp = get_vuln (i); /* anything for this bug-ID? */ if (!pp) continue; /* nope, skip it */ bugblk = (struct vuln_res *) malloc (sizeof (struct vuln_res)); if (!bugblk) continue; /* or try to, anyway.. */ if (prev_bugblk) { prev_bugblk->vr_next = bugblk; /* hook up the chain */ } else { bughead = bugblk; /* save the start point */ } prev_bugblk = bugblk; /* and dangle the next link */ bugblk->vr_vulid = i; bugblk->vr_output = &vvr_strings[ptr_vvr]; /* ack!! */ bugblk->vr_next = NULL; vvr_strings[ptr_vvr] = pp; /* chain off to real result string */ ptr_vvr++; while (pp = get_vuln (i)) { /* collect the rest of 'em */ vvr_strings[ptr_vvr] = pp; ptr_vvr++; } vvr_strings[ptr_vvr] = NULL; /* terminate this block */ ptr_vvr++; /* and point just past it */ } /* for i = bugid */ for (prev_bugblk = bughead; prev_bugblk; prev_bugblk = prev_bugblk->vr_next) { strsize = 0; for (ptr = prev_bugblk->vr_output; *ptr; ptr++) strsize += strlen(*ptr)+10; buf = (char *)malloc(strsize+100); memset(buf, 0, strsize+100); for (ptr = prev_bugblk->vr_output; *ptr; ptr++) { strcat(buf, *ptr); strcat(buf, "\n"); } prev_bugblk->vr_output = (char **)malloc(2); prev_bugblk->vr_output[0] = buf; prev_bugblk->vr_output[1] = NULL; } return (bughead); } /* * Write format to file, opening file if it's not open */ #ifdef __STDC__ void natprintf(char *format, ...) { #else void natprintf(va_alist) va_dcl { char *format; #endif va_list ap; static FILE *outfd = NULL; char *s; #ifdef __STDC__ va_start(ap, format); #else va_start(ap); format = va_arg(ap,char *); #endif vfprintf(stdout, format, ap); if (!outputfile) return; if (!outfd) { if (!(outfd = fopen(outputfile, "a"))) { fprintf(stderr, "[*]--- Error: Unable to open: %s\n", outputfile); exit(-1); } } vfprintf(outfd, format, ap); return; } nat-1.0.orig/nat.1.txt0100600000175000017500000000770606301746754015632 0ustar jfernandezjfernandez NAT(1) NAT(1) NNAAMMEE nat - NetBIOS Auditing Tool SSYYNNOOPPSSIISS nat [-o ] [-u ] [-p ] <> DDEESSCCRRIIPPTTIIOONN nnaatt is a tool written to perform various security checks on systems offering the NetBIOS file sharing service. nnaatt will attempt to retrieve all information availible from the remote server, and attempt to access any services pro- vided by the server. OOPPTTIIOONNSS --oo Specify the oouuttppuutt file. All results from the scan will be written to the specified file, in addition to standard output. --uu Specify the file to read uusseerrnnaammeess from. Usernames will be read from the specified file when attempt- ing to guess the password on the remote server. Usernames should appear one per line in the speci- fied file. --pp Specify the file to read ppaasssswwoorrddss from. Passwords will be read from the specified file when attempt- ing to guess the password on the remote server. Passwords should appear one per line in the speci- fied file. <> Addresses should be specified in comma deliminated format, with no spaces. Valid address specifica- tions include: hostname - "hostname" is added 127.0.0.1-127.0.0.3, adds addresses 127.0.0.1 through 127.0.0.3 127.0.0.1-3, adds addresses 127.0.0.1 through 127.0.0.3 127.0.0.1-3,7,10-20, adds addresses 127.0.0.1 through 127.0.0.3, 127.0.0.7, 127.0.0.10 through 127.0.0.20. hostname,127.0.0.1-3, adds "hostname" and 127.0.0.1 through 127.0.0.1 All combinations of hostnames and address ranges as specified above are valid. 1 NAT(1) NAT(1) If no userlist or password list files are specified on the command line, a small set of defaults are used. This list includes the following: UUsseerrnnaammeess "ADMINISTRATOR", "GUEST", "BACKUP", "ROOT", "ADMIN", "USER", "DEMO", "TEST", "SYSTEM", "OPERATOR", "OPER", "LOCAL" PPaasssswwoorrddss "ADMINISTRATOR", "GUEST", "ROOT", "ADMIN", "PASSWORD", "TEMP", "SHARE", "WRITE", "FULL", "BOTH", "READ", "FILES", "DEMO", "TEST", "ACCESS", "USER", "BACKUP", "SYSTEM", "SERVER", "LOCAL" The password guessing routines are written in such a way that all passwords are tried for all usernames. Keep this in mind when using larger lists of passwords and user- names, as the time required increases exponentially with the size of these lists. SSUUPPPPOORRTTEEDD PPLLAATTFFOORRMMSS This version of nnaatt has been tested against Windows NT 4.0 and various versions of the Samba server written by Andrew Tridgell. This version of nnaatt has been tested and compiled on the following operating systems: SSoollaarriiss 2.5, LLiinnuuxx 2.0, FFrreeeeBBSSDD 2.1.5, OOppeennBBSSDD 2.0, BBSSDDII 2.1, WWiinnddoowwss NNTT 4.0, WWiinn-- ddoowwss 9955 FFIILLEESS nnaatt, uusseerrlliisstt..ttxxtt, ppaasssslliisstt..ttxxtt 2 nat-1.0.orig/nat.10100600000175000017500000000532206301746754015004 0ustar jfernandezjfernandez.TH NAT 1 .SH NAME nat - NetBIOS Auditing Tool .SH SYNOPSIS nat [-o <\fBoutput\fP>] [-u <\fBuserlist\fP>] [-p <\fBpasslist\fP>] \fB
\fP .SH DESCRIPTION .PP \fBnat\fP is a tool written to perform various security checks on systems offering the NetBIOS file sharing service. \fBnat\fP will attempt to retrieve all information availible from the remote server, and attempt to access any services provided by the server. .SH OPTIONS .IP \fB-o\fP Specify the \fBoutput\fP file. All results from the scan will be written to the specified file, in addition to standard output. .IP \fB-u\fP Specify the file to read \fBusernames\fP from. Usernames will be read from the specified file when attempting to guess the password on the remote server. Usernames should appear one per line in the specified file. .IP \fB-p\fP Specify the file to read \fBpasswords\fP from. Passwords will be read from the specified file when attempting to guess the password on the remote server. Passwords should appear one per line in the specified file. .IP \fB
\fP Addresses should be specified in comma deliminated format, with no spaces. Valid address specifications include: hostname - "hostname" is added 127.0.0.1-127.0.0.3, adds addresses 127.0.0.1 through 127.0.0.3 127.0.0.1-3, adds addresses 127.0.0.1 through 127.0.0.3 127.0.0.1-3,7,10-20, adds addresses 127.0.0.1 through 127.0.0.3, 127.0.0.7, 127.0.0.10 through 127.0.0.20. hostname,127.0.0.1-3, adds "hostname" and 127.0.0.1 through 127.0.0.1 All combinations of hostnames and address ranges as specified above are valid. .PP If no userlist or password list files are specified on the command line, a small set of defaults are used. This list includes the following: \fBUsernames\fP "ADMINISTRATOR", "GUEST", "BACKUP", "ROOT", "ADMIN", "USER", "DEMO", "TEST", "SYSTEM", "OPERATOR", "OPER", "LOCAL" \fBPasswords\fP "ADMINISTRATOR", "GUEST", "ROOT", "ADMIN", "PASSWORD", "TEMP", "SHARE", "WRITE", "FULL", "BOTH", "READ", "FILES", "DEMO", "TEST", "ACCESS", "USER", "BACKUP", "SYSTEM", "SERVER", "LOCAL" The password guessing routines are written in such a way that all passwords are tried for all usernames. Keep this in mind when using larger lists of passwords and usernames, as the time required increases exponentially with the size of these lists. .SH SUPPORTED PLATFORMS This version of \fBnat\fP has been tested against Windows NT 4.0 and various versions of the Samba server written by Andrew Tridgell. .PP This version of \fBnat\fP has been tested and compiled on the following operating systems: \fBSolaris\fP 2.5, \fBLinux\fP 2.0, \fBFreeBSD\fP 2.1.5, \fBOpenBSD\fP 2.0, \fBBSDI\fP 2.1, \fBWindows NT\fP 4.0, \fBWindows 95\fP .SH FILES \fBnat\fP, \fBuserlist.txt\fP, \fBpasslist.txt\fP nat-1.0.orig/nameserv.h0100600000175000017500000001121106301746754016123 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. NBT netbios header - version 2 Copyright (C) Andrew Tridgell 1994-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define MAX_DGRAM_SIZE 576 #define MIN_DGRAM_SIZE 12 #define NMB_PORT 137 #define DGRAM_PORT 138 #define SMB_PORT 139 enum name_source {LMHOSTS, REGISTER, SELF, DNS, DNSFAIL}; enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3}; enum packet_type {NMB_PACKET, DGRAM_PACKET}; /* a netbios name structure */ struct nmb_name { char name[17]; char scope[64]; int name_type; }; /* this is the structure used for the local netbios name list */ struct name_record { struct name_record *next; struct name_record *prev; struct nmb_name name; time_t death_time; struct in_addr ip; BOOL unique; enum name_source source; }; /* this is used by the list of domains */ struct domain_record { struct domain_record *next; struct domain_record *prev; fstring name; time_t lastannounce_time; int announce_interval; struct in_addr bcast_ip; }; /* this is used to hold the list of servers in my domain */ struct server_record { struct server_record *next; struct server_record *prev; fstring name; fstring comment; uint32 servertype; time_t death_time; }; /* a resource record */ struct res_rec { struct nmb_name rr_name; int rr_type; int rr_class; int ttl; int rdlength; char rdata[MAX_DGRAM_SIZE]; }; /* define a nmb packet. */ struct nmb_packet { struct { int name_trn_id; int opcode; BOOL response; struct { BOOL bcast; BOOL recursion_available; BOOL recursion_desired; BOOL trunc; BOOL authoritative; } nm_flags; int rcode; int qdcount; int ancount; int nscount; int arcount; } header; struct { struct nmb_name question_name; int question_type; int question_class; } question; struct res_rec *answers; struct res_rec *nsrecs; struct res_rec *additional; }; /* a datagram - this normally contains SMB data in the data[] array */ struct dgram_packet { struct { int msg_type; struct { enum node_type node_type; BOOL first; BOOL more; } flags; int dgm_id; struct in_addr source_ip; int source_port; int dgm_length; int packet_offset; } header; struct nmb_name source_name; struct nmb_name dest_name; int datasize; char data[MAX_DGRAM_SIZE]; }; /* define a structure used to queue packets. this will be a linked list of nmb packets */ struct packet_struct { struct packet_struct *next; struct packet_struct *prev; struct in_addr ip; int port; int fd; time_t timestamp; enum packet_type packet_type; union { struct nmb_packet nmb; struct dgram_packet dgram; } packet; }; /* this defines a list of network interfaces */ struct net_interface { struct net_interface *next; struct in_addr ip; struct in_addr bcast; struct in_addr netmask; }; /* prototypes */ void free_nmb_packet(struct nmb_packet *nmb); void free_packet(struct packet_struct *packet); struct packet_struct *read_packet(int fd,enum packet_type packet_type); BOOL send_packet(struct packet_struct *p); struct packet_struct *receive_packet(int fd,enum packet_type type,int timeout); void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope); BOOL name_query(int fd,char *name,int name_type, BOOL bcast,BOOL recurse, struct in_addr to_ip, struct in_addr *ip,void (*fn)()); BOOL name_status(int fd,char *name,int name_type,BOOL recurse, struct in_addr to_ip,char *master,char *rname, void (*fn)()); BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len, char *srcname,char *dstname, int src_type,int dest_type, struct in_addr dest_ip, struct in_addr src_ip); char *namestr(struct nmb_name *n); nat-1.0.orig/local.h0100600000175000017500000001312006301746754015376 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* local definitions for file server */ #ifndef _LOCAL_H #define _LOCAL_H /* This defines the section name in the configuration file that will contain */ /* global parameters - that is, parameters relating to the whole server, not */ /* just services. This name is then reserved, and may not be used as a */ /* a service name. It will default to "global" if not defined here. */ #define GLOBAL_NAME "global" #define GLOBAL_NAME2 "globals" /* This defines the section name in the configuration file that will refer to the special "homes" service */ #define HOMES_NAME "homes" /* This defines the section name in the configuration file that will refer to the special "printers" service */ #define PRINTERS_NAME "printers" /* This defines the name of the printcap file. It is MOST UNLIKELY that this will change BUT! Specifying a file with the format of a printcap file but containing only a subset of the printers actually in your real printcap file is a quick-n-dirty way to allow dynamic access to a subset of available printers. */ #define PRINTCAP_NAME "/etc/printcap" /* set these to define the limits of the server. NOTE These are on a per-client basis. Thus any one machine can't connect to more than MAX_CONNECTIONS services, but any number of machines may connect at one time. */ #define MAX_CONNECTIONS 127 #define MAX_OPEN_FILES 100 /* the max number of connections that the smbstatus program will show */ #define MAXSTATUS 1000 /* max number of directories open at once */ /* note that with the new directory code this no longer requires a file handle per directory, but large numbers do use more memory */ #define MAXDIR 64 #define WORDMAX 0xFFFF /* separators for lists */ #define LIST_SEP " \t,;:\n\r" #ifndef LOCKDIR #define LOCKDIR "/tmp/samba" #endif /* this is where browse lists are kept in the lock dir */ #define SERVER_LIST "browse.dat" /* the print command on the server, %s is replaced with the filename */ /* note that the -r removes the file after printing - you'll run out */ /* of disk pretty quickly if you don't. This command is only used as */ /* the default - it can be overridden in the configuration file. */ #define PRINT_COMMAND "lpr -r %s" /* the lpq command on the server. the printername is passed as an argument */ #ifndef LPQ_COMMAND #define LPQ_COMMAND "lpq -P" #endif /* shall guest entries in printer queues get changed to user entries, so they can be deleted using the windows print manager? */ #define LPQ_GUEST_TO_USER /* shall filenames with illegal chars in them get mangled in long filename listings? */ #define MANGLE_LONG_FILENAMES /* define this if you want to stop spoofing with .. and soft links NOTE: This also slows down the server considerably */ #define REDUCE_PATHS /* the size of the directory cache */ #define DIRCACHESIZE 20 /* what type of filesystem do we want this to show up as in a NT file manager window? */ #define FSTYPE_STRING "Samba" /* we have two time standards - local and GMT. This will try to sort them out. */ #define LOCAL_TO_GMT 1 #define GMT_TO_LOCAL (-1) /* do you want smbd to send a 1 byte packet to nmbd to trigger it to start when smbd starts? */ #ifndef PRIME_NMBD #define PRIME_NMBD 1 #endif /* do you want session setups at user level security with a invalid password to be rejected or allowed in as guest? WinNT rejects them but it can be a pain as it means "net view" needs to use a password You have 3 choices: GUEST_SESSSETUP = 0 means session setups with an invalid password are rejected. GUEST_SESSSETUP = 1 means session setups with an invalid password are rejected, unless the username does not exist, in which case it is treated as a guest login GUEST_SESSSETUP = 2 means session setups with an invalid password are treated as a guest login Note that GUEST_SESSSETUP only has an effect in user or server level security. */ #ifndef GUEST_SESSSETUP #define GUEST_SESSSETUP 0 #endif /* the default pager to use for the client "more" command. Users can override this with the PAGER environment variable */ #ifndef PAGER #define PAGER "more" #endif /* the size of the uid cache used to reduce valid user checks */ #define UID_CACHE_SIZE 4 /* the following control timings of various actions. Don't change them unless you know what you are doing. These are all in seconds */ #define DEFAULT_SMBD_TIMEOUT (60*60*24*7) #define SMBD_RELOAD_CHECK (10) #define SHARE_MODES_CHECK (10) #define SHARE_MODES_CLEAN (300) #define IDLE_CLOSED_TIMEOUT (30) #define DPTR_IDLE_TIMEOUT (120) #define SMBD_SELECT_LOOP (10) #define NMBD_SELECT_LOOP (10) #define BROWSE_INTERVAL (60) #define REGISTRATION_INTERVAL (10*60) #define NMBD_INETD_TIMEOUT (120) #define NMBD_MAX_TTL (24*60*60) #define LPQ_LOCK_TIMEOUT (5) /* the following are in milliseconds */ #define LOCK_RETRY_TIMEOUT (100) /* do you want to dump core (carefully!) when an internal error is encountered? Samba will be careful to make the core file only accessible to root */ #define DUMP_CORE 1 /* what is the longest significant password available on your system? Knowing this speeds up password searches a lot */ #ifndef PASSWORD_LENGTH #define PASSWORD_LENGTH 8 #endif #define SMB_ALIGNMENT 1 /* shall we support browse requests via a FIFO to nmbd? */ #define ENABLE_FIFO 1 #ifdef SCANNER #undef IDLE_CLOSED_TIMEOUT #define IDLE_CLOSED_TIMEOUT (600) #endif /* SCANNER */ #endif nat-1.0.orig/loadparm.h0100600000175000017500000000001406301746754016101 0ustar jfernandezjfernandez/* empty */ nat-1.0.orig/kanji.h0100600000175000017500000000012306301746754015377 0ustar jfernandezjfernandez/* stubs for system.c */ #define unix_to_dos(x,y) (x) #define dos_to_unix(x,y) (x) nat-1.0.orig/includes.h0100600000175000017500000005120106301746754016114 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ #ifndef _INCLUDES_H #define _INCLUDES_H /* Unix SMB/Netbios implementation. Version 1.9. Machine customisation and include handling Copyright (C) Andrew Tridgell 1994-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This file does all the #includes's. This makes it easier to port to a new unix. Hopefully a port will only have to edit the Makefile and add a section for the new unix below. */ /* the first OS dependent section is to setup what includes will be used. the main OS dependent section comes later on */ #ifdef ALTOS #define NO_UTIMEH #endif #ifdef MIPS #define POSIX_H #define NO_UTIMEH #endif #ifdef sun386 #define NO_UTIMEH #endif #ifdef NEXT2 #define NO_UTIMEH #endif #ifdef NEXT3_0 #define NO_UTIMEH #define NO_UNISTDH #endif #ifdef APOLLO #define NO_UTIMEH #define NO_SYSMOUNTH #define NO_UNISTDH #endif #ifdef AIX #define NO_SYSMOUNTH #endif #ifdef M88K_R3 #define SVR3H #define NO_RESOURCEH #endif #ifdef DNIX #define NO_SYSMOUNTH #define NO_NETIFH #define NO_RESOURCEH #define PRIME_NMBD 0 #define NO_SETGROUPS #endif #ifdef ISC #define SYSSTREAMH #define NO_RESOURCEH #endif #ifdef QNX #define NO_RESOURCEH #define NO_SYSMOUNTH #define USE_MMAP 1 #ifdef __386__ #define __i386__ #endif #endif #ifdef NEWS42 #define NO_UTIMEH #define NO_STRFTIME #define NO_UTIMBUF #define REPLACE_MKTIME #define NO_TM_NAME #endif #ifdef OS2 #define NO_SYSMOUNTH #define NO_NETIFH #endif #if (defined(SHADOW_PWD)||defined(OSF1_ENH_SEC)||defined(SecureWare)||defined(PWDAUTH)) #define PASSWORD_LENGTH 16 #endif /* here is the general includes section - with some ifdefs generated by the previous section */ #include "local.h" #include #ifdef POSIX_STDLIBH #include #else #include #endif #include #include #ifndef NO_UTIMEH #include #endif #include #ifdef SVR3H #include #include #include #include #include #endif #include #include #include #ifdef POSIX_H #include #include #include #else #include #include #endif #include #include #include #include #include #include #include #ifndef NO_RESOURCEH #include #endif #ifndef NO_SYSMOUNTH #include #endif #include #ifdef __STDC__ #include #else #include #endif #ifndef NO_UNISTDH #include #endif #include #ifdef SYSSTREAMH #include #endif #ifndef NO_NETIFH #ifdef POSIX_H #include #else #include #endif #endif #if USE_MMAP #include #endif #if defined(GETPWANAM) #include #include #include #include #endif #if defined(SHADOW_PWD) && !defined(NETBSD) && !defined(OPENBSD) && !defined(CONVEX) #include #endif /* this might be different on different systems */ #ifdef QUOTAS #include #ifndef CRAY #include #else #include #endif #endif #ifdef SYSLOG #include #endif /*************************************************************************** Here come some platform specific sections ***************************************************************************/ #ifdef LINUX #include #include #include #include #include #ifndef NO_ASMSIGNALH #include #endif #define SIGNAL_CAST (__sighandler_t) #define USE_GETCWD #define USE_SETSID #define HAVE_BZERO #define HAVE_MEMMOVE #ifdef SHADOW_PWD #ifndef crypt #define crypt pw_encrypt #endif #endif #endif #ifdef SUNOS4 #define SIGNAL_CAST (void (*)(int)) #include #include #include #include #include #include #include #include /* #include */ #ifdef sun386 #define NO_STRFTIME #define NO_UTIMBUF #define mktime timelocal typedef unsigned short mode_t; #else #include #define NO_STRERROR #endif #define REPLACE_GETPASS #define BSD_TERMIO #endif #ifdef SUNOS5 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int gettimeofday (struct timeval *, void *); extern int gethostname (char *name, int namelen); extern int innetgr (const char *, const char *, const char *, const char *); #define USE_SETVBUF #define SIGNAL_CAST (void (*)(int)) #ifndef SYSV #define SYSV #endif #define USE_WAITPID #define REPLACE_STRLEN #define USE_STATVFS #define USE_GETCWD #define USE_SETSID #define REPLACE_GETPASS #endif #ifdef ULTRIX #include #include #include #include #ifdef ULTRIX_AUTH #include #endif char *getwd(char *); #define NOSTRDUP #ifdef __STDC__ #define SIGNAL_CAST (void(*)(int)) #endif #define USE_DIRECT #endif #ifdef SGI #include #include #include #include #ifndef SYSV #define SYSV #endif #define SIGNAL_CAST (void (*)()) #define STATFS4 #define USE_WAITPID #define USE_DIRECT #endif #ifdef SGI5 #include #include #include #include #include #define USE_WAITPID #define NETGROUP #ifndef SYSV #define SYSV #endif #define SIGNAL_CAST (void (*)()) #define USE_STATVFS #define USE_WAITPID #endif #ifdef MIPS #include #include #include #include #include #include #include #define SIGNAL_CAST (void (*)()) typedef int mode_t; extern struct group *getgrnam(); extern struct passwd *getpwnam(); #define STATFS4 #define NO_STRERROR #define REPLACE_STRSTR #endif /* MIPS */ #ifdef DGUX #include #include #include #include #include #include #define SYSV #define USE_WAITPID #define SIGNAL_CAST (void (*)(int)) #define STATFS4 #define USE_GETCWD #endif #ifdef SVR4 #include #include #include #include #include #include #include #include #include #include #include #include #define SYSV #define USE_WAITPID #define SIGNAL_CAST (void (*)(int)) #define USE_STATVFS #define USE_GETCWD #endif #ifdef OSF1 #include #include #include char *getwd(char *); char *mktemp(char *); /* No standard include */ #include #include /* both for inet_ntoa */ #define SIGNAL_CAST ( void (*) (int) ) #define STATFS3 #define USE_F_FSIZE #include #ifdef OSF1_ENH_SEC #include #include #include #include #include #define PASSWORD_LENGTH 16 #endif /* OSF1_ENH_SEC */ #endif #ifdef CLIX #include #define SIGNAL_CAST (void (*)()) #include #include #include #define NO_EID #define USE_WAITPID #define STATFS4 #define NO_FSYNC #define USE_GETCWD #define USE_SETSID #define REPLACE_GETPASS #define NO_GETRLIMIT #endif /* CLIX */ #ifdef BSDI #include #include #define SIGNAL_CAST (void (*)()) #define USE_DIRECT #endif #if defined(NETBSD) || defined(OPENBSD) #include #include #include /* you may not need this */ #define NO_GETSPNAM #define SIGNAL_CAST (void (*)()) #define USE_DIRECT #define REPLACE_INNETGR #endif #ifdef FreeBSD #include #include #include #include #define SIGNAL_CAST (void (*)()) #define USE_DIRECT #define REPLACE_INNETGR #endif #ifdef AIX #include #include #include #include #include #include #include #include #include #define SYSV #define USE_WAITPID #define SIGNAL_CAST (void (*)()) #define DEFAULT_PRINTING PRINT_AIX #endif #ifdef HPUX #include #include #include #include #include #include #include #define SIGNAL_CAST (void (*)(__harg)) #define SELECT_CAST (int *) #define SYSV #define USE_WAITPID #define WAIT3_CAST2 (int *) #define USE_GETCWD #define USE_SETSID #define USE_SETRES #define DEFAULT_PRINTING PRINT_HPUX #define SIGCLD_IGNORE #endif #ifdef SEQUENT #include #include #include #include #include #include #include #include #include #include #define SIGNAL_CAST (void (*)(int)) #define USE_WAITPID #define USE_GETCWD #define NO_EID #define STATFS4 #define USE_DIRECT #endif #ifdef NEXT2 #include #include #include #include #define bzero(b,len) memset(b,0,len) #define mode_t int #define NO_UTIMBUF #include #define NOSTRDUP #define USE_DIRECT #define USE_WAITPID #endif #ifdef NEXT3_0 #include #include #include #define bzero(b,len) memset(b,0,len) #define NO_UTIMBUF #include #define NOSTRDUP #define USE_DIRECT #define mode_t int #define GID_TYPE int #define gid_t int #define SIGNAL_CAST (void (*)(int)) #define WAIT3_CAST1 (union wait *) #endif #ifdef APOLLO #include #include #include #define NO_UTIMBUF #define USE_DIRECT #define USE_GETCWD #define SIGNAL_CAST (void (*)()) #define HAVE_FCNTL_LOCK 0 #define HAVE_GETTIMEOFDAY #define STATFS4 #endif #ifdef SCO #include #include #include #include #include #include #include #include #include #ifdef EVEREST #include #endif #ifdef NETGROUP #include #endif #ifdef SecureWare #include #include #include #define crypt bigcrypt #endif #ifndef EVEREST #define ftruncate(f,l) syscall(0x0a28,f,l) #endif #define SIGNAL_CAST (void (*)(int)) #define USE_WAITPID #define USE_GETCWD #define USE_SETSID #ifdef SCO3_2_2 #define NO_EID #else #ifndef EVEREST #define USE_IFREQ #endif #endif #define STATFS4 #define NO_FSYNC #ifndef EVEREST #define NO_INITGROUPS #endif #define HAVE_PATHCONF #define NO_GETRLIMIT #endif /* Definitions for RiscIX */ #ifdef RiscIX #define SIGNAL_CAST (void (*)(int)) #include #include #include #include #include #include #define HAVE_GETTIMEOFDAY #define NOSTRCASECMP #define NOSTRDUP #endif #ifdef ISC #include #include #include #include #include #include #include #include #include #include #define FIONREAD FIORDCHK #define SYSV #define USE_WAITPID #define SIGNAL_CAST (void (*)(int)) #define USE_GETCWD #define USE_SETSID #define USE_IFREQ #define NO_FTRUNCATE #define STATFS4 #define NO_FSYNC #endif #ifdef AUX #include #include #include #include #include #include #define SYSV #define USE_WAITPID #define SIGNAL_CAST (void (*)(int)) char *strdup (char *); #define USE_GETCWD #endif #ifdef M88K_R3 #include #include #include #include #define STATFS4 #define SYSV #define USE_WAITPID #define SIGNAL_CAST (void (*)(int)) char *strdup (char *); #define USE_GETCWD #define NO_FSYNC #define NO_EID #endif #ifdef DNIX #include #include #include #include #include #define NO_GET_BROADCAST #define USE_WAITPID #define USE_GETCWD #define USE_SETSID #define STATFS4 #define NO_EID #define PF_INET AF_INET #define NO_STRERROR #define ftruncate(f,l) chsize(f,l) #endif /* DNIX */ #ifdef CONVEX #define SIGNAL_CAST (void (*)(int)) #include #include #include #include #include #include #define DONT_REINSTALL_SIG #define USE_SIGBLOCK #define USE_WAITPID #define SIGNAL_CAST (_SigFunc_Ptr_t) #define NO_GETSPNAM #define HAVE_MEMMOVE extern char *mktemp(char *); extern int fsync(int); extern int seteuid(uid_t); extern int setgroups(int, int *); extern int initgroups(char *, int); extern int statfs(char *, struct statfs *); extern int setegid(gid_t); extern int getopt(int, char *const *, const char *); extern int chroot(char *); extern int gettimeofday(struct timeval *, struct timezone *); extern int gethostname(char *, int); extern char *crypt(char *, char *); extern char *getpass(char *); #endif #ifdef CRAY #define MAXPATHLEN 1024 #include #include #include #include #define SIGNAL_CAST (void (*)(int)) #define SIGCLD_IGNORE #define HAVE_FCNTL_LOCK 1 #define USE_SETSID #define STATFS4 #endif #ifdef ALTOS #include #include #include #include #include #define const #define uid_t int #define gid_t int #define mode_t int #define ptrdiff_t int #define HAVE_GETGRNAM 0 #define NO_EID #define NO_FSYNC #define NO_FTRUNCATE #define NO_GETRLIMIT #define NO_INITGROUPS #define NO_SELECT #define NO_SETGROUPS #define NO_STRERROR #define NO_STRFTIME #define NO_TM_NAME #define NO_UTIMEH #define NOSTRCASECMP #define REPLACE_MKTIME #define REPLACE_RENAME #define REPLACE_STRSTR #define STATFS4 #define USE_GETCWD #endif #ifdef QNX #define STATFS4 #include #include #include #include #define SIGNAL_CAST (void (*)()) #define USE_WAITPID #define NO_INITGROUPS #define NO_SETGROUPS #define HAVE_TIMEZONE #define USE_GETCWD #define USE_SETSID #define HAVE_FCNTL_LOCK 1 #define DEFAULT_PRINTING PRINT_QNX #endif #ifdef NEWS42 #include #include #include #include typedef int mode_t; #endif #ifdef OS2 #include #include #include #include #define SIGNAL_CAST (void (*)()) #define HAVE_FCNTL_LOCK 0 #define USE_WAITPID #define NO_GET_BROADCAST #define NO_EID #define NO_SETGROUPS #define NO_INITGROUPS #define NO_CRYPT #define NO_STATFS #define NO_CHROOT #define NO_CHOWN #define strcasecmp stricmp #define strncasecmp strnicmp #endif /******************************************************************* end of the platform specific sections ********************************************************************/ /* #ifdef REPLACE_GETPASS extern char *getsmbpass(char *); #define getpass(s) getsmbpass(s) #endif */ #ifdef REPLACE_INNETGR #define innetgr(group,host,user,dom) InNetGr(group,host,user,dom) #endif #ifndef FD_SETSIZE #define FD_SETSIZE 255 #endif #ifndef MAXINT #define MAXINT ((((unsigned)1)<<(sizeof(int)*8-1))-1) #endif #ifndef __STDC__ #define const #endif /* Now for some other grungy stuff */ #ifdef NO_GETSPNAM struct spwd { /* fake shadow password structure */ char *sp_pwdp; }; #endif #ifndef HAVE_BZERO #ifndef bzero #define bzero(p,s) memset(p,0,s) #endif #endif #ifndef HAVE_MEMMOVE #ifndef memmove #define memmove(d,s,n) MemMove(d,s,n) #endif #endif #ifdef USE_DIRECT #include #endif /* some unixes have ENOTTY instead of TIOCNOTTY */ #ifndef TIOCNOTTY #ifdef ENOTTY #define TIOCNOTTY ENOTTY #endif #endif #ifndef SIGHUP #define SIGHUP 1 #endif /* if undefined then use bsd or sysv printing */ #ifndef DEFAULT_PRINTING #ifdef SYSV #define DEFAULT_PRINTING PRINT_SYSV #else #define DEFAULT_PRINTING PRINT_BSD #endif #endif #ifdef AFS_AUTH #include #include #endif #ifdef DFS_AUTH #include #include #endif #ifdef NO_UTIMBUF struct utimbuf { time_t actime; time_t modtime; }; #endif #ifdef NO_STRERROR #ifndef strerror extern char *sys_errlist[]; #define strerror(i) sys_errlist[i] #endif #endif #ifndef perror #define perror(m) printf("%s: %s\n",m,strerror(errno)) #endif #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 255 #endif #include "version.h" #include "smb.h" #include "byteorder.h" #ifdef SMB_PASSWD #include "smbpass.h" #endif #include "kanji.h" #include "charset.h" #ifndef S_IFREG #define S_IFREG 0100000 #endif #ifndef S_ISREG #define S_ISREG(x) ((S_IFREG & x)!=0) #endif #ifndef S_ISDIR #define S_ISDIR(x) ((S_IFDIR & x)!=0) #endif #ifdef UFC_CRYPT #define crypt ufc_crypt #endif #ifdef REPLACE_STRLEN #define strlen(s) Strlen(s) #endif #ifdef REPLACE_STRSTR #define strstr(s,p) Strstr(s,p) #endif #ifdef REPLACE_MKTIME #define mktime(t) Mktime(t) #endif #ifndef NGROUPS_MAX #define NGROUPS_MAX 128 #endif #ifndef EDQUOT #define EDQUOT ENOSPC #endif #ifndef HAVE_GETGRNAM #define HAVE_GETGRNAM 1 #endif #ifndef SOL_TCP #define SOL_TCP 6 #endif /* default to using ftruncate workaround as this is safer than assuming it works and getting lots of bug reports */ #ifndef FTRUNCATE_CAN_EXTEND #define FTRUNCATE_CAN_EXTEND 0 #endif /* maybe this unix doesn't separate RD and WR locks? */ #ifndef F_RDLCK #define F_RDLCK F_WRLCK #endif #ifndef ENOTSOCK #define ENOTSOCK EINVAL #endif #ifndef SIGCLD #define SIGCLD SIGCHLD #endif #ifndef HAVE_FCNTL_LOCK #define HAVE_FCNTL_LOCK 1 #endif #ifndef WAIT3_CAST2 #define WAIT3_CAST2 (struct rusage *) #endif #ifndef WAIT3_CAST1 #define WAIT3_CAST1 (int *) #endif #ifndef QSORT_CAST #define QSORT_CAST (int (*)()) #endif /* this is a rough check to see if this machine has a lstat() call. it is not guaranteed to work */ #if !(defined(S_ISLNK) || defined(S_IFLNK)) #define lstat stat #endif /* Not all systems declare ERRNO in errno.h... and some systems #define it! */ #ifndef errno extern int errno; #endif #ifdef NO_EID #define geteuid() getuid() #define getegid() getgid() #define seteuid(x) setuid(x) #define setegid(x) setgid(x) #endif #if (HAVE_FCNTL_LOCK == 0) /* since there is no locking available, system includes */ /* for DomainOS 10.4 do not contain any of the following */ /* #define's. So, to satisfy the compiler, add these */ /* #define's, although they arn't really necessary. */ #define F_GETLK 0 #define F_SETLK 0 #define F_WRLCK 0 #define F_UNLCK 0 #endif /* HAVE_FCNTL_LOCK == 0 */ #ifdef NOSTRCASECMP #define strcasecmp(s1,s2) StrCaseCmp(s1,s2) #define strncasecmp(s1,s2,n) StrnCaseCmp(s1,s2,n) #endif #ifndef strcpy #define strcpy(dest,src) StrCpy(dest,src) #endif /* possibly wrap the malloc calls */ #if WRAP_MALLOC /* undo the old malloc def if necessary */ #ifdef malloc #define xx_old_malloc malloc #undef malloc #endif #define malloc(size) malloc_wrapped(size,__FILE__,__LINE__) /* undo the old realloc def if necessary */ #ifdef realloc #define xx_old_realloc realloc #undef realloc #endif #define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__) /* undo the old free def if necessary */ #ifdef free #define xx_old_free free #undef free #endif #define free(ptr) free_wrapped(ptr,__FILE__,__LINE__) /* and the malloc prototypes */ void *malloc_wrapped(int,char *,int); void *realloc_wrapped(void *,int,char *,int); void free_wrapped(void *,char *,int); #endif #if WRAP_MEMCPY /* undo the old memcpy def if necessary */ #ifdef memcpy #define xx_old_memcpy memcpy #undef memcpy #endif #define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__) void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line); #endif #endif nat-1.0.orig/client.c0100600000175000017500000033171106301746754015566 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. SMB client Copyright (C) Andrew Tridgell 1994-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef SYSLOG #undef SYSLOG #endif #include "includes.h" #ifndef REGISTER #define REGISTER 0 #endif extern FILE *userfd; extern FILE *passfd; extern char *userfile; extern char *passfile; pstring cur_dir = "\\"; pstring cd_path = ""; pstring service=""; pstring desthost=""; pstring myname = ""; pstring password = ""; pstring username=""; pstring workgroup=WORKGROUP; BOOL got_pass = False; BOOL connect_as_printer = False; BOOL connect_as_ipc = False; char cryptkey[8]; BOOL doencrypt=False; extern pstring user_socket_options; /* * 30 second timeout on most commands */ #define CLIENT_TIMEOUT (30*1000) #define SHORT_TIMEOUT (5*1000) /* * value for unused fid field in trans2 secondary request */ #define FID_UNUSED (0xFFFF) int name_type = 0x20; int max_protocol = PROTOCOL_NT1; #ifdef SCANNER #include "vulns.h" #ifndef VERBOSE #define fprintf donothing #define printf donothing #endif #undef CLIENT_TIMEOUT #define CLIENT_TIMEOUT (15 * 1000) /* only 15 seconds here.. */ /* * stuff *this* file is gonna need: */ extern char * vuln_strings []; /* stuff to pass back thru the interface */ extern int vuln_ids[]; extern int cur_vuln; /* what bugid we're now working on */ extern int clear_block(); /* * control stuff for testing for ".." style bugs */ static file_info stash; file_info * cur_stash = NULL; int tested_stash = 0; /* * Some saved session variables in case of lossage */ int cur_port = 0; /* shouldn't be ushort??! */ pstring cur_user = ""; pstring cur_pass = ""; int cur_sec_mode = 0; int cur_protocol = 0; int cur_serr = 0; /* last server-class error */ /* some extra control flags */ BOOL read_pass = 0; BOOL stepping = 0; BOOL xflag = 0; /* yes, do encryption */ #endif /* SCANNER */ time_t newer_than = 0; int archive_level = 0; extern struct in_addr myip; extern pstring debugf; extern int DEBUGLEVEL; BOOL translation = False; /* clitar bits insert */ extern void cmd_tar(); extern void cmd_block(); extern void cmd_tarmode(); extern void cmd_setmode(); extern int blocksize; extern BOOL tar_inc; extern BOOL tar_reset; /* clitar bits end */ int cnum = 0; int pid = 0; int gid = 0; int uid = 0; int mid = 0; int myumask = 0755; int max_xmit = BUFFER_SIZE; extern pstring scope; BOOL prompt = True; int printmode = 1; BOOL recurse = False; BOOL lowercase = False; BOOL have_ip = False; struct in_addr dest_ip; #define SEPARATORS " \t\n\r" BOOL abort_mget = True; extern int Protocol; BOOL readbraw_supported = False; BOOL writebraw_supported = False; pstring fileselection = ""; extern file_info def_finfo; /* timing globals */ int get_total_size = 0; int get_total_time_ms = 0; int put_total_size = 0; int put_total_time_ms = 0; extern int Client; static int said_protocol = 0; /* Whether we've told the user the protocol already */ #ifdef SCANNER /* * external data blocks we fill in along the way. If these seem size limited, * not to worry; there's a much bigger dictionary waiting in the wings */ /* * XXX: any null entry must be first in the list, per fill_block() et al */ /* * XXX: should fill these with "live" info from the net FIRST, and then tack * on the "extra" test entries at the end, to avoid trying them first. */ /* try_? is starting array + filled-in from previous phases */ /* idx_? is index from which to start filling in additional data */ /* ptr_? is pointer used by uppair() to index through blocks */ /* * Names to attempt to connect to remote host with (The names associated * with the remote host itself). */ int ptr_names = 0; int idx_names = 1; char *try_names [] = { "*", "", "", "", "", "", "", "", "", /* placeholders for 8 more */ NULL /* trailer */ }; /* * Common usernames to guess */ int ptr_users = 0; int idx_users = 13; char *try_users [] = { "", "ADMINISTRATOR", /* the order of these IS somewhat relevant */ "GUEST", "BACKUP", "ROOT", "ADMIN", "USER", "DEMO", "TEST", "SYSTEM", "OPERATOR", "OPER", "LOCAL", "", "", "", "", "", "", "", "", /* placeholders for 8 more */ NULL /* trailer */ }; /* * Common passwords to guess */ int ptr_pass = 0; int idx_pass = 21; char * try_pass [] = { "", "ADMINISTRATOR", "GUEST", "ROOT", "ADMIN", "PASSWORD", "TEMP", "SHARE", "WRITE", "FULL", "BOTH", "READ", "FILES", "DEMO", "TEST", "ACCESS", "USER", "BACKUP", "SYSTEM", "SERVER", "LOCAL", "", "", "", "", "", "", "", "", /* placeholders for 16 more */ "", "", "", "", "", "", "", "", NULL /* trailer */ }; /* * Shares availibles on remote host */ int ptr_shares = 0; int idx_shares = 1; int hid_shares = 0; /* >= here are C$, etc */ char * try_shares [] = { "", "", "", "", "", "", "", "", "", /* placeholders for 16 more */ "", "", "", "", "", "", "", "", NULL /* trailer */ }; int ptr_browses = 0; int idx_browses = 0; char *browses [16]; char *smb_errstr(char *); /* * Create and fill a new data block entry. Return index of the block just * created, or 0 if no more empties available. Also return 0 if no entry was * made for whatever reason, i.e. nothing changed. * *NOTE: data blocks are 128 bytes [like fstrings] and copy is limited to * 126, so don't expect to cram a lotta stuff into it. Also each block contains * no greater than 128 entries; this *should* be enough unless we need a huge * one for trial passwords. */ int fill_block (char ** block, char * str) { register int i = 1; /* start at *second* entry */ register char ** p = block; if (!str) /* sanity */ return (0); if (str[0] == '\0') /* avoid empty strings, too */ return (0); for (; i < 128; i++) { /* runaway protection... */ if (p[i] == NULL) return (0); /* block is full! */ if (*p[i] == '\0') break; if (! strcmp (p[i], str)) /* avoid dupes */ return (0); } /* for i */ p[i] = (char *) malloc (128); /* okay, really need a new one */ if (! p[i]) return (0); memset (p[i], 0, 128); /* pre-clear it */ StrnCpy (p[i], str, 126); /* and be safe */ return (i); /* tell us which entry got filled */ } /* fill_block */ /* * Return the item from the specified block at the specified index, * return pointer to string or NULL. * */ char *get_block (blk, idx) char ** blk; int idx; { if (!blk) return(NULL); if (idx > 127) return (NULL); if (idx == 0) { /* first item *can* be a null-string */ if (blk[0] == NULL) return (NULL); return (blk[0]); } if (blk[idx]) if (*(blk[idx])) /* otherwise, see if it has content */ return (blk[idx]); return (NULL); /* nope, empty -- done */ } void donothing (); /* in module() file */ void cmd_tar() {} /* fakeouts for the sambatar stuff */ void cmd_block() {} void cmd_tarmode() {} void cmd_setmode() {} /* * Pick off the first dir entry and squirrel away its details. */ static void get_stash (file_info *finfo) { if (cur_stash != NULL) return; /* already got it */ cur_stash = &stash; memset (cur_stash, 0, sizeof (file_info)); memcpy (cur_stash, finfo, sizeof (file_info)); tested_stash = 1; /* flag do_dir to quit */ } /* get_stash */ /* * Compare first dir entry against saved one; holler if *different*. * * This checks for the .. bug. We compare 2 directory entries to see * if we successfully entered another directory by issuing ".." from the * root directory. */ static void cmp_stash (file_info *finfo) { register int diff_stash = 0; if (tested_stash) { /* should "never happen"... */ DEBUG (1,("Redundant cmp_stash call?!\n")); return; } tested_stash = 1; /* did-first-entry flag */ if (cur_stash == NULL) return; /* can't test! */ if (! cur_stash->name) /* various hairy errors */ return; if ((! finfo) || (! finfo->name)) return; /* * compare various fields to see if we're looking at the same file, and * set a flag if something doesn't match */ if (strcmp (cur_stash->name, finfo->name)) diff_stash = 1; if (cur_stash->size != finfo->size) diff_stash = 1; if (cur_stash->mtime != finfo->mtime) diff_stash = 1; if (diff_stash) { #ifdef VERBOSE natprintf("[*]--- WARNING: Was able to exercise .. bug in: %s\n", cur_dir); #endif DEBUG (0,("probable directory-handling bug using %s\n", cur_dir)); cur_vuln = VULID_DOTDOTBUG; fill_vuln ("Was able to exercise .. bug in directory:", cur_dir); } } static int upp_ctx = 0; /* uppair context: set to 0 to restart */ /* * Get a new user/passwd pair to try, either from the user or from dict [?]. * modifies global "username" and "password" so everyone can see 'em. */ /* * XXX: could be much cleaner if we eliminated the strcpys and just chuck * pointers around, but the guessing stuff is network-limited anyways and it * pays to give the target a *little* more time to recover between blows. * 'Sides, we want to preserve whatever gets us in.. */ static BOOL uppair() { char * user; char * pass; static int count = 0; pass = NULL; if (stepping) goto upp_mode; /* * password-only cases: we've already got "username" set and don't touch it */ if (read_pass) { pass = fgets (password, 128, stdin); if (! pass) return (False); /* EOF */ pass += strlen (password); pass--; if (*pass == '\n') *pass = '\0'; pass--; if (*pass == '\r') *pass = '\0'; return (1); } /* if read_pass */ /* * ordinary one-shot case */ pass = (char *)getpass("Password: "); goto upp_done; upp_mode: if ((upp_ctx == 0) || (upp_ctx == 4)) { /* first time thru? */ ptr_pass = 0; ptr_users = 0; strcpy (username, try_users[0]); /* first one is blank anyways */ upp_ctx++; } /* ctx = 0 */ if ((upp_ctx == 1) || (upp_ctx == 5)) { /* builtin and collected lists */ pass = get_block (try_pass, ptr_pass); ptr_pass++; /* for next time thru */ if (pass == NULL) { ptr_users++; if (upp_ctx == 5) /* only indexing passwords */ return (0); user = get_block (try_users, ptr_users); if (user == NULL) return (0); /* done! XXX: or goto big-dict */ strcpy (username, user); /* new username, so ... */ pass = try_pass[0]; /* restart passwd list */ ptr_pass = 1; /* fiddle for next time thru */ } /* pass == NULL */ } /* ctx = 1 */ if (upp_ctx == 2) { /* dunno yet */ ; /* bigdict here? */ } /* ctx = 2 */ if (upp_ctx == 3) { /* this got in before, reuse it */ strcpy (username, cur_user); strcpy (password, cur_pass); } /* ctx = 3 */ upp_done: if (pass == NULL) return (0); if (count > 20) { /* let the target recover... */ sleep (1); count = 0; } strcpy (password, pass); return (1); /* * wanna put permutation stuff [with appropriate state-stepping] here?? */ } #endif /* SCANNER */ #define CNV_LANG(s) (s) #define CNV_INPUT(s) ; static void send_logout(void ); BOOL reopen_connection(char *inbuf,char *outbuf); static int do_long_dir(char *inbuf,char *outbuf,char *Mask, int attribute,void (*fn)(),BOOL recurse_dir); static int do_short_dir(char *inbuf,char *outbuf,char *Mask, int attribute,void (*fn)(),BOOL recurse_dir); static BOOL call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt, int *rprcnt,int *rdrcnt,char *param,char *data, char **rparam,char **rdata); static BOOL send_trans_request(char *outbuf,int trans, char *name,int fid,int flags, char *data,char *param,uint16 *setup, int ldata,int lparam,int lsetup, int mdata,int mparam,int msetup); /* * Setup basics in a outgoing packet */ void setup_pkt(char *outbuf) { SSVAL(outbuf,smb_pid,pid); SSVAL(outbuf,smb_uid,uid); SSVAL(outbuf,smb_mid,mid); if (Protocol > PROTOCOL_CORE) { SCVAL(outbuf,smb_flg,0x8); SSVAL(outbuf,smb_flg2,0x1); } /* * Above is setting: flg: caseless-filenames; * flg2: long-filenames * WANT TO ADD: flg: 0x10 already-canon-filenames [set by !CLIENT!] * flg2: 0x2000 permit read if client has "execute" perm?? */ #ifdef SCANNER if (Protocol > PROTOCOL_CORE) { SCVAL(outbuf,smb_flg,0x18); SSVAL(outbuf,smb_flg2,0x2001); } #endif } /* * write to a local file with CR/LF->LF translation if appropriate. return the * number taken from the buffer. This may not equal the number written. */ static int writefile(int f, char *b, int n) { int i; if (!translation) return(write(f,b,n)); i = 0; while (i < n) { if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') { b++;i++; } if (write(f, b, 1) != 1) break; b++; i++; } return(i); } /* * read from a file with LF->CR/LF translation if appropriate. return the * number read. read approx n bytes. */ static int readfile(char *b, int size, int n, FILE *f) { int i; int c; if (!translation || (size != 1)) return(fread(b,size,n,f)); i = 0; while (i < n) { if ((c = getc(f)) == EOF) break; if (c == '\n') { b[i++] = '\r'; n++; } b[i++] = c; } return(i); } /* * read from a file with print translation. return the number read. * read approx n bytes. */ static int printread(FILE *f,char *b,int n) { int i; i = readfile(b,1, n-1,f); #if FORMFEED if (feof(f) && i>0) b[i++] = '\014'; #endif return(i); } /* * check for existance of a dir */ static BOOL chkpath(char *path,BOOL report) { fstring path2; pstring inbuf,outbuf; char *p; strcpy(path2,path); trim_string(path2,NULL,"\\"); if (!*path2) *path2 = '\\'; bzero(outbuf,smb_size); set_message(outbuf,0,4 + strlen(path2),True); SCVAL(outbuf,smb_com,SMBchkpth); SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; strcpy(p,path2); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (report && CVAL(inbuf,smb_rcls) != 0) DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf))); return(CVAL(inbuf,smb_rcls) == 0); } /* * check the space on a device */ static void do_dskattr(void) { pstring inbuf,outbuf; bzero(outbuf,smb_size); set_message(outbuf,0,0,True); CVAL(outbuf,smb_com) = SMBdskattr; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf))); DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n", SVAL(inbuf,smb_vwv0), SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2), SVAL(inbuf,smb_vwv3))); } /* * show cd/pwd */ static void cmd_pwd(void) { DEBUG(0,("Current directory is %s",CNV_LANG(service))); DEBUG(0,("%s\n",CNV_LANG(cur_dir))); } /* * change directory */ static void cmd_cd(char *inbuf,char *outbuf) { fstring buf; char *p = buf; pstring saved_dir; if (next_token(NULL,buf,NULL)) { pstring dname; #ifdef SCANNER /* * just plug in exactly what I say, without locally checking it. Implies * that we must always supply an abspath, which for the mo' is fine */ cur_dir[0] = '\0'; strcpy (cur_dir, p); DEBUG (0,("chkpath says: %d\n", chkpath (cur_dir, False))); #else /* * Save the current directory in case the new directory is invalid */ strcpy(saved_dir, cur_dir); if (*p == '\\') strcpy(cur_dir,p); else strcat(cur_dir,p); if (*(cur_dir+strlen(cur_dir)-1) != '\\') { strcat(cur_dir, "\\"); } dos_clean_name(cur_dir); strcpy(dname,cur_dir); strcat(cur_dir,"\\"); dos_clean_name(cur_dir); if (!strequal(cur_dir,"\\")) if (!chkpath(dname,True)) strcpy(cur_dir,saved_dir); #endif /* SCANNER */ } else DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir))); strcpy(cd_path,cur_dir); } /* * display info about a file */ static void display_finfo(file_info *finfo) { time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */ DEBUG(0,(" %-30s%7.7s%10d %s", CNV_LANG(finfo->name), attrib_string(finfo->mode), finfo->size, asctime(LocalTime(&t,GMT_TO_LOCAL)))); } /* * do a directory listing, calling fn on each file found */ void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) { if (Protocol >= PROTOCOL_LANMAN2) { if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0) return; } expand_mask(Mask,False); do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir); return; } /* * decide if a file should be operated on */ static BOOL do_this_one(file_info *finfo) { if (finfo->mode & aDIR) return(True); if (newer_than && finfo->mtime < newer_than) return(False); if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) return(False); return(True); } /* * interpret a short filename structure * The length of the structure is returned */ static int interpret_short_filename(char *p,file_info *finfo) { finfo->mode = CVAL(p,21); /* * this date is converted to GMT by make_unix_date */ finfo->ctime = make_unix_date(p+22); finfo->mtime = finfo->atime = finfo->ctime; finfo->size = IVAL(p,26); strcpy(finfo->name,p+30); return(DIR_STRUCT_SIZE); } /* * interpret a long filename structure - this is mostly guesses at the moment * The length of the structure is returned * The structure of a long filename depends on the info level. 260 is used * by NT and 2 is used by OS/2 */ static int interpret_long_filename(int level,char *p,file_info *finfo) { if (finfo) memcpy(finfo,&def_finfo,sizeof(*finfo)); switch (level) { case 1: /* OS/2 understands this */ if (finfo) { /* these dates are converted to GMT by make_unix_date */ finfo->ctime = make_unix_date2(p+4); finfo->atime = make_unix_date2(p+8); finfo->mtime = make_unix_date2(p+12); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); strcpy(finfo->name,p+27); } return(28 + CVAL(p,26)); case 2: /* this is what OS/2 uses mostly */ if (finfo) { /* these dates are converted to GMT by make_unix_date */ finfo->ctime = make_unix_date2(p+4); finfo->atime = make_unix_date2(p+8); finfo->mtime = make_unix_date2(p+12); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); strcpy(finfo->name,p+31); } return(32 + CVAL(p,30)); /* levels 3 and 4 are untested */ case 3: if (finfo) { /* these dates are probably like the other ones */ finfo->ctime = make_unix_date2(p+8); finfo->atime = make_unix_date2(p+12); finfo->mtime = make_unix_date2(p+16); finfo->size = IVAL(p,20); finfo->mode = CVAL(p,28); strcpy(finfo->name,p+33); } return(SVAL(p,4)+4); case 4: if (finfo) { /* these dates are probably like the other ones */ finfo->ctime = make_unix_date2(p+8); finfo->atime = make_unix_date2(p+12); finfo->mtime = make_unix_date2(p+16); finfo->size = IVAL(p,20); finfo->mode = CVAL(p,28); strcpy(finfo->name,p+37); } return(SVAL(p,4)+4); case 260: /* NT uses this, but also accepts 2 */ if (finfo) { int ret = SVAL(p,0); int namelen; p += 4; /* next entry offset */ p += 4; /* fileindex */ /* these dates appear to arrive in a weird way. It seems to be localtime plus the serverzone given in the initial connect. This is GMT when DST is not in effect and one hour from GMT otherwise. Can this really be right?? I suppose this could be called kludge-GMT. Is is the GMT you get by using the current DST setting on a different localtime. It will be cheap to calculate, I suppose, as no DST tables will be needed */ finfo->ctime = interpret_long_date(p); p += 8; finfo->atime = interpret_long_date(p); p += 8; finfo->mtime = interpret_long_date(p); p += 8; p += 8; finfo->size = IVAL(p,0); p += 8; p += 8; /* alloc size */ finfo->mode = CVAL(p,0); p += 4; namelen = IVAL(p,0); p += 4; p += 4; /* EA size */ p += 2; /* short name len? */ p += 24; /* short name? */ StrnCpy(finfo->name,p,namelen); return(ret); } return(SVAL(p,0)); } DEBUG(1,("Unknown long filename format %d\n",level)); return(SVAL(p,0)); } /* * act on the files in a dir listing */ static void dir_action(char *inbuf,char *outbuf,int attribute, file_info *finfo,BOOL recurse_dir, void (*fn)(),BOOL longdir) { if (!((finfo->mode & aDIR) == 0 && *fileselection && !mask_match(finfo->name,fileselection,False,False)) && !(recurse_dir && (strequal(finfo->name,".") || strequal(finfo->name,"..")))) { if (recurse_dir && (finfo->mode & aDIR)) { pstring mask2; pstring sav_dir; strcpy(sav_dir,cur_dir); strcat(cur_dir,finfo->name); strcat(cur_dir,"\\"); strcpy(mask2,cur_dir); if (!fn) DEBUG(0,("\n%s\n",CNV_LANG(cur_dir))); if (longdir) { strcat(mask2,"*"); do_long_dir(inbuf,outbuf,mask2,attribute,fn,True); } else { strcat(mask2,"*.*"); do_dir(inbuf,outbuf,mask2,attribute,fn,True); } strcpy(cur_dir,sav_dir); } else { if (fn && do_this_one(finfo)) fn(finfo); } } } /* * do a directory listing, calling fn on each file found */ static int do_short_dir(char *inbuf,char *outbuf, char *Mask,int attribute, void (*fn)(),BOOL recurse_dir) { char *p; int received = 0; BOOL first = True; char status[21]; int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE; int num_received = 0; int i; char *dirlist = NULL; pstring mask; file_info finfo; finfo = def_finfo; bzero(status,21); strcpy(mask,Mask); while (1) { bzero(outbuf,smb_size); if (first) set_message(outbuf,2,5 + strlen(mask),True); else set_message(outbuf,2,5 + 21,True); #if FFIRST if (Protocol >= PROTOCOL_LANMAN1) CVAL(outbuf,smb_com) = SMBffirst; else #endif CVAL(outbuf,smb_com) = SMBsearch; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,num_asked); SSVAL(outbuf,smb_vwv1,attribute); p = smb_buf(outbuf); *p++ = 4; if (first) strcpy(p,mask); else strcpy(p,""); p += strlen(p) + 1; *p++ = 5; if (first) SSVAL(p,0,0); else { SSVAL(p,0,21); p += 2; memcpy(p,status,21); } send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); received = SVAL(inbuf,smb_vwv0); DEBUG(5,("dir received %d\n",received)); DEBUG(6,("errstr=%s\n",smb_errstr(inbuf))); if (received <= 0) break; first = False; dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE); if (!dirlist) return 0; p = smb_buf(inbuf) + 3; memcpy(dirlist+num_received*DIR_STRUCT_SIZE, p,received*DIR_STRUCT_SIZE); memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21); num_received += received; if (CVAL(inbuf,smb_rcls) != 0) break; } #if FFIRST if (!first && Protocol >= PROTOCOL_LANMAN1) { bzero(outbuf,smb_size); CVAL(outbuf,smb_com) = SMBfclose; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; strcpy(p,""); p += strlen(p) + 1; *p++ = 5; SSVAL(p,0,21); p += 2; memcpy(p,status,21); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT,False); if (CVAL(inbuf,smb_rcls) != 0) DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf))); } #endif if (!fn) for (p=dirlist,i=0;i 200) { DEBUG(0,("ERROR: Looping in FIND_NEXT??\n")); break; } if (First) { setup = TRANSACT2_FINDFIRST; SSVAL(param,0,attribute); /* attribute */ SSVAL(param,2,max_matches); /* max count */ SSVAL(param,4,8+4+2); /* resume required + close on end + continue */ SSVAL(param,6,info_level); SIVAL(param,8,0); strcpy(param+12,mask); } else { setup = TRANSACT2_FINDNEXT; SSVAL(param,0,ff_dir_handle); SSVAL(param,2,max_matches); /* max count */ SSVAL(param,4,info_level); SIVAL(param,6,ff_resume_key); /* ff_resume_key */ SSVAL(param,10,8+4+2); /* resume required + close on end + continue */ strcpy(param+12,mask); DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", ff_dir_handle,ff_resume_key,ff_lastname,mask)); } /* ??? original code added 1 pad byte after param */ send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, NULL,param,&setup, 0,12+strlen(mask)+1,1, BUFFER_SIZE,10,0); if (!receive_trans_response(inbuf,SMBtrans2, &resp_data_len,&resp_param_len, &resp_data,&resp_param)) { DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf))); break; } /* parse out some important return info */ p = resp_param; if (First) { ff_dir_handle = SVAL(p,0); ff_searchcount = SVAL(p,2); ff_eos = SVAL(p,4); ff_lastname = SVAL(p,8); } else { ff_searchcount = SVAL(p,0); ff_eos = SVAL(p,2); ff_lastname = SVAL(p,6); } if (ff_searchcount == 0) break; /* point to the data bytes */ p = resp_data; /* we might need the lastname for continuations */ if (ff_lastname > 0) { switch(info_level) { case 260: ff_resume_key =0; StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname); /* strcpy(mask,p+ff_lastname+94); */ break; case 1: strcpy(mask,p + ff_lastname + 1); ff_resume_key = 0; break; } } else strcpy(mask,""); /* and add them to the dirlist pool */ dirlist = Realloc(dirlist,dirlist_len + resp_data_len); if (!dirlist) { DEBUG(0,("Failed to expand dirlist\n")); break; } /* put in a length for the last entry, to ensure we can chain entries into the next packet */ { char *p2; for (p2=p,i=0;i<(ff_searchcount-1);i++) p2 += interpret_long_filename(info_level,p2,NULL); SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p)); } /* grab the data for later use */ memcpy(dirlist+dirlist_len,p,resp_data_len); dirlist_len += resp_data_len; total_received += ff_searchcount; if (resp_data) free(resp_data); resp_data = NULL; if (resp_param) free(resp_param); resp_param = NULL; DEBUG(3,("received %d entries (eos=%d resume=%d)\n", ff_searchcount,ff_eos,ff_resume_key)); First = False; } if (!fn) for (p=dirlist,i=0;i 0) { DEBUG(3,("Chaining readX wth openX\n")); SSVAL(outbuf,smb_vwv0,SMBreadX); SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf)); bzero(p,200); p -= smb_wct; SSVAL(p,smb_wct,10); SSVAL(p,smb_vwv0,0xFF); SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size)); SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size)); smb_setlen(outbuf,smb_len(outbuf)+11*2+1); } #endif if(!strcmp(lname,"-")) handle = fileno(stdout); else { handle = creat(lname,0644); newhandle = True; } if (handle < 0) { DEBUG(0,("Error opening local file %s\n",lname)); free(inbuf);free(outbuf); return; } send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) { if (CVAL(inbuf,smb_rcls) == ERRSRV && SVAL(inbuf,smb_err) == ERRnoresource && reopen_connection(inbuf,outbuf)) { do_get(rname,lname,finfo1); return; } DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname))); if(newhandle) close(handle); free(inbuf);free(outbuf); return; } strcpy(finfo.name,rname); if (!finfo1) { finfo.mode = SVAL(inbuf,smb_vwv3); /* these times arrive as LOCAL time, using the DST offset corresponding to that time, we convert them to GMT */ finfo.mtime = make_unix_date3(inbuf+smb_vwv4); finfo.atime = finfo.ctime = finfo.mtime; finfo.size = IVAL(inbuf,smb_vwv6); } DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode)); fnum = SVAL(inbuf,smb_vwv2); /* we might have got some data from a chained readX */ if (SVAL(inbuf,smb_vwv0) == SMBreadX) { p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct; datalen = SVAL(p,smb_vwv5); dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6); } else { dataptr = NULL; datalen = 0; } DEBUG(2,("getting file %s of size %d bytes as %s ", CNV_LANG(finfo.name), finfo.size, lname)); while (nread < finfo.size && !close_done) { int method = -1; static BOOL can_chain_close = True; p=NULL; DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size)); /* 3 possible read types. readbraw if a large block is required. readX + close if not much left and read if neither is supported */ /* we might have already read some data from a chained readX */ if (dataptr && datalen>0) method=3; /* if we can finish now then readX+close */ if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) && ((finfo.size - nread) < (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300)))) method = 0; /* if we support readraw then use that */ if (method<0 && readbraw_supported) method = 1; /* if we can then use readX */ if (method<0 && (Protocol >= PROTOCOL_LANMAN1)) method = 2; switch (method) { /* use readX */ case 0: case 2: if (method == 0) close_done = True; /* use readX + close */ bzero(outbuf,smb_size); set_message(outbuf,10,0,True); CVAL(outbuf,smb_com) = SMBreadX; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); if (close_done) { CVAL(outbuf,smb_vwv0) = SMBclose; SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf)); } else CVAL(outbuf,smb_vwv0) = 0xFF; SSVAL(outbuf,smb_vwv2,fnum); SIVAL(outbuf,smb_vwv3,nread); SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread)); SSVAL(outbuf,smb_vwv6,0); SIVAL(outbuf,smb_vwv7,0); SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread)); if (close_done) { p = smb_buf(outbuf); bzero(p,9); CVAL(p,0) = 3; SSVAL(p,1,fnum); SIVALS(p,3,-1); /* now set the total packet length */ smb_setlen(outbuf,smb_len(outbuf)+9); } send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) { DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf))); break; } if (close_done && SVAL(inbuf,smb_vwv0) != SMBclose) { /* NOTE: WfWg sometimes just ignores the chained command! This seems to break the spec? */ DEBUG(3,("Rejected chained close?\n")); close_done = False; can_chain_close = False; ignore_close_error = True; } datalen = SVAL(inbuf,smb_vwv5); dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6); break; /* use readbraw */ case 1: { static int readbraw_size = BUFFER_SIZE; extern int Client; bzero(outbuf,smb_size); set_message(outbuf,8,0,True); CVAL(outbuf,smb_com) = SMBreadbraw; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); SIVAL(outbuf,smb_vwv1,nread); SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size)); SSVAL(outbuf,smb_vwv4,0); SIVALS(outbuf,smb_vwv5,-1); send_smb(Client,outbuf); /* Now read the raw data into the buffer and write it */ if(read_smb_length(Client,inbuf,0) == -1) { DEBUG(0,("Failed to read length in readbraw\n")); exit(1); } /* Even though this is not an smb message, smb_len returns the generic length of an smb message */ datalen = smb_len(inbuf); if (datalen == 0) { /* we got a readbraw error */ DEBUG(4,("readbraw error - reducing size\n")); readbraw_size = (readbraw_size * 9) / 10; if (readbraw_size < max_xmit) { DEBUG(0,("disabling readbraw\n")); readbraw_supported = False; } dataptr=NULL; continue; } if(read_data(Client,inbuf,datalen) != datalen) { DEBUG(0,("Failed to read data in readbraw\n")); exit(1); } dataptr = inbuf; } break; case 3: /* we've already read some data with a chained readX */ break; default: /* use plain read */ bzero(outbuf,smb_size); set_message(outbuf,5,0,True); CVAL(outbuf,smb_com) = SMBread; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread)); SIVAL(outbuf,smb_vwv2,nread); SSVAL(outbuf,smb_vwv4,finfo.size - nread); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) { DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf))); break; } datalen = SVAL(inbuf,smb_vwv0); dataptr = smb_buf(inbuf) + 3; break; } if (writefile(handle,dataptr,datalen) != datalen) { DEBUG(0,("Error writing local file\n")); break; } nread += datalen; if (datalen == 0) { DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread)); break; } dataptr=NULL; datalen=0; } if (!close_done) { bzero(outbuf,smb_size); set_message(outbuf,3,0,True); CVAL(outbuf,smb_com) = SMBclose; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,fnum); SIVALS(outbuf,smb_vwv1,-1); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0) { DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf))); if(newhandle) close(handle); free(inbuf);free(outbuf); return; } } if(newhandle) close(handle); if (archive_level >= 2 && (finfo.mode & aARCH)) { bzero(outbuf,smb_size); set_message(outbuf,8,strlen(rname)+4,True); CVAL(outbuf,smb_com) = SMBsetatr; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH)); SIVALS(outbuf,smb_vwv1,0); p = smb_buf(outbuf); *p++ = 4; strcpy(p,rname); p += strlen(p)+1; *p++ = 4; *p = 0; send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); } { struct timeval tp_end; int this_time; GetTimeOfDay(&tp_end); this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_usec - tp_start.tv_usec)/1000; get_total_time_ms += this_time; get_total_size += finfo.size; DEBUG(2,("(%g kb/s) (average %g kb/s)\n", finfo.size / (1.024*this_time + 1.0e-4), get_total_size / (1.024*get_total_time_ms))); } free(inbuf);free(outbuf); } /* * get a file */ static void cmd_get(void) { pstring lname; pstring rname; char *p; strcpy(rname,cur_dir); strcat(rname,"\\"); p = rname + strlen(rname); if (!next_token(NULL,p,NULL)) { DEBUG(0,("get \n")); return; } strcpy(lname,p); #ifndef SCANNER dos_clean_name(rname); #endif next_token(NULL,lname,NULL); do_get(rname,lname,NULL); } /* * make a directory of name "name" */ static BOOL do_mkdir(char *name) { char *p; char *inbuf,*outbuf; inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); if (!inbuf || !outbuf) { DEBUG(0,("out of memory\n")); return False; } bzero(outbuf,smb_size); set_message(outbuf,0,2 + strlen(name),True); CVAL(outbuf,smb_com) = SMBmkdir; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; strcpy(p,name); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) { DEBUG(0,("%s making remote directory %s\n", smb_errstr(inbuf), CNV_LANG(name))); free(inbuf);free(outbuf); return(False); } free(inbuf);free(outbuf); return(True); } /* * make a directory */ static void cmd_mkdir(char *inbuf,char *outbuf) { pstring mask; fstring buf; char *p=buf; strcpy(mask,cur_dir); strcat(mask,"\\"); /* prepend with \\ */ if (!next_token(NULL,p,NULL)) { if (!recurse) DEBUG(0,("mkdir \n")); return; } strcat(mask,p); if (recurse) { pstring ddir; pstring ddir2; *ddir2 = 0; strcpy(ddir,mask); trim_string(ddir,".",NULL); p = strtok(ddir,"/\\"); while (p) { strcat(ddir2,p); if (!chkpath(ddir2,False)) { do_mkdir(ddir2); } strcat(ddir2,"\\"); p = strtok(NULL,"/\\"); } } else do_mkdir(mask); } /* * remove a directory of name "name". Added cuz cmd_rmdir otherwise does * the SMB stuff directly, and we want a callable thing. */ static BOOL do_rmdir(char *name) { char *p; char *inbuf,*outbuf; inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); if (!inbuf || !outbuf) { DEBUG(0,("out of memory\n")); return False; } bzero(outbuf,smb_size); set_message(outbuf,0,2 + strlen(name),True); CVAL(outbuf,smb_com) = SMBrmdir; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; strcpy(p,name); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) { DEBUG(0,("%s removing remote directory %s\n", smb_errstr(inbuf),CNV_LANG(name))); free(inbuf);free(outbuf); return(False); } free(inbuf);free(outbuf); return(True); } /* do_rmdir */ /* * delete some files */ static void do_del(file_info *finfo) { char *p; char *inbuf,*outbuf; pstring mask; strcpy(mask,cur_dir); strcat(mask,finfo->name); if (finfo->mode & aDIR) return; inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); if (!inbuf || !outbuf) { DEBUG(0,("out of memory\n")); return; } bzero(outbuf,smb_size); set_message(outbuf,1,2 + strlen(mask),True); CVAL(outbuf,smb_com) = SMBunlink; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,0); p = smb_buf(outbuf); *p++ = 4; strcpy(p,mask); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask))); free(inbuf);free(outbuf); } /* * delete some files */ static void cmd_del(char *inbuf,char *outbuf ) { pstring mask; fstring buf; int attribute = aSYSTEM | aHIDDEN; if (recurse) attribute |= aDIR; strcpy(mask,cur_dir); strcat(mask,"\\"); /* prepend \\ */ if (!next_token(NULL,buf,NULL)) { DEBUG(0,("del \n")); return; } strcat(mask,buf); do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False); } /* * remove a directory */ static void cmd_rmdir(char *inbuf,char *outbuf ) { pstring mask; fstring buf; char *p; strcpy(mask,cur_dir); strcat(mask,"\\"); /* prepend with \\ */ if (!next_token(NULL,buf,NULL)) { DEBUG(0,("rmdir \n")); return; } strcat(mask,buf); bzero(outbuf,smb_size); set_message(outbuf,0,2 + strlen(mask),True); CVAL(outbuf,smb_com) = SMBrmdir; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); p = smb_buf(outbuf); *p++ = 4; strcpy(p,mask); send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) { DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask))); return; } } /* * send a session request */ static BOOL send_session_request(char *inbuf,char *outbuf) { fstring dest; char *p; int len = 4; /* send a session request (RFC 8002) */ strcpy(dest,desthost); p = strchr(dest,'.'); if (p) *p = 0; /* put in the destination name */ p = outbuf+len; name_mangle(dest,p,name_type); len += name_len(p); /* and my name */ p = outbuf+len; name_mangle(myname,p,0); len += name_len(p); /* setup the packet length */ _smb_setlen(outbuf,len); CVAL(outbuf,0) = 0x81; send_smb(Client,outbuf); DEBUG(5,("Sent session request\n")); receive_smb(Client,inbuf,CLIENT_TIMEOUT); if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */ { /* For information, here is the response structure. * We do the byte-twiddling to for portability. struct RetargetResponse{ unsigned char type; unsigned char flags; int16 length; int32 ip_addr; int16 port; }; */ extern int Client; int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9); /* SESSION RETARGET */ putip((char *)&dest_ip,inbuf+4); close_sockets(); #ifdef SCANNER DEBUG(3,("Retargeted to [%s] %d\n", inet_ntoa (dest_ip), port)); #endif Client = open_socket_out(SOCK_STREAM, &dest_ip, port); if (Client == -1) return False; DEBUG(3,("Retargeted\n")); set_socket_options(Client,user_socket_options); /* Try again */ return send_session_request(inbuf,outbuf); } /* C. Hoch 9/14/95 End */ if (CVAL(inbuf,0) != 0x82) { int ecode = CVAL(inbuf,4); DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n", CVAL(inbuf,0),ecode,myname,desthost)); /* * XXX: do something slightly more intelligent here, like only "reasons" */ #ifndef SCANNER switch (ecode) { case 0x80: DEBUG(0,("Not listening on called name\n")); DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); DEBUG(0,("You may find the -I option useful for this\n")); break; case 0x81: DEBUG(0,("Not listening for calling name\n")); DEBUG(0,("Try to connect as another name (instead of %s)\n",myname)); DEBUG(0,("You may find the -n option useful for this\n")); break; case 0x82: DEBUG(0,("Called name not present\n")); DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); DEBUG(0,("You may find the -I option useful for this\n")); break; case 0x83: DEBUG(0,("Called name present, but insufficient resources\n")); DEBUG(0,("Perhaps you should try again later?\n")); break; default: DEBUG(0,("Unspecified error 0x%X\n",ecode)); DEBUG(0,("Your server software is being unfriendly\n")); break; } #endif /* SCANNER */ return(False); } return(True); } #ifdef STEPPING /* * Turn various server errors into a single interpretable status. * The error returns from various platforms are many and varied, but all of * them mean a couple of basic things. This boils relevant ones down roughly * to common server-class status, i.e.: * 0 success * 2 access denied, or wrong username/passwd for session OR share * 5 network-ID not found, for session * 6 sharename not found, TCon problem * 1 anything else, probably fatal, including disabled accounts, * negotiation problems, etc */ static int interpret_serr (rcls, err) unsigned char rcls; uint16 err; { register int reserr = 0; if ((rcls == 0) && (err == 0)) return (0); /* no error */ if (rcls == ERRSRV) { if (err == 1) return (1); if (err == 2) return (2); if (err == 4) return (1); if (err == 5) return (5); if (err == 6) return (6); if (err == 7) return (6); } /* ERRSRV */ if (rcls == ERRDOS) { if (err == 5) return (2); if (err == 65) return (1); if (err == 67) return (6); if (err == 71) return (1); if (err == 86) return (2); if (err == 87) return (1); if (err == 90) return (1); if (err == 2239) return (1); if (err == 2240) return (1); if (err == 2241) return (1); if (err == 2242) return (1); if (err == 2247) return (1); } /* ERRDOS */ return (1); /* didn't find any mapping */ } /* interpret_serr */ /* * Do an nmb status query; collect all the names. */ static BOOL send_status(char *lookup) { register int x; int udpfd; if ((udpfd = open_socket_in(SOCK_DGRAM, 137, 3)) < 0) return (0); DEBUG(3, ("UDP Socket opened.\n")); x = H_name_status(udpfd, lookup, name_type, dest_ip); /* * our modded version of which needs to: * use unicast * probably use name "*", zero-filled, nametype 0, --> CKAAAAAAAAA.... * fill in try_names with hostnames, workgroups, ??? * fill in try_users with 0x3 nametype stuff et al * fill in try_pass with selected items from both... */ (void) close (udpfd); if (x == 0) return (0); /* didn't get anything, oh well */ return (1); } /* send_status */ /* Moved these vars outside send_login, so all routines here have access: */ static int sesskey=0; /* from send_login */ static time_t servertime = 0; /* from send_login */ static int sec_mode=0; /* from send_login */ static int crypt_len; /* from send_login */ static int max_vcs=0; /* from send_login */ static BOOL send_prots(char *inbuf,char *outbuf) { BOOL was_null = (!inbuf && !outbuf); extern int serverzone; struct { int prot; char *name; } prots[] = { {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"}, {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, {PROTOCOL_LANMAN1,"LANMAN1.0"}, {PROTOCOL_LANMAN2,"LM1.2X002"}, {PROTOCOL_LANMAN2,"Samba"}, {PROTOCOL_NT1,"NT LM 0.12"}, {PROTOCOL_NT1,"NT LANMAN 1.0"}, {-1,NULL} }; register char *p; int numprots; if (was_null) return (0); bzero(outbuf,smb_size); /* setup the protocol strings */ { int plength; for (plength=0,numprots=0; prots[numprots].name && prots[numprots].prot<=max_protocol; numprots++) plength += strlen(prots[numprots].name)+2; set_message(outbuf,0,plength,True); p = smb_buf(outbuf); for (numprots=0; prots[numprots].name && prots[numprots].prot<=max_protocol; numprots++) { *p++ = 2; strcpy(p,prots[numprots].name); p += strlen(p) + 1; } } CVAL(outbuf,smb_com) = SMBnegprot; setup_pkt(outbuf); CVAL(smb_buf(outbuf),0) = 2; send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); show_msg(inbuf); if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots)) { DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n", myname,desthost,smb_errstr(inbuf))); return(False); } Protocol = prots[SVAL(inbuf,smb_vwv0)].prot; /* * SCANNER: if sent limited set but still get back secmode=doencrypt, need to * correct for it somehow. Easy answer: turn off doencrypt externally! */ if (Protocol < PROTOCOL_NT1) { sec_mode = SVAL(inbuf,smb_vwv1); max_xmit = SVAL(inbuf,smb_vwv2); sesskey = IVAL(inbuf,smb_vwv6); serverzone = SVALS(inbuf,smb_vwv10)*60; /* this time is converted to GMT by make_unix_date */ servertime = make_unix_date(inbuf+smb_vwv8); if (Protocol >= PROTOCOL_COREPLUS) { readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0); writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0); } crypt_len = smb_buflen(inbuf); memcpy(cryptkey,smb_buf(inbuf),8); DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3))); max_vcs = SVAL(inbuf,smb_vwv4); DEBUG(3,("max vcs %d\n",max_vcs)); DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5))); } else { /* NT protocol */ sec_mode = CVAL(inbuf,smb_vwv1); max_xmit = IVAL(inbuf,smb_vwv3+1); sesskey = IVAL(inbuf,smb_vwv7+1); serverzone = SVALS(inbuf,smb_vwv15+1)*60; /* this time arrives in real GMT */ servertime = interpret_long_date(inbuf+smb_vwv11+1); crypt_len = CVAL(inbuf,smb_vwv16+1); memcpy(cryptkey,smb_buf(inbuf),8); if (IVAL(inbuf,smb_vwv9+1) & 1) readbraw_supported = writebraw_supported = True; DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1))); max_vcs = SVAL(inbuf,smb_vwv2+1); DEBUG(3,("max vcs %d\n",max_vcs)); DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1))); DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1))); } DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1))); #ifdef SCANNER DEBUG(3,("Real Sec mode %d\n",sec_mode)); #endif DEBUG(3,("max xmt %d\n",max_xmit)); DEBUG(3,("Got %d byte crypt key\n",crypt_len)); #define PRINTK 1 /* XXX */ #ifdef PRINTK { register int i; for (i = 0; i < crypt_len; i++) { DEBUG (5,("%02X ", (unsigned char) cryptkey[i])); DEBUG (5,("\n")) ; fflush (stdout); } } /* PRINTK ctx */ #endif /* PRINTK */ DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name)); #ifdef VERBOSE if (!said_protocol) natprintf("[*]--- Attempting to connect with protocol: %s\n", prots[SVAL(inbuf,smb_vwv0)].name); #endif if (xflag) doencrypt = ((sec_mode & 2) != 0); if (servertime) { static BOOL done_time = False; if (!done_time) { #ifdef VERBOSE if (!said_protocol) { natprintf("[*]--- Server time is %s[*]--- Timezone is UTC%+02.1f\n", asctime(LocalTime(&servertime,GMT_TO_LOCAL)), -(double)(serverzone/3600.0)); said_protocol++; } #endif DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n", asctime(LocalTime(&servertime,GMT_TO_LOCAL)), -(double)(serverzone/3600.0))); done_time = True; } } return (True); } /* send_prots */ /* * send session setupX. split from send_login */ /* * This only does a one-off shot, using global "username" and "password" */ static BOOL send_setup (char *inbuf,char *outbuf) { char *pass = password; register char * p; register int x; bzero(outbuf,smb_size); if (Protocol >= PROTOCOL_LANMAN1) /* punted use_setup */ { fstring pword; int passlen = strlen(pass)+1; strcpy(pword,pass); #ifdef SMB_PASSWD /* check for user-level security: skip encrypting if we're not gonna use it */ if (doencrypt && *pass && (sec_mode & 1)) { DEBUG(3,("Using encrypted session passwords\n")); passlen = 24; SMBencrypt(pass,cryptkey,pword); } #else doencrypt = False; #endif /* if in share level security then don't send a password now */ if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} /* send a session setup command */ bzero(outbuf,smb_size); if (Protocol < PROTOCOL_NT1) { set_message(outbuf,10,1 + strlen(username) + passlen,True); CVAL(outbuf,smb_com) = SMBsesssetupX; setup_pkt(outbuf); CVAL(outbuf,smb_vwv0) = 0xFF; SSVAL(outbuf,smb_vwv2,max_xmit); SSVAL(outbuf,smb_vwv3,2); SSVAL(outbuf,smb_vwv4,max_vcs-1); SIVAL(outbuf,smb_vwv5,sesskey); SSVAL(outbuf,smb_vwv7,passlen); p = smb_buf(outbuf); memcpy(p,pword,passlen); p += passlen; strcpy(p,username); } else { /* xxx: dont for now; send regular len: if (!doencrypt) passlen--; /* WHY??!?!? */ /* for Win95 */ set_message(outbuf,13,0,True); CVAL(outbuf,smb_com) = SMBsesssetupX; setup_pkt(outbuf); CVAL(outbuf,smb_vwv0) = 0xFF; SSVAL(outbuf,smb_vwv2,BUFFER_SIZE); SSVAL(outbuf,smb_vwv3,2); /* SCANNER: xxx: */ SSVAL(outbuf,smb_vwv4,getpid()); SIVAL(outbuf,smb_vwv5,sesskey); SSVAL(outbuf,smb_vwv7,passlen); SSVAL(outbuf,smb_vwv8,0); p = smb_buf(outbuf); memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7); /* * SCANNER: oops -- *set* vwv8, it's taken as NT-passwd-len on server end!! * Used by samba / reply.c / reply_sesssetupX to cmp against NT-MD4 * Documented in CIFS, too -- "case sensitive passwd length" */ /* * a more recent discovery: it *DOES* have to be unicode; make it so. * One sleaze, a-comin' up ... * XXX SCANNER STEPPING and a host of other chinese words: * we now know what to do here. Don't mung vwv7 len, it's okay. Either make * vwv8 be 0 so vwv7 is used [aka passlen-- before inserting it] , or make * vwv8 the real unicode len and bust a plaintext password apart into * unicode here. Is there a handy unicoder routine??? there should be.. * for now, let's just leave vwv8 zeroed unless we're encrypting; lanman * plaintext passwd will take care of it *and* reduce the keyspace. */ #define USE_V8 1 /* XXX -- clean this up.. */ #if USE_V8 if (!doencrypt) passlen = 0; SSVAL(outbuf,smb_vwv8,passlen); /* always 24? [?] */ /* * also have to put appropriate response in corresponding field, even if it's * the same 24 crypted-bytes. XXX: out-n-out *wrong* for the first shot * since it was encrypted LM-style! */ memcpy (p, pword, passlen); p += SVAL (outbuf, smb_vwv8); /* * memset (p, 0, 24); p += SVAL (outbuf, smb_vwv8); */ #endif /* USE_V8 */ /* * XXX: this following cruft is all s'posed to be UNICODE! but probably * depends on flags2/0x8000 ... */ strcpy(p,username);p = skip_string(p,1); strcpy(p,workgroup);p = skip_string(p,1); /* SCANNER: xxx: */ strcpy(p,"Unix");p = skip_string(p,1); strcpy(p,"Samba");p = skip_string(p,1); set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False); } /* PROTOCOL_NT1 */ send_smb(Client,outbuf); x = receive_smb(Client,inbuf,CLIENT_TIMEOUT); /* * XXX: need some other indicator that the net's hung, so step() bails */ if (x == 0) { /* fukt connection? */ DEBUG(0,("setupX reply failed\n")); return (False); } show_msg(inbuf); #ifdef SCANNER #ifdef SMB_PASSWD /* * maybe try the NT-mode passwd. This is a total hack; shd be done better */ /* * XXX: I'm not even sure if vwv8 *is* the right param to send it in, although * testing does seem to prove that out. Furthermore, even NULL passwords * have to be sent as hashed/encrypted P24 blocks. Feh. */ if ((CVAL(inbuf,smb_rcls) != 0) && (Protocol >= PROTOCOL_NT1) && doencrypt) { SMBNTencrypt(pass,cryptkey,pword); p = smb_buf (outbuf); /* hopefully we can just diddle */ memcpy (p, pword, passlen); /* the crypto-response in-place, */ #if USE_V8 p += passlen; memcpy (p, pword, passlen); /* *TWICE* ... sheesh */ #endif send_smb (Client, outbuf); /* and resend the changed packet */ x = receive_smb (Client, inbuf, CLIENT_TIMEOUT); if (x == 0) return (False); show_msg (inbuf); } /* if err & NT-mode & doencrypt */ /* and fall out to regular error handling with new response */ #endif /* SMB_PASSWD */ #endif /* SCANNER */ if (CVAL(inbuf,smb_rcls) != 0) { DEBUG(2,("%s/%s: session: %s\n", username, pass, smb_errstr(inbuf))); cur_serr = interpret_serr (CVAL (inbuf, smb_rcls), SVAL (inbuf, smb_err)); return(False); } /* rcls != 0 */ /* we're in, we think */ if ((SVAL (inbuf, smb_vwv2)) & 1) /* mentioned in CIFS, but */ DEBUG (0,("GUEST-mode ")); /* never seems to happen */ DEBUG(0,("session established as %s/%s\n", username, pass)); #if 0 /* done externally */ if (read_pass && (sec_mode & 1)) exit (0); #endif #endif /* SCANNER */ /* SCANNER: this stuff is in the response regardless of protocol level! */ #ifdef SCANNER { /* we're already "if >= LANMAN1" */ #else if (Protocol >= PROTOCOL_NT1) { #endif /* SCANNER */ char *domain,*os,*lanman; p = smb_buf(inbuf); os = p; lanman = skip_string(os,1); domain = skip_string(lanman,1); if (*domain || *os || *lanman) { DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman)); #ifdef SCANNER /* what the hell, collect some of this info too */ cur_vuln = 182; fill_vuln ("Domain: ", domain); fill_vuln ("OS: ", os); #endif } /* if dom/os/srv */ } /* use the returned uid from now on */ /* SCANNER: unless we reset it later... */ if (SVAL(inbuf,smb_uid) != uid) DEBUG(3,("Server gave us a UID of %d. We gave %d\n", SVAL(inbuf,smb_uid),uid)); uid = SVAL(inbuf,smb_uid); } /* >= LANMAN1 */ return (True); } /* send_setup */ static BOOL send_tcon (char *inbuf,char *outbuf) { char * pass = password; pstring dev; register char * p; register int x; int passlen = strlen(pass)+1; /* moved from inside "again2" ctx */ fstring pword; /* moved from inside "again2" ctx */ #if AJT if (strstr(service,"IPC$")) connect_as_ipc = True; #endif strcpy(dev,"A:"); if (connect_as_printer) strcpy(dev,"LPT1:"); if (connect_as_ipc) strcpy(dev,"IPC"); /* SCANNER: should split all this into separate functions for sessreq / dialect / sesssetupX / tcon, that all take uname/pw args. ... hmm, above looks like pre-lanman1 didn't use sesssetup??? */ /* now we've got a connection - send a tcon message */ bzero(outbuf,smb_size); if (strncmp(service,"\\\\",2) != 0) { DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n")); DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n")); } /* XXX: old again2: local-context silliness */ { strcpy(pword,pass); /* if in user level security then don't send a password now */ if ((sec_mode & 1)) { strcpy(pword, ""); passlen=1; } else /* only do encryption if we're gonna use it. */ /* XXX: does this work if encrypted-mode but NULL passwd??!?!? */ /* looks like it punts, or zero-fills the resp, if null passwd */ #ifdef SMB_PASSWD if (doencrypt && *pass) { passlen=24; SMBencrypt(pass,cryptkey,pword); } #endif ; /* possibly null else */ set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True); CVAL(outbuf,smb_com) = SMBtconX; setup_pkt(outbuf); SSVAL(outbuf,smb_vwv0,0xFF); SSVAL(outbuf,smb_vwv3,passlen); p = smb_buf(outbuf); memcpy(p,pword,passlen); p += passlen; strcpy(p,service); p = skip_string(p,1); strcpy(p,dev); } /* again2 ctx */ send_smb(Client,outbuf); x = receive_smb(Client,inbuf,CLIENT_TIMEOUT); /* XXX: need some other indicator that the net's hung, so step() bails */ if (x == 0) { /* fukt connection? */ DEBUG(0,("tcon reply failed\n")); return (False); } /* blank-passwd retry ripped; handled externally now */ #ifdef SCANNER #ifdef SMB_PASSWD /* maybe try the NT-mode passwd, exactly as done in send_setup */ /* XXX: this code currently trashes the buffer; need to fix like send_setup */ /* XXX: does NT use an alternate field for SHARE-level passwds?? */ if ((CVAL(inbuf,smb_rcls) != 0) && (Protocol >= PROTOCOL_NT1) && doencrypt) { SMBNTencrypt(pass,cryptkey,pword); p = smb_buf (outbuf); /* hopefully we can just diddle */ memcpy (p, pword, passlen); /* the crypto-response in-place, */ send_smb (Client, outbuf); /* and resend the changed packet */ x = receive_smb (Client, inbuf, CLIENT_TIMEOUT); if (x == 0) return (False); show_msg (inbuf); } /* if err & NT- mode & doencrypt */ /* and fall out to regular error handling with new response */ #endif /* SMB_PASSWD */ #endif /* SCANNER */ if (CVAL(inbuf,smb_rcls) != 0) { #ifndef SCANNER DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf))); DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n")); DEBUG(0,("Some servers insist that these be in uppercase\n")); return(False); } #else DEBUG(2,("%s/%s: %s: %s\n", username, pass, service, smb_errstr(inbuf))); cur_serr = interpret_serr (CVAL (inbuf, smb_rcls), SVAL (inbuf, smb_err)); /* this "can't happen" but does against misconfigured samba, fer example */ if ((cur_serr == 2) && (sec_mode & 1)) DEBUG (1,("Wanted TCon passwd in USER-mode sec?!??!\n")); return(False); } /* if smb_rcls err */ /* we're in */ DEBUG(0,("tcon %s connected as %s/%s\n", service, username, pass)); #if 0 /* done externally */ if (read_pass && !(sec_mode & 1)) exit (0); #endif #endif /* SCANNER */ max_xmit = MIN(max_xmit,BUFFER_SIZE-4); if (max_xmit <= 0) max_xmit = BUFFER_SIZE - 4; cnum = SVAL(inbuf,smb_tid); /* could this actually happen?? */ if (cnum == 0) { DEBUG (0,("OOPS! opened tcon, but Tree-ID is zero?!?!\n")); return (False); } DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit)); return True; } /* send_tcon */ /* * stepped version of send_login, for compat with the old one */ static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session, BOOL use_setup) { fstring dev; register BOOL x; BOOL was_null = (!inbuf && !outbuf); if (was_null) { inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); } x = 0; if (read_pass) DEBUG (0,("Reading passwords from stdin...\n")); /* * just wade through the nice other steps we've set up, but calling uppair * whenever it seems to want a password */ if (start_session && !send_session_request(inbuf,outbuf)) goto lame_bailout; if (!send_prots (inbuf, outbuf)) goto lame_bailout; sl_setx: cur_serr = 0; if (use_setup && !send_setup (inbuf, outbuf)) { if ((cur_serr == 2) && uppair()) goto sl_setx; goto lame_bailout; } sl_tcon: cur_serr = 0; if (!send_tcon (inbuf, outbuf)) { if ((cur_serr == 2) && uppair()) goto sl_tcon; goto lame_bailout; } x = 1; /* we're in */ lame_bailout: if (was_null) { free(inbuf); free(outbuf); } if (read_pass) exit (0); return x; } /* * send_logout minus the connection teardown -- just send SMBTdis. */ static void send_tdis (char * inbuf, char * outbuf) { bzero(outbuf,smb_size); set_message(outbuf,0,0,True); CVAL(outbuf,smb_com) = SMBtdis; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); if (cnum == 0) return; send_smb(Client,outbuf); receive_smb(Client,inbuf,SHORT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) { DEBUG(3,("SMBtdis failed %s\n",smb_errstr(inbuf))); } cnum = 0; } /* send_tdis */ /* * Send a logout command */ static void send_logout(void ) { pstring inbuf,outbuf; bzero(outbuf,smb_size); set_message(outbuf,0,0,True); CVAL(outbuf,smb_com) = SMBtdis; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); if (cnum == 0) return; send_smb(Client,outbuf); receive_smb(Client,inbuf,SHORT_TIMEOUT); if (CVAL(inbuf,smb_rcls) != 0) DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf))); #ifdef STATS stats_report(); #endif exit(0); } /* * Call a remote api */ static BOOL call_api(int prcnt,int drcnt, int mprcnt,int mdrcnt, int *rprcnt,int *rdrcnt, char *param,char *data, char **rparam,char **rdata) { static char *inbuf=NULL; static char *outbuf=NULL; if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0, data,param,NULL,drcnt,prcnt,0, mdrcnt,mprcnt,0); return (receive_trans_response(inbuf,SMBtrans,rdrcnt,rprcnt,rdata,rparam)); } /* * Send a SMB trans or trans2 request */ static BOOL send_trans_request(char *outbuf,int trans, char *name,int fid,int flags, char *data,char *param,uint16 *setup, int ldata,int lparam,int lsetup, int mdata,int mparam,int msetup) { int i; int this_ldata,this_lparam; int tot_data=0,tot_param=0; char *outdata,*outparam; pstring inbuf; char *p; this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */ this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam)); bzero(outbuf,smb_size); set_message(outbuf,14+lsetup,0,True); CVAL(outbuf,smb_com) = trans; SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3); outdata = outparam+this_lparam; /* primary request */ SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */ SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */ SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */ SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */ SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */ SSVAL(outbuf,smb_flags,flags); /* flags */ SIVAL(outbuf,smb_timeout,0); /* timeout */ SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */ SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */ SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */ SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */ SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */ for (i=0;i 0) { natprintf("\n\tSharename Type Comment\n"); natprintf("\t--------- ---- -------\n"); } if (sort) qsort(p,count,20,QSORT_CAST strcasecmp); for (i=0;i8) long_share_name=True; p += 20; } } } if (rparam) free(rparam); if (rdata) free(rdata); return(count>0); } /* * get some server info */ static void server_info() { char *rparam = NULL; char *rdata = NULL; char *p; int rdrcnt,rprcnt; pstring param; bzero(param,sizeof(param)); p = param; SSVAL(p,0,63); /* api number */ p += 2; strcpy(p,"WrLh"); p = skip_string(p,1); strcpy(p,"zzzBBzz"); p = skip_string(p,1); SSVAL(p,0,10); /* level 10 */ SSVAL(p,2,1000); p += 6; if (call_api(PTR_DIFF(p,param),0, 6,1000, &rprcnt,&rdrcnt, param,NULL, &rparam,&rdata)) { int res = SVAL(rparam,0); int converter=SVAL(rparam,2); if (res == 0) { p = rdata; #ifdef VERBOSE natprintf("\n[*]--- Obtained server information:\n"); #endif natprintf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n", rdata+SVAL(p,0)-converter, rdata+SVAL(p,4)-converter, rdata+SVAL(p,8)-converter, rdata+SVAL(p,14)-converter); #ifdef SCANNER cur_vuln = VULID_SERVERINFO; /* server info */ fill_vuln("Was able to obtain server info:", ""); sprintf (param, "Server %.15s, User %.15s", rdata+SVAL(p,0)-converter, rdata+SVAL(p,4)-converter); fill_vuln ("Serverinfo: ", param); sprintf (param, "Workgroup %.15s, Domain %.15s", rdata+SVAL(p,8)-converter, rdata+SVAL(p,14)-converter); fill_vuln ("Serverinfo: ", param); #endif /* SCANNER */ } } if (rparam) free(rparam); if (rdata) free(rdata); return; } /* * try and browse available connections on a host */ static BOOL list_servers() { char *rparam = NULL; char *rdata = NULL; int rdrcnt,rprcnt; char *p; pstring param; int uLevel = 1; int count = 0; int servertype = SV_TYPE_ALL; /* now send a SMBtrans command with api ServerEnum? */ p = param; SSVAL(p,0,0x68); /* api number */ p += 2; strcpy(p,"WrLehDO"); p = skip_string(p,1); strcpy(p,"B16BBDz"); #if 0 strcpy(p,getenv("XX_STR2")); #endif p = skip_string(p,1); SSVAL(p,0,uLevel); SSVAL(p,2,0x2000); /* buf length */ p += 4; SIVAL(p,0,servertype); p += 4; if (call_api(PTR_DIFF(p,param),0, 8,10000, &rprcnt,&rdrcnt, param,NULL, &rparam,&rdata)) { int res = SVAL(rparam,0); int converter=SVAL(rparam,2); int i; if (res == 0) { count=SVAL(rparam,4); p = rdata; if (count > 0) { natprintf("\n[*]--- This machine has a browse list:\n"); natprintf("\n\tServer Comment\n"); natprintf("\t--------- -------\n"); } #ifdef SCANNER cur_vuln = VULID_BROWSELIST; /* name tables */ fill_vuln("Was able to obtain browselist:",""); #endif for (i=0;i0); } /* * open the client sockets */ static BOOL open_sockets(int port ) { static int last_port; char *host; pstring service2; extern int Client; if (port == 0) port=last_port; last_port=port; strupper(service); if (*desthost) host = desthost; else { strcpy(service2,service); host = strtok(service2,"\\/"); strcpy(desthost,host); } DEBUG(3,("Opening sockets\n")); #ifndef SCANNER if (*myname == 0) { get_myname(myname,NULL); strupper(myname); } #endif /* SCANNER */ if (!have_ip) { struct hostent *hp; if ((hp = Get_Hostbyname(host)) == 0) { DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host)); return False; } putip((char *)&dest_ip,(char *)hp->h_addr); } Client = open_socket_out(SOCK_STREAM, &dest_ip, port); if (Client == -1) return False; DEBUG(3,("Connected\n")); set_socket_options(Client,user_socket_options); return True; } /* * close and open the connection again */ BOOL reopen_connection(char *inbuf,char *outbuf) { static int open_count=0; open_count++; if (open_count>5) return(False); DEBUG(1,("Trying to re-open connection\n")); set_message(outbuf,0,0,True); SCVAL(outbuf,smb_com,SMBtdis); SSVAL(outbuf,smb_tid,cnum); setup_pkt(outbuf); send_smb(Client,outbuf); receive_smb(Client,inbuf,SHORT_TIMEOUT); close_sockets(); if (!open_sockets(0)) return(False); return(send_login(inbuf,outbuf,True,True)); } #include /* * oops! closed connection. Catch the sigpipe and throw off * to something that can deal with it. */ void busted () { DEBUG(3,("sigpipe! restarting...\n")); signal (SIGPIPE, SIG_DFL); } /* busted */ /* * The step function steps through the various functions required to * login and obtain the required information on NetBIOS security * conditions. * * global VARS used: * desthost victim's netbios name * myname our system name * stepping set if doing the stepped-guess thing * cur_port usually 139, but needed global copy * cur_user set if valid non-null username * cur_pass set if we got in somehow * cur_sec_mode 0/1/2/3 depending? * cur_phase how far we got last time before it blew chow?? * upp_ctx username/passwd guess tables context * doencrypt obvious * xflag affects doencrypt * Protocol highest max_protocol that was reasonable * [try_names list] filled from nbstat list? [use for bruting too] * [try_users list] preloaded and added to from nbstat * [try_pass list] preloaded and added to from nbstat & shares * [try_shares list] filled if we got a sharelist * [browses list] filled from browse dump [use for bruting too] */ int step (inbuf, outbuf) char * inbuf; char * outbuf; { #ifdef SCANNER fstring test_dir = "\\-NASTY-.$$$"; /* to test write-access */ #endif /* SCANNER */ int fattr = (aDIR | aSYSTEM | aHIDDEN); /* for dir attributes */ char * p; register int x; register int i; int rval = 0; int phase = 0; /* how far we got */ int done; /* * 0 start, with or without NMB names * 1 tcp connected * 2 session_request succeeded, trg name in desthost * 3 vrfydialect ok, cur_sec_mode set * 4 setupX okay [may not happen at all * 5 tcon/IPC & trans-api succeeded, got stuff in sharelist block * 6 connected to at least one share * 7 found various share-related bugs * * Apparently the server can dump the TCP conn any time, so we have to save the * state of progress and be able to quickly resume using info we have already. * At least until we get up to where we can start TConning, I think.. */ /* XXX SCANNER: try to maybe *skip* netbios session_request stuff?? */ /* XXX: TMP for gdb-interactive phase jumping; see what it tolerates */ #define SKIPIT 1 /* * init trial values for things */ max_protocol = PROTOCOL_COREPLUS; Client = -1; upp_ctx = 0; ptr_names = 0; /* * establish buffers here, so subroutines don't have to worry 'bout it */ if (inbuf == NULL) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); if (outbuf == NULL) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); if (!inbuf || !outbuf) return (-1); signal (SIGPIPE, busted); /* XXX? need recovery routine */ /* * put nmbstatus probe here; fill in more of try_names LL to 16 chars !! * fill in some try_users and try_pass from that list, too * if can't get nmbstatus, not a problem; start guessing nbnames anyways * if send/recv TIMEOUT or write err at any point, restart??? * scope-guessing here? */ #ifdef VERBOSE natprintf("[*]--- Obtaining list of remote NetBIOS names\n"); #endif name_type = 0; p = NULL; x = send_status("*"); if (x) goto s_got_names; DEBUG (1,("NBSTAT * query failed, making some more guesses\n")); /* * At this point the server didn't respond with any names. * grab some DNS stuff and feed it in, first */ p = (char *) Get_Hostbyaddr (dest_ip); if (p && (p = strtok(p, "."))) { fill_block (try_names, p); /* its bare hostname */ /* * if we're not root further queries are unlikely to work, so punt here */ if (getuid()) goto s_got_names; x = send_status (p); p = strtok (NULL, "."); if (p) send_status (p); /* server.BIGCORP.com?? */ } /* * XXX: perhaps should rephase this to handle try_scopes block ?? * Should think about SNMP here, too. Under some circumstances NT 4.0 * doesn't respond to "*". Could be a * blatant violation of rfc1001/1002, * but nonetheless it looks like we have to make MORE guesses and hope for * the best. */ if (!x) x = send_status ("WORKGROUP"); if (!x) { name_type = 1; x = send_status ("\001\002__MSBROWSE__\002"); name_type = 0; } if (!x) x = send_status ("DEFAULT"); /* roughly in */ if (!x) x = send_status ("SERVER"); /* decreasing order */ if (!x) x = send_status ("ADMINISTRATOR"); /* of likelihood... */ s_got_names: fill_block (try_names, "*SMBSERVER"); fill_block (try_names, "SMBSERVER"); fill_block (try_names, "* "); name_type = 0x20; /* for normal sessions */ /* * Phase 0 opens a connection to the specified host */ phase_0: /* get a TCP connection */ phase = 0; rval = 0; close_sockets(); if (open_sockets (cur_port)) phase++; if (phase != 1) /* if we can't talk to 139, */ goto nope; /* pretty much give up here... */ rval = 1; /* * Phase 1 does initial protocol negotiation - setting up the session * with what we think is the remote hosts's netbios name */ phase_1: /* pass the wacky rfc1002 stuff */ #ifdef SKIPIT if (phase == 2) goto phase_2; #endif /* SKIPIT */ p = get_block (try_names, ptr_names); if (p == NULL) { if (name_type == 0) goto nope; /* really exhausted namelist, punt */ name_type = 0; /* retry names w/o trailing space */ ptr_names = 0; DEBUG (1,("retrying session-names with type 0...\n")); goto phase_0; } strcpy (desthost, p); #ifdef VERBOSE natprintf("\n[*]--- Attempting to connect with name: %s\n", p); #endif x = send_session_request (inbuf, outbuf); if (x == 1) { #ifdef VERBOSE natprintf("[*]--- CONNECTED with name: %s\n", p); #endif DEBUG(0,("session to %s (0x%x) open\n", desthost, name_type)); phase = 2; goto phase_2; } else { #ifdef VERBOSE natprintf("[*]--- Unable to connect\n"); #endif ptr_names++; goto phase_0; } /* * Phase 2 does more protocol netgotiation */ phase_2: #ifdef SKIPIT if (phase == 3) goto phase_3; #endif /* SKIPIT */ name_type = 0x20; x = send_prots (inbuf, outbuf); /* * XXX: negprot may just plain fail here, if server wants > CORE */ if (x == 1) { if ((max_protocol == PROTOCOL_COREPLUS) && (sec_mode & 0x03)) { /* * got use-encrypted secmode anyway; do something creative here */ #ifdef VERBOSE natprintf("[*]--- Remote server wants us to encrypt, telling it not to\n"); #endif max_protocol = PROTOCOL_LANMAN2; /* was PROTOCOL_NT1 ... */ x = send_prots (inbuf, outbuf); if (x == 0) { goto phase_0; } } /* sec_mode = encryption */ cur_protocol = max_protocol; cur_sec_mode = sec_mode; phase++; } /* if x */ if (phase != 3) goto nope; /* * Setup the session with username and password authentication */ phase_3: /* smb session setup/auth */ #ifdef SKIPIT if (phase == 4) goto phase_4; #endif /* SKIPIT */ /* * Try session using any given user/pass first, and then various guesses */ #ifdef VERBOSE natprintf("[*]--- Attempting to establish session\n"); #endif x = send_setup (inbuf, outbuf); /* First try is NULL/NULL */ if (x == 1) { cur_vuln = VULID_SESSIONNOPASS; fill_vuln("Was able to connect with no username", "or password"); phase = 4; goto phase_4; } #ifdef VERBOSE natprintf("[*]--- Was not able to establish session with no password\n"); #endif upp_ctx = 0; /* oops, gotta try harder */ done = 0; username[0] = '\0'; while (!done) { if (!userfd || !passfd) uppair(); else { if (fgets(password, sizeof(password), passfd) == NULL) { rewind(passfd); if (fgets(password, sizeof(password), passfd) == NULL) { natprintf("[*]--- Failure reading password from: %s\n", passfile); exit(-1); } username[0] = '\0'; } strtok(password, "\r\n"); if (username[0] == '\0') { if (fgets(username, sizeof(username), userfd) == NULL) { if (feof(userfd)) { done++; goto nope; } } strtok(username, "\r\n"); } } if ((! *username) && (! *password)) uppair(); /* sleaze for NT */ #ifdef VERBOSE natprintf("[*]--- Attempting to connect with Username: `%s' Password: `%s'\n", username, password); #endif x = send_setup (inbuf, outbuf); if ((x == 1) && (upp_ctx < 3)) { #ifdef VERBOSE natprintf("[*]--- CONNECTED: Username: `%s' Password: `%s'\n", username, password); #endif strcpy (cur_user, username); /* XXX: we never really use these */ strcpy (cur_pass, password); upp_ctx = 3; phase++; cur_vuln = VULID_SESSIONPASS; fill_vuln("Was able to guess the username and", " password to establish a connection"); sprintf(outbuf, "Username: `%s'", username); fill_vuln(outbuf, ""); sprintf(outbuf, "Password: `%s'", password); fill_vuln(outbuf, ""); break; } } /* while uppair */ if (phase == 4) goto phase_4; #if 0 for (i = 0; ; i++) { if (try_users[i] == NULL) break; strcpy (username, try_users[i]); } #endif /* * NOW try both-null params if all else failed */ username[0] = '\0'; password[0] = '\0'; if (send_setup (inbuf, outbuf)) phase++; if (phase != 4) goto nope; /* oh well, */ /* * Connects to the IPC service and dumps the share list */ phase_4: /* IPC TCon, and dump sharelist */ #ifdef SKIPIT if (phase == 5) goto phase_5; #endif /* SKIPIT */ /* * connect as IPC / \\PIPE\LANMAN, do modded browse_host -> try_shares */ /* * 3 places that call_api to get info: browse_host server_info list_servers * all of which need modded to fill in the info blox */ /* * "service" and "dev" dont even come into play here, and then WAY LATER get * plugged into a tcon. So after playing here, shuck this tcon and get a new * one of type A: for phase 5. */ sprintf(service,"\\\\%s\\IPC$", desthost); strupper(service); connect_as_ipc = True; cur_serr = 0; x = send_tcon (inbuf, outbuf); if (x == 1) goto phase_4b; if (cur_serr != 2) { /* unless it's an access problem, */ phase++; goto phase_5; /* plunge blindly ahead anyways */ } /* * we shouldn't need a password for a IPC tcon, but if we do we do. */ upp_ctx = 4; while (uppair()) { cur_serr = 0; x = send_tcon (inbuf, outbuf); if (x == 1) goto phase_4b; } /* while uppair */ #if 0 for (i = 0; ; i++) { p = get_block (try_names, i); if (! p) goto nope; sprintf (service, "\\\\%s\\IPC$", p); strupper (service); x = send_tcon (inbuf, outbuf); if (x == 1) { phase++; break; } } /* for i */ /* * XXX: no IPC tcon ain't necessarily fatal; should try shares anyways?? */ if (phase != 5) goto nope; #endif /* 0 */ phase_4b: server_info(); x = browse_host(True); x = list_servers(); send_tdis(inbuf, outbuf); /* done with this tcon, dump it */ phase++; /* * Actually try to access all of the shared services */ phase_5: /* connect to some shares */ #ifdef SKIPIT if (phase == 6) goto phase_6; #endif /* SKIPIT */ /* * Add extra try_shares guesses [C$, D$, NT-def etc] here, and keep bumping * hid_shares up past any live names we collected. */ x = fill_block (try_shares, "ADMIN$"); if (x) hid_shares = x; x = fill_block (try_shares, "C$"); if (x) hid_shares = x; x = fill_block (try_shares, "D$"); if (x) hid_shares = x; x = fill_block (try_shares, "ROOT"); /* useful in default Samba setups! */ if (x) hid_shares = x; x = fill_block (try_shares, "WINNT$"); if (x) hid_shares = x; ptr_shares = 0; connect_as_ipc = False; /* * Try hitting disk-shares till exhausted, skipping invalid ones */ phase_5a: p = get_block (try_shares, ptr_shares); if (p == NULL) { goto nope; /* done with 'em all! */ } cur_serr = 0; sprintf (service, "\\\\%s\\%s", desthost, p); #ifdef VERBOSE natprintf("\n[*]--- Attempting to access share: %s\n", service); #endif x = send_tcon (inbuf, outbuf); if (x == 1) { #ifdef VERBOSE natprintf("[*]--- WARNING: Able to access share: %s\n", service); #endif phase = 6; goto phase_6; } else { #ifdef VERBOSE natprintf("[*]--- Unable to access\n"); #endif } /* * try all listed shares with the current info; get fancy later. */ /* * should start picking out the *reason* share-connect failed, to * differentiate between bad sharename and bad passwd if at all possible?? * yes: see cur_serr and interpret_serr to set it ... */ if (cur_serr == 6) { /* if nonexistent netpath, */ ptr_shares++; /* skip this sharename entirely */ goto phase_5a; } upp_ctx = 4; /* restart passwd list only! */ while (uppair()) { x = send_tcon (inbuf, outbuf); if (x == 1) { phase = 6; goto phase_6; } /* x */ if ((sec_mode & 1) && (cur_serr == 2)) /* if still access-denied and */ break; /* in user-mode sec, skip it as well */ } /* while uppair */ ptr_shares++; goto phase_5a; phase_6: /* exercise file-access bugs */ #ifdef SCANNER cur_vuln = VULID_SHAREACCESS; /* default-passwd */ sprintf (outbuf, "%s as user `%s' pass `%s'", service, username, password); fill_vuln ("Connected to share ", outbuf); /* * xxx: probably want to check for *WRITE* access, too, BEFORE filling this */ /* * i.e. create/nuke some bogus file and strcat RO or RW on to vuln_string */ /* * holler if this is one of those hidden shares */ if (ptr_shares >= hid_shares) { cur_vuln = VULID_SHAREHIDDEN; fill_vuln ("Hidden share: ", service); } /* * as long as we're here, we're bloody well gonna test the access mode */ strcpy (cur_dir, test_dir); natprintf("[*]--- Checking write access in: %s\n", service); x = do_mkdir (cur_dir); if (x == 1) { cur_vuln = VULID_SHAREWRITE; fill_vuln ("Write access: ", service); natprintf("[*]--- WARNING: Directory is writeable: %s\n", service); strcpy (cur_dir, test_dir); /* reset after expand_mask */ x = do_rmdir (cur_dir); if (x == 0) fill_vuln ("cleanup FAILED: ", service); } /* if mkdir x = 1 */ /* * Various .. checks to see if we can get out of the share */ natprintf("[*]--- Attempting to exercise .. bug on: %s\n", service); DEBUG (0,("%s: insert dotdot here!\n", try_shares[ptr_shares])); cur_stash = NULL; /* RESET per share! */ strcpy (cur_dir, "\\*.*"); do_dir (inbuf, outbuf, cur_dir, fattr, get_stash, False); tested_stash = 0; strcpy (cur_dir, "..\\*.*"); /* straight-out ../foo */ do_dir (inbuf, outbuf, cur_dir, fattr, cmp_stash, False); tested_stash = 0; strcpy (cur_dir, "\\..\\*.*"); /* or with leading slashes */ do_dir (inbuf, outbuf, cur_dir, fattr, cmp_stash, False); tested_stash = 0; strcpy (cur_dir, "...\\*.*"); /* obligatory multi-dots attack */ do_dir (inbuf, outbuf, cur_dir, fattr, cmp_stash, False); tested_stash = 0; strcpy (cur_dir, ".\\...\\*.*"); /* try to confuse it */ do_dir (inbuf, outbuf, cur_dir, fattr, cmp_stash, False); tested_stash = 0; /* * Hmm, if we don't do this, we might octopus the server, but it seems to * be fairly resistant and just hands back "no resources". */ send_tdis (inbuf, outbuf); ptr_shares++; goto phase_5a; /* back for the next one */ /* * by *now* we should have a nice little pile of info, and possibly an open * connection to the last tested share to mess with ... */ nope: (void) free (inbuf); (void) free (outbuf); inbuf = outbuf = NULL; return (rval); } /* step */ #endif /* STEPPING */ #ifdef SCANNER /* Step-wrapper that swaps in for main(), called by module(). */ int nas_step (xip) unsigned long xip; { register int i; BOOL is_vuln = 0; /* do or don't report anything? */ TimeInit(); /* from main */ charset_initialise(); /* so toupper/tolower work?!?? */ if (xip == 0L) return (0); /* sanity checks */ if (xip == 0xffffffff) return (0); putip (&dest_ip, (struct in_addr *)&xip); /* cast-convert! sigh.. */ have_ip = True; pid = 10240; uid = 0; gid = 0; cur_port = 139; /* will be stock... */ stepping = 1; strcpy (username, "ADMINISTRATOR"); /* preload the ideal situation... */ xflag = 0; /* disable passwd encryption */ is_vuln = step (NULL, NULL); /* do canned vulnerability tests */ close_sockets(); clear_block (try_names, idx_names); /* clean up all dynamic info... */ clear_block (try_users, idx_users); clear_block (try_pass, idx_pass); clear_block (try_shares, idx_shares); return (is_vuln); } /* nas_step */ #else /* SCANNER */ /**************************************************************************** main program ****************************************************************************/ int main(int argc,char *argv[]) { char *pname = argv[0]; int port = 139; int opt; extern FILE *dbf; extern char *optarg; pstring query_host; BOOL message = False; BOOL didstat = 0; *query_host = 0; DEBUGLEVEL = 2; setup_logging(pname,True); TimeInit(); charset_initialise(); setvbuf (stdout, (char *) 0, _IOLBF, 0); #ifdef SCANNER /* should have hooks for setting these on the fly? are they relevant? */ pid = ~ getpid(); uid = 0; gid = 0; #else pid = getpid(); uid = getuid(); gid = getgid(); mid = pid + 100; myumask = umask(0); umask(myumask); #endif /* SCANNER */ #ifndef SCANNER /* leave username null until we either set it, or need one, or ... */ if (getenv("USER")) { strcpy(username,getenv("USER")); strupper(username); } if (*username == 0 && getenv("LOGNAME")) { strcpy(username,getenv("LOGNAME")); strupper(username); } #endif /* SCANNER */ if (argc < 2) { usage(pname); exit(1); } if (*argv[1] != '-') { strcpy(service,argv[1]); argc--; argv++; if (count_chars(service,'\\') < 3) { usage(pname); natprintf("\n%s: Not enough '\\' characters in service\n",service); exit(1); } /* if (count_chars(service,'\\') > 3) { usage(pname); natprintf("\n%s: Too many '\\' characters in service\n",service); exit(1); } */ #ifdef SCANNER /* if passwd arg is "-", arrange to brute via dictionary fed from someplace */ /* if needed to brute an *IPC* tcon, ferkrissake, use "\\\ - -L victim" */ if ((argc > 1) && (*argv[1] == '-') && (argv[1][1] == '\0')) { read_pass = 1; argc--; argv++; } #endif /* SCANNER */ if (argc > 1 && (*argv[1] != '-')) { got_pass = True; strcpy(password,argv[1]); memset(argv[1],'X',strlen(argv[1])); argc--; argv++; } } #ifdef KANJI setup_term_code (KANJI); while ((opt = getopt (argc, argv, "O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:")) != EOF) #else #ifdef STEPPING while ((opt = getopt (argc, argv, "O:M:i:Nn:d:Pp:l:hI:EB:S:U:L:m:W:x")) != EOF) #else while ((opt = getopt (argc, argv, "O:M:i:Nn:d:Pp:l:hI:EB:U:L:m:W:")) != EOF) #endif /* STEPPING */ #endif /* KANJI */ switch (opt) { case 'm': max_protocol = interpret_protocol(optarg,max_protocol); break; case 'O': strcpy(user_socket_options,optarg); break; case 'M': name_type = 3; strcpy(desthost,optarg); strupper(desthost); message = True; break; case 'i': strcpy(scope,optarg); break; case 'L': got_pass = True; strcpy(query_host,optarg); break; case 'U': { char *p; strcpy(username,optarg); if ((p=strchr(username,'%'))) { *p = 0; strcpy(password,p+1); got_pass = True; memset(strchr(optarg,'%')+1,'X',strlen(password)); } } break; case 'W': strcpy(workgroup,optarg); break; case 'E': dbf = stderr; break; case 'I': { dest_ip = *interpret_addr2(optarg); if (zero_ip(dest_ip)) exit(1); have_ip = True; } break; case 'n': strcpy(myname,optarg); break; case 'N': got_pass = True; break; case 'P': connect_as_printer = True; break; case 'd': if (*optarg == 'A') DEBUGLEVEL = 10000; else DEBUGLEVEL = atoi(optarg); break; case 'l': sprintf(debugf,"%s.client",optarg); break; case 'p': port = atoi(optarg); break; case 'h': usage(pname); exit(0); break; #ifdef STEPPING /* 'B' was in getopt-str but unused??! Now it means "Breakin". */ /* can issue multiple "-B FOO" cmds to add netbios names to try_names block */ case 'B': fill_block (try_names, optarg); stepping = 1; break; /* one-off NMB status, which just happens to add any results to try_names */ case 'S': (void) send_status (optarg); didstat = 1; break; case 'x': xflag = 1; break; #endif /* STEPPING */ #ifdef KANJI case 't': if (!setup_term_code (optarg)) { DEBUG(0, ("%s: unknown terminal code name\n", optarg)); usage (pname); exit (1); } break; #endif /* KANJI */ default: usage(pname); exit(1); } #ifdef STEPPING if (stepping) goto do_stepping; #endif /* STEPPING */ if (!*query_host && !*service && !message) { if (! didstat) usage(pname); exit(1); } DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION)); #ifndef SCANNER get_myname(*myname?NULL:myname,&myip); strupper(myname); #endif if (*query_host) { int ret = 0; sprintf(service,"\\\\%s\\IPC$",query_host); strupper(service); connect_as_ipc = True; if (open_sockets(port)) { #if 0 *username = 0; #endif if (!send_login(NULL,NULL,True,True)) return(1); server_info(); if (!browse_host(True)) { sleep(1); browse_host(True); } if (!list_servers()) { sleep(1); list_servers(); } send_logout(); close_sockets(); } return(ret); } if (message) { int ret = 0; if (open_sockets(port)) { pstring inbuf,outbuf; bzero(outbuf,smb_size); if (!send_session_request(inbuf,outbuf)) return(1); send_message(inbuf,outbuf); close_sockets(); } return(ret); } if (open_sockets(port)) { if (!process()) { close_sockets(); return(1); } close_sockets(); } else return(1); return(0); #ifdef STEPPING do_stepping: /* if regular interactive but still in step-mode, get as far as we can and then offer prompt for human intervention */ if (! have_ip) { natprintf ("need a target!\n"); exit (1); } if (stepping) { cur_port = port; if (*username) fill_block (try_users, username); /* we can supply an extra uname */ if (*password) fill_block (try_pass, password); /* likewise for passwd */ if (*service) { register int i = strlen (service); while ((i > 0) && (service[i] != '\\')) i--; if (i > 0) { i++; fill_block (try_shares, &service[i]); /* and a sharename */ } } /* if *service */ step (NULL, NULL); /* pre-try a whole pile of stuff */ close_sockets(); return (0); } /* stepping */ #endif /* STEPPING */ } /* main */ /* error code stuff - put together by Merik Karman merik@blackadder.dsh.oz.au */ #endif /* SCANNER, build main -vs- nas_step */ typedef struct { char *name; int code; char *message; } err_code_struct; /* Dos Error Messages */ err_code_struct dos_msgs[] = { {"ERRbadfunc",1,"Invalid function."}, {"ERRbadfile",2,"File not found."}, {"ERRbadpath",3,"Directory invalid."}, {"ERRnofids",4,"No file descriptors available"}, {"ERRnoaccess",5,"Access denied."}, {"ERRbadfid",6,"Invalid file handle."}, {"ERRbadmcb",7,"Memory control blocks destroyed."}, {"ERRnomem",8,"Insufficient server memory to perform the requested function."}, {"ERRbadmem",9,"Invalid memory block address."}, {"ERRbadenv",10,"Invalid environment."}, {"ERRbadformat",11,"Invalid format."}, {"ERRbadaccess",12,"Invalid open mode."}, {"ERRbaddata",13,"Invalid data."}, {"ERR",14,"reserved."}, {"ERRbaddrive",15,"Invalid drive specified."}, {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."}, {"ERRdiffdevice",17,"Not same device."}, {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."}, {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."}, {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."}, {"ERRbadpipe",230,"Pipe invalid."}, {"ERRpipebusy",231,"All instances of the requested pipe are busy."}, {"ERRpipeclosing",232,"Pipe close in progress."}, {"ERRnotconnected",233,"No process on other end of pipe."}, {"ERRmoredata",234,"There is more data to be returned."}, #ifdef SCANNER /* a few more discovered on the fly... most weren't in CIFS draft, but doing "net helpmsg on NT spews the text. we're inventing some of this now; they won't match final draft!! */ {"ERRnetaccess",65,"Network access denied"}, {"ERRresourcetype",66,"Network resource type incorrect"}, {"ERRnetname",67,"Network name not found"}, /* NT ?sharename */ {"ERRnomoreconn",71,"No more connections available"}, {"ERRnetpassword",86,"Network password incorrect"}, {"ERRparam",87,"Parameter incorrect"}, /* NT unicode stuff */ {"ERRnouids",90,"Too many UIDs"}, {"ERRaccexpired",2239,"Account expired or disabled"}, {"ERRwsaccess",2240,"Access denied from this workstation"}, {"ERRtimeaccess",2241,"Cannot log in at this time"}, {"ERRpassword",2242,"Password expired"}, {"ERRcorruptsec",2247,"Security database corrupted"}, {"ERRinvgroup",2455,"Invalid workgroup"}, /* from smb 1.9.16 */ #endif /* SCANNER */ {NULL,-1,NULL}}; /* Server Error Messages */ err_code_struct server_msgs[] = { {"ERRerror",1,"Non-specific error code."}, {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."}, {"ERRbadtype",3,"reserved."}, {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."}, {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."}, {"ERRinvnetname",6,"Invalid network name in tree connect."}, {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."}, {"ERRqfull",49,"Print queue full (files) -- returned by open print file."}, {"ERRqtoobig",50,"Print queue full -- no space."}, {"ERRqeof",51,"EOF on print queue dump."}, {"ERRinvpfid",52,"Invalid print file FID."}, {"ERRsmbcmd",64,"The server did not recognize the command received."}, {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."}, {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."}, {"ERRreserved",68,"reserved."}, {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."}, {"ERRreserved",70,"reserved."}, {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."}, {"ERRpaused",81,"Server is paused."}, {"ERRmsgoff",82,"Not receiving messages."}, {"ERRnoroom",83,"No room to buffer message."}, {"ERRrmuns",87,"Too many remote user names."}, {"ERRtimeout",88,"Operation timed out."}, {"ERRnoresource",89,"No resources currently available for request."}, {"ERRtoomanyuids",90,"Too many UIDs active on this session."}, {"ERRbaduid",91,"The UID is not known as a valid ID on this session."}, {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."}, {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."}, {"ERRcontmpx",252,"Continue in MPX mode."}, {"ERRreserved",253,"reserved."}, {"ERRreserved",254,"reserved."}, {"ERRnosupport",0xFFFF,"Function not supported."}, {NULL,-1,NULL}}; /* Hard Error Messages */ err_code_struct hard_msgs[] = { {"ERRnowrite",19,"Attempt to write on write-protected diskette."}, {"ERRbadunit",20,"Unknown unit."}, {"ERRnotready",21,"Drive not ready."}, {"ERRbadcmd",22,"Unknown command."}, {"ERRdata",23,"Data error (CRC)."}, {"ERRbadreq",24,"Bad request structure length."}, {"ERRseek",25 ,"Seek error."}, {"ERRbadmedia",26,"Unknown media type."}, {"ERRbadsector",27,"Sector not found."}, {"ERRnopaper",28,"Printer out of paper."}, {"ERRwrite",29,"Write fault."}, {"ERRread",30,"Read fault."}, {"ERRgeneral",31,"General failure."}, {"ERRbadshare",32,"A open conflicts with an existing open."}, {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, {"ERRwrongdisk",34,"The wrong disk was found in a drive."}, {"ERRFCBUnavail",35,"No FCBs are available to process request."}, {"ERRsharebufexc",36,"A sharing buffer has been exceeded."}, {NULL,-1,NULL}}; struct { int code; char *class; err_code_struct *err_msgs; } err_classes[] = { {0,"SUCCESS",NULL}, {0x01,"ERRDOS",dos_msgs}, {0x02,"ERRSRV",server_msgs}, {0x03,"ERRHRD",hard_msgs}, {0x04,"ERRXOS",NULL}, {0xE1,"ERRRMX1",NULL}, {0xE2,"ERRRMX2",NULL}, {0xE3,"ERRRMX3",NULL}, {0xFF,"ERRCMD",NULL}, {-1,NULL,NULL}}; /**************************************************************************** return a SMB error string from a SMB buffer ****************************************************************************/ char *smb_errstr(char *inbuf) { static pstring ret; int class = CVAL(inbuf,smb_rcls); int num = SVAL(inbuf,smb_err); int i,j; for (i=0;err_classes[i].class;i++) if (err_classes[i].code == class) { if (err_classes[i].err_msgs) { err_code_struct *err = err_classes[i].err_msgs; for (j=0;err[j].name;j++) if (num == err[j].code) { if (DEBUGLEVEL > 0) sprintf(ret,"%s - %s (%s)",err_classes[i].class, err[j].name,err[j].message); else sprintf(ret,"%s - %s",err_classes[i].class,err[j].name); return ret; } } sprintf(ret,"%s - %d",err_classes[i].class,num); return ret; } sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num); return(ret); } nat-1.0.orig/charset.h0100600000175000017500000000334106301746754015741 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. Character set handling Copyright (C) Andrew Tridgell 1992-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef CHARSET_C extern char *dos_char_map; extern char *upper_char_map; extern char *lower_char_map; extern void add_char_string(char *s); extern void charset_initialise(void); #ifdef toupper #undef toupper #endif #ifdef tolower #undef tolower #endif #ifdef isupper #undef isupper #endif #ifdef islower #undef islower #endif #ifdef isdoschar #undef isdoschar #endif #ifdef isspace #undef isspace #endif #define toupper(c) upper_char_map[(char)(c)] #define tolower(c) lower_char_map[(char)(c)] #define isupper(c) (((char)(c)) != tolower(c)) #define islower(c) (((char)(c)) != toupper(c)) #define isdoschar(c) (dos_char_map[(char)(c)] != 0) #define isspace(c) ((c)==' ' || (c) == '\t') #endif nat-1.0.orig/charset.c0100600000175000017500000000675406301746754015747 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. Character set handling Copyright (C) Andrew Tridgell 1992-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define CHARSET_C #include "includes.h" extern int DEBUGLEVEL; char xx_dos_char_map[256]; char xx_upper_char_map[256]; char xx_lower_char_map[256]; char *dos_char_map = NULL; char *upper_char_map = NULL; char *lower_char_map = NULL; static void add_dos_char(int lower, int upper) { DEBUG(6,("Adding chars 0%o 0%o\n",lower,upper)); if (lower) dos_char_map[(char)lower] = 1; if (upper) dos_char_map[(char)upper] = 1; if (lower && upper) { lower_char_map[(char)upper] = (char)lower; upper_char_map[(char)lower] = (char)upper; } } /**************************************************************************** initialise the charset arrays ****************************************************************************/ void charset_initialise(void) { int i; dos_char_map = &xx_dos_char_map[128]; upper_char_map = &xx_upper_char_map[128]; lower_char_map = &xx_lower_char_map[128]; for (i= -128;i<=127;i++) { dos_char_map[(char)i] = 0; } for (i=0;i<=127;i++) { if (isalnum((char)i) || strchr("._^$~!#%&-{}()@'`",(char)i)) add_dos_char(i,0); } for (i= -128;i<=127;i++) { char c = (char)i; upper_char_map[i] = lower_char_map[i] = c; if (isupper(c)) lower_char_map[c] = tolower(c); if (islower(c)) upper_char_map[c] = toupper(c); } /* valid for all DOS PC */ add_dos_char(142,0); /* A trema */ add_dos_char(143,0); /* A o */ add_dos_char(144,0); /* E ' */ add_dos_char(146,0); /* AE */ add_dos_char(153,0); /* O trema */ add_dos_char(154,0); /* U trema */ add_dos_char(165,0); /* N tilda */ add_dos_char(128,0); /* C cedille */ add_dos_char(156,0); /* Pound */ add_dos_char(183,0); /* A ` (WIN)*/ add_dos_char(157,0); /* Phi (WIN)*/ add_dos_char(212,0); /* E` (WIN)*/ } /******************************************************************* add characters depending on a string passed by the user ********************************************************************/ void add_char_string(char *s) { char *extra_chars = (char *)strdup(s); char *t; if (!extra_chars) return; for (t=strtok(extra_chars," \t\r\n"); t; t=strtok(NULL," \t\r\n")) { char c1=0,c2=0; int i1=0,i2=0; if (isdigit(*t) || (*t)=='-') { sscanf(t,"%i:%i",&i1,&i2); add_dos_char(i1,i2); } else { sscanf(t,"%c:%c",&c1,&c2); add_dos_char(c1,c2); } } free(extra_chars); } nat-1.0.orig/byteorder.h0100600000175000017500000000621306301746754016310 0ustar jfernandezjfernandez/* * This file has been modified from the original Samba package * by Secure Networks Inc., January and February, 1997. This package and * all code which it is based on falls under the GNU Public License * agreement. */ /* Unix SMB/Netbios implementation. Version 1.9. SMB Byte handling Copyright (C) Andrew Tridgell 1992-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This file implements macros for machine independent short and int manipulation */ #undef CAREFUL_ALIGNMENT /* we know that the 386 can handle misalignment and has the "right" byteorder */ #ifdef __i386__ #define CAREFUL_ALIGNMENT 0 #endif #ifndef CAREFUL_ALIGNMENT #define CAREFUL_ALIGNMENT 1 #endif #define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) #define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) #define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val)) #if CAREFUL_ALIGNMENT #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) #define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) #define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) #define SVALS(buf,pos) ((int16)SVAL(buf,pos)) #define IVALS(buf,pos) ((int32)IVAL(buf,pos)) #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val))) #define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val))) #define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val))) #define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val))) #else /* this handles things for architectures like the 386 that can handle alignment errors */ /* WARNING: This section is dependent on the length of int16 and int32 being correct */ #define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos))) #define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos))) #define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos))) #define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos))) #define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val)) #define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val)) #define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val)) #define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val)) #endif /* now the reverse routines - these are used in nmb packets (mostly) */ #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16))) #define RSVAL(buf,pos) SREV(SVAL(buf,pos)) #define RIVAL(buf,pos) IREV(IVAL(buf,pos)) #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) nat-1.0.orig/README0100600000175000017500000000303006301746754015012 0ustar jfernandezjfernandezNetBIOS Security Kit v1.0 The intention of this package is to perform various security checks on remote servers running NetBIOS file sharing services. For usage, please see the nat.1 man page or nat.1.txt for the text version. In the grand scheme of NetBIOS and Windows NT security, NAT is fairly small. It is, without question a step in the right direction but it like any other software, needs further development. In order to continue software like this to be available for free, it needs to be a community effort. If you are interested in helping NAT grow, we encourage you to mail us at nat-dev@secnet.com This package is entirely based on code written by Andrew Tridgell and contains the following license agreement: /* Unix SMB/Netbios implementation. Version 1.9. Samba utility functions Copyright (C) Andrew Tridgell 1992-1995 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ nat-1.0.orig/Makefile0100600000175000017500000003006007475247462015602 0ustar jfernandezjfernandez########################################################################### # Makefile for Samba SMB client/server for unix # Copyright Andrew Tridgell 1992,1993,1994 ########################################################################### CC = gcc # set this to the default group you want your machine to appear in # for browsing. This can also be set in nmbd (see nmbd(8)) # NOTE: If you set it to * then nmbd will try to find a workgroup on # the local net WORKGROUP = WORKGROUP # set this to the name of the default account, which is the one # to use when no username or password is specified. This can be overridden # in the runtime configuration file (see smb.conf(5)) # NOTE: The account "nobody" may not be a good one as # on many unixes it may not be able to print. Thus you # might have to create a separate guest account that can print. GUESTACCOUNT = nobody ##################################### # WHICH OPERATING SYSTEM? # UNCOMMENT ONE OF THE SECTIONS BELOW # MAKE SURE ONLY *ONE* IS UNCOMMENTED # # The following are additional flags that may apply # -DNETGROUP if your machine supports yp netgroups # -DSHADOW_PWD if you are using shadow passwords # -DGETPWANAM if you wish to use getpwanam() call # -DPWDAUTH if you have and want to use the pwdauth() call # -DUFC_CRYPT if you want the fast crypt routine # -DALLOW_CHANGE_PASSWORD if you want users to be able to set their password # remotely (only works on some systems) # -DQUOTAS for quota support in disk_free(). This probably only works # on some systems. # # NOTE: GETPWANAM & PWDAUTH are mutually exclusive, if you # Define one, you should NOT define the other. ##################################### ##################################### # for the JAPANESE EXTENSION # select filename's code set for KANJI/KANA in UNIX, # apply the following flag # -DKANJI=\"\" # is select character code set for JAPAN. # sjis: if your machine support SJIS # euc: if your machine support EUC # jis7: if your machine support JIS7 # jis8: if your machine support JIS8 # junet: if your machine support jis7 + junet rule # hex: if your machine only support 7 bits ascii filename only # convert to hexdecimal code preseeding ':'. # see also README.jis ###################################### # This is for SUNOS 4. Use the SUNOS5 entry for Solaris 2. # Note that you cannot use Suns "cc" compiler # as it's not an Ansi-C compiler. Get gcc or acc. # Note that if you have adjunct passwords you may need the GETPWANAM # or PWDAUTH option. There have been reports that using PWDAUTH may crash # your pwdauthd server so GETPWANAM is preferable (and probably faster) # contributed by Andrew.Tridgell@anu.edu.au # FLAGSM = -DSUNOS4 # LIBSM = # Use this for Linux with shadow passwords # contributed by Andrew.Tridgell@anu.edu.au # add -DLINUX_BIGCRYPT is you have shadow passwords but don't have the # right libraries and includes #FLAGSM = -DLINUX -DSHADOW_PWD -DNO_ASMSIGNALH #LIBSM = -lshadow # Use this for Linux without shadow passwords # contributed by Andrew.Tridgell@anu.edu.au FLAGSM = -DLINUX -DNO_ASMSIGNALH LIBSM = # This is for SUNOS5 (also known as Solaris 2) # contributed by Andrew.Tridgell@anu.edu.au # FLAGSM = -DSUNOS5 -DSHADOW_PWD -DNETGROUP # LIBSM = -lsocket -lnsl # This is for SVR4 # Contributed by mark@scot1.ucsalf.ac.uk # FLAGSM = -DSVR4 -DSHADOW_PWD -DALLOW_CHANGE_PASSWORD # LIBSM = -lsocket -lnsl -lc -L/usr/ucblib -lucb # This is for the Motorola 88xxx/9xx range of machines # Contributed by RPE@monnet.com # FLAGSM = -DSVR4 -DSHADOW_PWD -DGETTIMEOFDAY1 # LIBSM = -lsocket -lnsl -lc -L/usr/ucblib -lucb # This is for UNIXWARE # FLAGSM = -Xa -DSVR4 -DSHADOW_PWD # LIBSM = -lsocket -lnsl -lc -L/usr/ucblib -lucb # This is for ULTRIX. Add -DULTRIX_AUTH for Ultrix enhanced security. # contributed by iversen@dsfys1.fi.uib.no # FLAGSM = -DULTRIX # LIBSM = # This is for OSF1 (Alpha) # contributed by errath@balu.kfunigraz.ac.at # NOTE: You may need -warning_unresolved if you get unresolved symbols # FLAGSM = -DOSF1 # LIBSM = # This is for OSF1 (Alpha) with NIS and Fast Crypt # contributed by David Gardiner # FLAGSM = -DOSF1 -DNETGROUP -DUFC_CRYPT # LIBSM = # This is for OSF1 (Alpha) V2.0 Enhanced Security # contributed by Udo Linauer # FLAGSM = -DOSF1 -DOSF1_ENH_SEC # LIBSM = -lsecurity # This is for AIX # contributed by tomc@osi.curtin.edu.au # FLAGSM = -DAIX # LIBSM = # This is for AIX 3.2.5 with DCE/DFS # contributed by Jim Doyle # FLAGSM = -DAIX -DDFS_AUTH -DSIGCLD_IGNORE -DNO_SIGNAL_TEST # LIBSM = -lc_r -ldce -lpthreads # CC = cc_r # This is for BSDI # contributed by tomh@metrics.com # versions of BSDI prior to 2.0 may need to add -DUSE_F_FSIZE for # disk usage stats to be correct # FLAGSM = -DBSDI # LIBSM = # # This is for OpenBSD. # # FLAGSM = -DOPENBSD -DSHADOW_PWD # LIBSM = -lcrypt # This is for NetBSD. Add -DNETBSD_1_0 if you are using 1.0 # contributed by noses@oink.rhein.de # FLAGSM = -DNETBSD -DSHADOW_PWD # LIBSM = -lcrypt # This is for SEQUENT. # Contributed by fwk@ix.netcom.com (Frank Keeney) and # rpwillia@Pentagon-EMH6.army.mil (Ray Williams) # tested on DYNIX/ptx(R) V2.1.0 # FLAGSM = -DSEQUENT -DSHADOW_PWD -DHAVE_TIMEZONE # LIBSM = -lrpc -lsocket -lPW -linet -lnsl -lseq -lsec # This is for HP-UX. Note that some systems don't like the -Aa switch. # contributed by Pasi.Kaara@atk.tpo.fi # FLAGSM = -DHPUX -Aa -D_HPUX_SOURCE -D_POSIX_SOURCE # LIBSM = # This is for HP-UX with DCE/DFS # contributed by Jim Doyle # FLAGSM = -DHPUX -Aa -D_HPUX_SOURCE -D_POSIX_SOURCE -DDFS_AUTH -D_REENTRANT -I/usr/include/reentrant # LIBSM = -ldce -lM -lc_r # This is for SGI. # contributed by lpc@solomon.technet.sg (Michael Chua) # FOR SGI IRIX 4.x.x, use the following line # FLAGSM = -DSGI -DHAVE_TIMEZONE # LIBSM = -lsun # FOR SGI IRIX 5.x.x, use this line instead #FLAGSM = -DSGI5 -DSHADOW_PWD -DHAVE_TIMEZONE #LIBSM = # This is for FreeBSD # contributed by kuku@acds.physik.rwth-aachen.de # NOTE: You may need to add -DBSD44 if you have password problems # FLAGSM = -DFreeBSD # LIBSM = -lcrypt # This is for NEXTSTEP Release 2.X # No Posix. # contributed by brad@cac.washington.edu (Brad Greer) # FLAGSM = -DNEXT2 # LIBSM = # This is for NEXTSTEP Release 3.0 and greater (including OPENSTEP for Mach). # contributed by brad@cac.washington.edu (Brad Greer) # additional configuration by pmarcos@next.com (Paul Marcos) # For compiling n-way fat executables, you should append the appropriat -arch # flags to the FLAGSM variable. Valid flags are: # -arch m68k # -arch i386 # -arch hppa # -arch sparc # To compile 4-way fat, you would append # -arch m68k -arch i386 -arch hppa -arch sparc # FLAGSM = -DNEXT3_0 # LIBSM = # NOTE: ISC is also known as "INTERACTIVE" # This is for Sunsoft ISC SVR3V4 running in POSIX mode # contributed by pim@cti-software.nl (Pim Zandbergen) # FLAGSM = -posix -D_SYSV3 -DISC -DSHADOW_PWD # LIBSM = -lsec -lcrypt -linet # This is for Sunsoft ISC SVR3V4 running in iBCS2 mode # contributed by pim@cti-software.nl (Pim Zandbergen) # FLAGSM = -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_SYSV3\ # -DISC -DSHADOW_PWD -DREPLACE_GETWD -DREPLACE_RENAME # LIBSM = -lsec -lcrypt -linet -lcposix # This is for A/UX 3.0 # Contributed by root@dolphin.csudh.edu (Jon S. Stevens) # FLAGSM = -DAUX # LIBSM = # This is for Altos Series 386/1000 # Contributed by cal@zls.com # FLAGSM = -DALTOS -DHAS_RDCHK # LIBSM = -lsocket -lxenix #Note: The SCO entries require the libcrypt library. You can get it via #anonymous ftp from ftp.sco.com:/SLS/lng225b.* or ftp.uu.net:/vendors/sco # # Use this for SCO with shadow passwords. Tested on "Open enterprise 3.0" # SCO changes from Heinz Mauelshagen (mauelsha@ez.da.telekom.de) # FLAGSM = -DSCO -DSHADOW_PWD -DNETGROUP # LIBSM = -lyp -lrpc -lyp -lsec -lsocket -lcrypt_i -lintl # Use this for SCO with shadow passwords, without YP. # Tested on "Open Enterprise Server 3.0" (John Owens john@micros.com) # Also, use "CC = cc" above. # FLAGSM = -DSCO -DSHADOW_PWD # LIBSM = -lsec -lsocket -lcrypt_i # Use this for SCO with TCB passwords (default). # Tested on "Open enterprise 3.0". Contributed by lance@fox.com. # CC = cc # FLAGSM = -DSCO -DSecureWare # LIBSM = -lprot_s -lcrypt -lsocket -lm -lc_s # Use this for SCO Unix 3.2v2 (ODT 1.1) with TCB passwords (default). # Contributed by Stephen.Rothwell@pd.necisa.oz.au # N.B. this needs gcc # FLAGSM = -DSCO -DSecureWare -DSCO3_2_2 # LIBSM = -lprot -lcrypt_i -lsocket -lm -lintl # This is for the european distribution of SCO. # Contributed by Urmet.Janes@gwhite.goodwin.ee # FLAGSM = -DSCO -DSHADOW_PWD # LIBSM = -lsec -lsocket /usr/lib/libcrypt_i.a -lintl # Use this for SCO OpenServer 5 with TCB passwords (default). # contributed by Scott Michel # CC = cc -Xc # FLAGSM = -DSCO -DSecureWare -DEVEREST -DUSE_MMAP # LIBSM = -lprot -lcurses -lcrypt -lsocket -lPW -lm -lx -lc_s -lc # This is for intergraph. # contributed by cjkiick@flinx.b11.ingr.com # modified by ttj@sknsws61.sjo.statkart.no # FLAGSM = -DCLIX -D_INGR_EXTENSIONS=1 # LIBSM = -lbsd -lc_s # This is for DGUX. # Contributed by ross@augie.insci.com (Ross Andrus) # FLAGSM = -DDGUX # LIBSM = # This is for Apollo Domain/OS sr10.3 (systype = BSD4.3) # Added 1994-07-08 Stephen C. Steel # additional patches by jmi@csd.cri.dk (John Mills) # you may need the "-A ansi" switch to cc # FLAGSM = -DAPOLLO -D_INCLUDE_BSD_SOURCE -D_INCLUDE_XOPEN_SOURCE # LIBSM = # RiscIX. # contributed by Jim Barry and # Charles Gay-Jones # FLAGSM = -DRiscIX -DNOSTRDUP # LIBSM = # This is for System V with some berkely extensions (Motorola 88k R32V3.2). # contributed by tonyb@plaza.ds.adp.com (Tony D. Birnseth) # FLAGSM = -DM88K_R3 # LIBSM = -lgen -lbsd -lnsl # This is for DNIX. # contributed by Peter Olsson # NOTE: You may need an updated libc.a from your vendor as older # versions have broken mktime calls and no initgroups() call # NOTE2: You may need -lpasswd if you use shadow passwords # NOTE3: Please read the file DNIX.txt in the docs directory. It # contains important information about uid handling under DNIX, you may # need to patch your C library. # FLAGSM = -DDNIX -I/usr/include/bsd # LIBSM = -ln # This is for Cray, Unicos 8.0 # contributed by velo@sesun3.epfl.ch (Martin Ouwehand) # FLAGSM = -DCRAY -U__STDC__ -DQUOTAS # LIBSM = # This is for Convex # contributed by Victor Balashov # and Ulrich Hahn # FLAGSM= -DCONVEX -DSHADOW_PWD # LIBSM= # This is for SMP_DC.OSx v1.1-94c079 on Pyramid S series # contributed by jeffrey@itm.org # FLAGSM = -DSOLARIS -DSHADOW_PWD -DBSD_COMP # LIBSM = -lsocket -lnsl # This is for QNX 4.22 # Contributed by eldo@invisa.satlink.net (Eldo Loguzzo) # FLAGSM = -DQNX -DGUEST_SESSSETUP=1 # LIBSM = # This is for SONY NEWS, NEWS-OS 4.2.x # contributed by sky@sm.sony.co.jp (Katushi Sato) # FLAGSM = -DNEWS42 -DKANJI=\"sjis\" # LIBSM = # This is for OS/2 using EMX 0.9b # Contributed by jasonr@pec.co.nz (Jason Rumney) # FLAGSM = -DOS2 # LIBSM = -Zexe -lsocket # This is for Cygwin32 for Windows NT and Windows 95 # Contributed by jwilkins@secnet.com (Jonathan Wilkins) # FLAGSM = -D_WIN32 # LIBSM = ###################################################################### # DON'T EDIT BELOW THIS LINE ###################################################################### SRCS = nat.c client.c util.c system.c nmb.c charset.c parse_ip.c OBJS = nat.o client.o util.o system.o nmb.o charset.o parse_ip.o CFLAGS1 = -DSTEPPING -DSCANNER -DVERBOSE CFLAGS2 = -DWORKGROUP=\"$(WORKGROUP)\" -DGUEST_ACCOUNT=\"$(GUESTACCOUNT)\" CFLAGS = $(CFLAGS1) $(CFLAGS2) $(FLAGSM) LIBS = $(LIBSM) all : nat INCLUDES = version.h local.h includes.h smb.h PROGS = nat .SUFFIXES: .SUFFIXES: .c .o .h .c.o: $(INCLUDES) @echo Compiling $*.c $(CC) $(CFLAGS) -c $*.c nat: $(OBJS) $(CC) $(CFLAGS) -o nat $(STATIC) $(OBJS) $(LIBS) clean: rm -f core *.o *~ $(PROGS) nat-1.0.orig/MD50100600000175000017500000000251306301746754014447 0ustar jfernandezjfernandezMD5 (COPYING) = 8ca43cbc842c2336e835926c2166c28b MD5 (INSTALL) = 3ca2cf5215eece3c0c8c4f2bb8710371 MD5 (Makefile) = 1565814494bd5904f79675cb076fa9c6 MD5 (README) = 6eceb76ba4cc6784f180aa6a11b738ab MD5 (byteorder.h) = b1f5a69a4a1176813e5394f58cdf858f MD5 (charset.c) = d6a206dc7e85895acf75e5ef19c94bcd MD5 (charset.h) = 43826b8f9126c48e333464a5e0e11b2a MD5 (client.c) = 216baac6163508046194b56dbec551e7 MD5 (includes.h) = bd1d7f4d4d67a636d179529d9a0ac384 MD5 (kanji.h) = b07f3df6e58099f5a97994bd683739ab MD5 (loadparm.h) = 6bc56500657f8c3b71b20af4c69e967f MD5 (local.h) = 38164f22329ee4ec7fb3e137b6123bf5 MD5 (nameserv.h) = 6e4301568767d53a4a8fa1ee2ea46430 MD5 (nat.1) = 46337fff5b3a8af61e9b09b6528ea648 MD5 (nat.1.txt) = d0f34410e91aa20c4e03c37cee785cd0 MD5 (nat.c) = 4ebbe2ec3dab5d0b41867554f3713690 MD5 (nmb.c) = 8b70a12324249a7d241986c6ec14df6b MD5 (parse_ip.c) = efb44f5262d0c9840fa6c5fab18bf241 MD5 (parse_ip.h) = 1c18d7dd2d05d1329549e062229a27b3 MD5 (passlist.txt) = 83fa766b5ea6124648aa6bb839120705 MD5 (smb.h) = 8257c1703d8f10ccd4060a3decbed191 MD5 (smbpass.h) = 63867b24984a7b94e08d40eae9c6a827 MD5 (system.c) = 244ce9fc2d5f30b0812add0bf0d60b55 MD5 (userlist.txt) = 872bf564ac381a865810914a40819c52 MD5 (util.c) = 20a16d34d8e127fb52d3dad1a181b4e1 MD5 (version.h) = ddcb66df623eb6ac50b66f385b7994c3 MD5 (vulns.h) = 46187a156216e8eca1e08ea183e0a3c0 nat-1.0.orig/INSTALL0100600000175000017500000000104106301746754015163 0ustar jfernandezjfernandez NetBIOS Auditing Tool Installation This package has been compiled and tested on the following operating systems: Solaris 2.5, Linux 2.0, FreeBSD 2.1.5, OpenBSD 2.0, BSDI 2.1, Windows NT 4.0, Windows 95 This package should also compile on almost all operating systems supported by the Samba package. That being said, the package has not been tested on other operating systems with the changes. Step 1. Modify Makefile to define which operating system this package will be compiled on. Step 2. Type 'make' nat-1.0.orig/vulns.h0100600000175000017500000000047206301746754015461 0ustar jfernandezjfernandez#define VULID_SESSIONNOPASS 16001 #define VULID_SESSIONPASS 16002 #define VULID_SERVERINFO 16003 #define VULID_SHARELIST 16004 #define VULID_BROWSELIST 16005 #define VULID_SHAREACCESS 16006 #define VULID_SHAREHIDDEN 16007 #define VULID_SHAREWRITE 16008 #define VULID_DOTDOTBUG 16009 #define VULID_NAMETABLES 16010 nat-1.0.orig/COPYING0100600000175000017500000004307606301746754015203 0ustar jfernandezjfernandez GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.