#include "includes.h"
-#if (defined(NETGROUP) && defined (AUTOMOUNT))
+#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
+#ifdef WITH_NISPLUS_HOME
+#include <rpcsvc/nis.h>
+#else
#include "rpcsvc/ypclnt.h"
#endif
+#endif
+
+#ifdef WITH_SSL
+#include <ssl.h>
+#undef Realloc /* SSLeay defines this and samba has a function of this name */
+extern SSL *ssl;
+extern int sslFd;
+#endif /* WITH_SSL */
pstring scope = "";
-int DEBUGLEVEL = 1;
+extern int DEBUGLEVEL;
BOOL passive = False;
/* 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;
*/
int case_default = CASE_LOWER;
-pstring debugf = "";
-int syslog_level;
-
/* the following control case operations - they are put here so the
client can link easily */
BOOL case_sensitive;
BOOL sam_logon_in_ssb = False;
-pstring myname = "";
-fstring myworkgroup = "";
+pstring global_myname = "";
+fstring global_myworkgroup = "";
char **my_netbios_names;
int smb_read_error = 0;
-static BOOL stdout_logging = False;
-
static char *filename_dos(char *path,char *buf);
-#if defined(SIGUSR2)
-/**************************************************************************** **
- catch a sigusr2 - decrease the debug log level.
- **************************************************************************** */
-int sig_usr2(void)
-{
- BlockSignals( True, SIGUSR2);
-
- DEBUGLEVEL--;
-
- if(DEBUGLEVEL < 0)
- DEBUGLEVEL = 0;
-
- DEBUG( 0, ( "Got SIGUSR2 set debug level to %d.\n", DEBUGLEVEL ) );
-
- BlockSignals( False, SIGUSR2);
-#ifndef DONT_REINSTALL_SIG
- signal(SIGUSR2, SIGNAL_CAST sig_usr2);
-#endif
- return(0);
-}
-#endif /* SIGUSR1 */
-
-#if defined(SIGUSR1)
-/**************************************************************************** **
- catch a sigusr1 - increase the debug log level.
- **************************************************************************** */
-int sig_usr1(void)
-{
- BlockSignals( True, SIGUSR1);
-
- DEBUGLEVEL++;
-
- if(DEBUGLEVEL > 10)
- DEBUGLEVEL = 10;
-
- DEBUG( 0, ( "Got SIGUSR1 set debug level to %d.\n", DEBUGLEVEL ) );
-
- BlockSignals( False, SIGUSR1);
-#ifndef DONT_REINSTALL_SIG
- signal(SIGUSR1, SIGNAL_CAST sig_usr1);
-#endif
- return(0);
-}
-#endif /* SIGUSR1 */
-
-
-/*******************************************************************
- 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;
-#ifdef LOG_DAEMON
- openlog(pname, LOG_PID, SYSLOG_FACILITY);
-#else /* for old systems that have no facility codes. */
- openlog(pname, LOG_PID);
-#endif
- }
-#endif
- if (interactive) {
- stdout_logging = True;
- dbf = stdout;
- }
-}
-
-
-BOOL append_log=False;
-
-
-/****************************************************************************
-reopen the log files
-****************************************************************************/
-void reopen_logs(void)
-{
- extern FILE *dbf;
- pstring fname;
-
- if (DEBUGLEVEL > 0)
- {
- strcpy(fname,debugf);
- if (lp_loaded() && (*lp_logfile()))
- strcpy(fname,lp_logfile());
-
- if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL))
- {
- int oldumask = umask(022);
- strcpy(debugf,fname);
- if (dbf) fclose(dbf);
- if (append_log)
- dbf = fopen(debugf,"a");
- else
- dbf = fopen(debugf,"w");
- if (dbf) setbuf(dbf,NULL);
- umask(oldumask);
- }
- }
- else
- {
- if (dbf)
- {
- fclose(dbf);
- dbf = NULL;
- }
- }
-}
-
-
-/*******************************************************************
-check if the log has grown too big
-********************************************************************/
-static void check_log_size(void)
-{
- static int debug_count=0;
- int maxlog;
- struct stat st;
-
- if (debug_count++ < 100 || getuid() != 0) return;
-
- maxlog = lp_max_log_size() * 1024;
- if (!dbf || maxlog <= 0) return;
-
- 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;
-}
-
-
-/*******************************************************************
-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;
- int old_errno = errno;
-
- if (stdout_logging) {
-#ifdef __STDC__
- va_start(ap, format_str);
-#else
- va_start(ap);
- format_str = va_arg(ap,char *);
-#endif
- vfprintf(dbf,format_str,ap);
- va_end(ap);
- errno = old_errno;
- return(0);
- }
-
-#ifdef SYSLOG
- if (!lp_syslog_only())
-#endif
- {
- if (!dbf) {
- int oldumask = umask(022);
- dbf = fopen(debugf,"w");
- umask(oldumask);
- if (dbf) {
- setbuf(dbf,NULL);
- } else {
- errno = old_errno;
- 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];
-
-#ifdef __STDC__
- va_start(ap, format_str);
-#else
- va_start(ap);
- format_str = va_arg(ap,char *);
-#endif
- vsprintf(msgbuf, format_str, ap);
- va_end(ap);
-
- msgbuf[255] = '\0';
- syslog(priority, "%s", msgbuf);
- }
-#endif
-
-#ifdef SYSLOG
- if (!lp_syslog_only())
-#endif
- {
-#ifdef __STDC__
- va_start(ap, format_str);
-#else
- va_start(ap);
- format_str = va_arg(ap,char *);
-#endif
- vfprintf(dbf,format_str,ap);
- va_end(ap);
- fflush(dbf);
- }
-
- check_log_size();
- errno = old_errno;
-
- return(0);
-}
/****************************************************************************
find a suitable temporary directory. The result should be copied immediately
return ret;
}
-#ifndef HAVE_MEMMOVE
-/*******************************************************************
-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<size;i++) idest[i] = isrc[i];
- } else {
- /* simplest */
- char *cdest = (char *)dest;
- char *csrc = (char *)src;
- for (i=0;i<size;i++) cdest[i] = csrc[i];
- }
- }
- else
- {
- /* must backward copy */
- if (d-s >= 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);
-}
-#endif
+/* ************************************************************************* **
+ * Duplicate a block of memory.
+ * ************************************************************************* **
+ */
+void *mem_dup( void *from, int size )
+ {
+ void *tmp;
+ tmp = malloc( size );
+ if( NULL != tmp )
+ (void)memcpy( tmp, from, size );
+ return( tmp );
+ } /* mem_dup */
/****************************************************************************
prompte a dptr (to make it recently used)
****************************************************************************/
void set_socket_options(int fd, char *options)
{
- string tok;
+ fstring tok;
while (next_token(&options,tok," \t,"))
{
****************************************************************************/
void close_sockets(void )
{
+#ifdef WITH_SSL
+ sslutil_disconnect(Client);
+#endif /* WITH_SSL */
+
close(Client);
Client = 0;
}
/****************************************************************************
determine whether we are in the specified group
****************************************************************************/
-BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups)
+BOOL in_group(gid_t group, int current_gid, int ngroups, GID_T *groups)
{
- int i;
+ int i;
- if (group == current_gid) return(True);
+ if (group == current_gid) return(True);
- for (i=0;i<ngroups;i++)
- if (group == groups[i])
- return(True);
+ for (i=0;i<ngroups;i++)
+ if (group == groups[i])
+ return(True);
- return(False);
+ return(False);
}
/****************************************************************************
{
char *d = dest;
-#if AJT
/* I don't want to get lazy with these ... */
if (!dest || !src) {
- DEBUG(0,("ERROR: NULL StrCpy() called!\n"));
- ajt_panic();
+ DEBUG(0,("ERROR: NULL StrCpy() called!\n"));
+ smb_panic("invalid StrCpy");
}
-#endif
if (!dest) return(NULL);
if (!src) {
if( '*' == In[0] )
buf[0] = '*';
else
- (void)sprintf( buf, "%-15.15s%c", In, name_type );
+ (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
/* Place the length of the first field into the output buffer. */
p[0] = 32;
********************************************************************/
char *attrib_string(int mode)
{
- static char attrstr[10];
+ static fstring attrstr;
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");
+ if (mode & aVOLID) fstrcat(attrstr,"V");
+ if (mode & aDIR) fstrcat(attrstr,"D");
+ if (mode & aARCH) fstrcat(attrstr,"A");
+ if (mode & aHIDDEN) fstrcat(attrstr,"H");
+ if (mode & aSYSTEM) fstrcat(attrstr,"S");
+ if (mode & aRONLY) fstrcat(attrstr,"R");
return(attrstr);
}
asynchronous upper to lower mapping.
*/
#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
if(lp_client_code_page() == KANJI_CODEPAGE)
{
/* Win95 treats full width ascii characters as case sensitive. */
asynchronous upper to lower mapping.
*/
#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
if(lp_client_code_page() == KANJI_CODEPAGE)
{
/* Win95 treats full width ascii characters as case sensitive. */
while (*s)
{
#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
if(lp_client_code_page() == KANJI_CODEPAGE)
{
/* Win95 treats full width ascii characters as case sensitive. */
else
#endif /* KANJI_WIN95_COMPATIBILITY */
{
- if (isupper(*s))
- *s = tolower(*s);
- s++;
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else
+ {
+ if (isupper(*s))
+ *s = tolower(*s);
+ s++;
+ }
}
}
}
while (*s)
{
#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
if(lp_client_code_page() == KANJI_CODEPAGE)
{
/* Win95 treats full width ascii characters as case sensitive. */
else
#endif /* KANJI_WIN95_COMPATIBILITY */
{
- if (islower(*s))
- *s = toupper(*s);
- s++;
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else
+ {
+ if (islower(*s))
+ *s = toupper(*s);
+ s++;
+ }
}
}
}
****************************************************************************/
void string_replace(char *s,char oldc,char newc)
{
+ int skip;
while (*s)
{
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- /* Win95 treats full width ascii characters as case sensitive. */
- if (is_shift_jis (*s))
- s += 2;
- else if (is_kana (*s))
- s++;
- else
- {
- if (oldc == *s)
- *s = newc;
- s++;
- }
- }
+ skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
else
-#endif /* KANJI_WIN95_COMPATIBILITY */
{
if (oldc == *s)
*s = newc;
if (*fname == '/')
{
pstrcpy(namecopy,fname);
- strcpy(fname,".");
- strcat(fname,namecopy);
+ pstrcpy(fname,".");
+ pstrcat(fname,namecopy);
}
}
string_replace(fname,'/','\\');
}
-
/*******************************************************************
show a smb message structure
********************************************************************/
void show_msg(char *buf)
{
- int i;
- int bcc=0;
-
- if (DEBUGLEVEL < 5) return;
+ 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)));
+ }
- 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)));
+ bcc = (int)SVAL(buf,smb_vwv+2*(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)));
+ DEBUG(5,("smb_bcc=%d\n",bcc));
- bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
- DEBUG(5,("smb_bcc=%d\n",bcc));
+ if (DEBUGLEVEL < 10) return;
- if (DEBUGLEVEL < 10) return;
+ if (DEBUGLEVEL < 50)
+ {
+ bcc = MIN(bcc, 512);
+ }
- dump_data(10, smb_buf(buf), MIN(bcc, 512));
+ dump_data(10, smb_buf(buf), bcc);
}
-
/*******************************************************************
return the length of an smb packet
********************************************************************/
*p = 0;
else
*s = 0;
- strcat(s,s1);
+ pstrcat(s,s1);
}
trim_string(s,NULL,"\\..");
if(strncmp(s, "./", 2) == 0) {
trim_string(s, "./", NULL);
if(*s == 0)
- strcpy(s,"./");
+ pstrcpy(s,"./");
}
while ((p = strstr(s,"/../")) != NULL)
*p = 0;
else
*s = 0;
- strcat(s,s1);
+ pstrcat(s,s1);
}
trim_string(s,NULL,"/..");
st.st_dev == st2.st_dev &&
(st2.st_mode & S_IFMT) == S_IFDIR)
{
- strcpy (str, ino_list[i].text);
+ pstrcpy (str, ino_list[i].text);
/* promote it for future use */
array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
return (NULL);
}
- strcpy(str,s);
+ pstrcpy(str,s);
DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
#else
pstring dir2;
pstring wd;
- pstring basename;
+ pstring base_name;
pstring newname;
char *p=NULL;
BOOL relative = (*s != '/');
- *dir2 = *wd = *basename = *newname = 0;
+ *dir2 = *wd = *base_name = *newname = 0;
if (widelinks)
{
}
if (strlen(s) == 0)
- strcpy(s,"./");
+ pstrcpy(s,"./");
return(True);
}
/* remove any double slashes */
string_sub(s,"//","/");
- pstrcpy(basename,s);
- p = strrchr(basename,'/');
+ pstrcpy(base_name,s);
+ p = strrchr(base_name,'/');
if (!p)
return(True);
}
- if (p && (p != basename))
+ if (p && (p != base_name))
{
*p = 0;
if (strcmp(p+1,".")==0)
*p = '/';
}
- if (ChDir(basename) != 0)
+ if (ChDir(base_name) != 0)
{
ChDir(wd);
- DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename));
+ DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
return(False);
}
return(False);
}
- if (p && (p != basename))
+ if (p && (p != base_name))
{
- strcat(newname,"/");
- strcat(newname,p+1);
+ pstrcat(newname,"/");
+ pstrcat(newname,p+1);
}
{
ChDir(wd);
if (strlen(s) == 0)
- strcpy(s,"./");
+ pstrcpy(s,"./");
DEBUG(3,("reduced to %s\n",s));
return(True);
}
else
{
- strcpy(mext,"");
+ pstrcpy(mext,"");
if (strlen(mbeg) > 8)
{
pstrcpy(mext,mbeg + 8);
}
if (*mbeg == 0)
- strcpy(mbeg,"????????");
+ pstrcpy(mbeg,"????????");
if ((*mext == 0) && doext && !hasdot)
- strcpy(mext,"???");
+ pstrcpy(mext,"???");
if (strequal(mbeg,"*") && *mext==0)
- strcpy(mext,"*");
+ pstrcpy(mext,"*");
/* expand *'s */
expand_one(mbeg,8);
expand_one(mext,3);
pstrcpy(Mask,dirpart);
- if (*dirpart || absolute) strcat(Mask,"\\");
- strcat(Mask,mbeg);
- strcat(Mask,".");
- strcat(Mask,mext);
+ if (*dirpart || absolute) pstrcat(Mask,"\\");
+ pstrcat(Mask,mbeg);
+ pstrcat(Mask,".");
+ pstrcat(Mask,mext);
DEBUG(6,("Mask expanded to [%s]\n",Mask));
}
while (*s)
{
#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
if(lp_client_code_page() == KANJI_CODEPAGE)
{
/* Win95 treats full width ascii characters as case sensitive. */
else
#endif /* KANJI_WIN95_COMPATIBILITY */
{
- if (isupper(*s))
- return(True);
- s++;
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else {
+ if (isupper(*s))
+ return(True);
+ s++;
+ }
}
}
return(False);
while (*s)
{
#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
if(lp_client_code_page() == KANJI_CODEPAGE)
{
/* Win95 treats full width ascii characters as case sensitive. */
else
#endif /* KANJI_WIN95_COMPATIBILITY */
{
- if (islower(*s))
- return(True);
- s++;
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else {
+ if (islower(*s))
+ return(True);
+ s++;
+ }
}
}
return(False);
int count=0;
#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
if(lp_client_code_page() == KANJI_CODEPAGE)
{
/* Win95 treats full width ascii characters as case sensitive. */
{
while (*s)
{
- if (*s == c)
- count++;
- s++;
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else {
+ if (*s == c)
+ count++;
+ s++;
+ }
}
}
return(count);
int read_udp_socket(int fd,char *buf,int len)
{
int ret;
- struct sockaddr sock;
+ struct sockaddr_in sock;
int socklen;
socklen = sizeof(sock);
bzero((char *)&sock,socklen);
bzero((char *)&lastip,sizeof(lastip));
- ret = recvfrom(fd,buf,len,0,&sock,&socklen);
+ ret = recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen);
if (ret <= 0) {
DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
return(0);
}
- lastip = *(struct in_addr *) &sock.sa_data[2];
- lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
+ lastip = sock.sin_addr;
+ lastport = ntohs(sock.sin_port);
DEBUG(10,("read_udp_socket: lastip %s lastport %d read: %d\n",
inet_ntoa(lastip), lastport, ret));
if (mincnt == 0) mincnt = maxcnt;
while (nread < mincnt) {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ readret = SSL_read(ssl, buf + nread, maxcnt - nread);
+ }else{
+ readret = read(fd, buf + nread, maxcnt - nread);
+ }
+#else /* WITH_SSL */
readret = read(fd, buf + nread, maxcnt - nread);
+#endif /* WITH_SSL */
+
if (readret == 0) {
smb_read_error = READ_EOF;
return -1;
return -1;
}
- readret = read(fd, buf+nread, maxcnt-nread);
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ readret = SSL_read(ssl, buf + nread, maxcnt - nread);
+ }else{
+ readret = read(fd, buf + nread, maxcnt - nread);
+ }
+#else /* WITH_SSL */
+ readret = read(fd, buf+nread, maxcnt-nread);
+#endif /* WITH_SSL */
+
if (readret == 0) {
/* we got EOF on the file descriptor */
smb_read_error = READ_EOF;
smb_read_error = 0;
while (total < N)
- {
+ {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ ret = SSL_read(ssl, buffer + total, N - total);
+ }else{
ret = read(fd,buffer + total,N - total);
- if (ret == 0) {
- smb_read_error = READ_EOF;
- return 0;
- }
- if (ret == -1) {
- smb_read_error = READ_ERROR;
- return -1;
- }
- total += ret;
}
+#else /* WITH_SSL */
+ ret = read(fd,buffer + total,N - total);
+#endif /* WITH_SSL */
+
+ if (ret == 0)
+ {
+ smb_read_error = READ_EOF;
+ return 0;
+ }
+ if (ret == -1)
+ {
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+ total += ret;
+ }
return total;
}
int ret;
while (total < N)
- {
+ {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ ret = SSL_write(ssl,buffer + total,N - total);
+ }else{
ret = write(fd,buffer + total,N - total);
+ }
+#else /* WITH_SSL */
+ ret = write(fd,buffer + total,N - total);
+#endif /* WITH_SSL */
- if (ret == -1) return -1;
- if (ret == 0) return total;
+ if (ret == -1) return -1;
+ if (ret == 0) return total;
- total += ret;
- }
+ total += ret;
+ }
return total;
}
int fromlen = sizeof(from);
int32 msg_len = 0;
+ smb_read_error = 0;
+
if(timeout != 0)
{
struct timeval to;
for processing.
****************************************************************************/
-typedef struct _message_list {
- struct _message_list *msg_next;
+typedef struct {
+ ubi_slNode msg_next;
char *msg_buf;
int msg_len;
} pending_message_list;
-static pending_message_list *smb_msg_head = NULL;
+static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
/****************************************************************************
- Function to push a linked list of local messages ready
+ Function to push a message onto the tail of a linked list of smb messages ready
for processing.
****************************************************************************/
-static BOOL push_local_message(pending_message_list **pml, char *buf, int msg_len)
+static BOOL push_local_message(ubi_slList *list_head, char *buf, int msg_len)
{
pending_message_list *msg = (pending_message_list *)
malloc(sizeof(pending_message_list));
if(msg == NULL)
{
- DEBUG(0,("push_message: malloc fail (1)\n"));
+ DEBUG(0,("push_local_message: malloc fail (1)\n"));
return False;
}
memcpy(msg->msg_buf, buf, msg_len);
msg->msg_len = msg_len;
- msg->msg_next = *pml;
- *pml = msg;
+ ubi_slAddTail( list_head, msg);
return True;
}
/****************************************************************************
- Function to push a linked list of local smb messages ready
+ Function to push a smb message onto a linked list of local smb messages ready
for processing.
****************************************************************************/
-BOOL push_smb_message(char *buf, int msg_len)
+BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
{
- return push_local_message(&smb_msg_head, buf, msg_len);
+ return push_local_message(&smb_oplock_queue, buf, msg_len);
}
/****************************************************************************
int selrtn;
struct timeval to;
+ smb_read_error = 0;
+
*got_smb = False;
/*
* If so - copy and return it.
*/
- if(smb_msg_head)
+ if(ubi_slCount(&smb_oplock_queue) != 0)
{
- pending_message_list *msg = smb_msg_head;
+ pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
- smb_msg_head = msg->msg_next;
/* Free the message we just copied. */
free((char *)msg->msg_buf);
{
char *p = name_ptr(buf,ofs);
int d = PTR_DIFF(p,buf+ofs);
- strcpy(name,"");
+ pstrcpy(name,"");
if (d < -50 || d > 50) return(0);
return(name_interpret(p,name));
}
return False;
}
- strcpy(*dest,src);
+ pstrcpy(*dest,src);
}
return(True);
}
return(ret);
}
-
-
/*********************************************************
-* Recursive routine that is called by mask_match.
-* Does the actual matching.
+* Recursive routine that is called by unix_mask_match.
+* Does the actual matching. This is the 'original code'
+* used by the unix matcher.
*********************************************************/
-BOOL do_match(char *str, char *regexp, int case_sig)
+static BOOL unix_do_match(char *str, char *regexp, int case_sig)
{
char *p;
while(*str) {
while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
str++;
- if(do_match(str,p,case_sig))
+ if(unix_do_match(str,p,case_sig))
return True;
if(!*str)
return False;
* Routine to match a given string with a regexp - uses
* simplified regexp that takes * and ? only. Case can be
* significant or not.
+* This is the 'original code' used by the unix matcher.
*********************************************************/
-BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
+
+static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
{
char *p;
pstring p1, p2;
StrnCpy(p2,str,sizeof(pstring)-1);
if (!strchr(p2,'.')) {
- strcat(p2,".");
- }
-
-/*
- if (!strchr(p1,'.')) {
- strcat(p1,".");
+ pstrcat(p2,".");
}
-*/
-
-#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]);
+ (void)pstrcpy( &p[1], &p[2]);
if (strequal(p1,"*")) return(True);
- DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
+ DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
if (trans2) {
fstrcpy(ebase,p1);
}
}
- matched = do_match(sbase,ebase,case_sig) &&
- (trans2 || do_match(sext,eext,case_sig));
+ matched = unix_do_match(sbase,ebase,case_sig) &&
+ (trans2 || unix_do_match(sext,eext,case_sig));
- DEBUG(8,("mask_match returning %d\n", matched));
+ DEBUG(8,("unix_mask_match returning %d\n", matched));
return matched;
}
+/*********************************************************
+* Recursive routine that is called by mask_match.
+* Does the actual matching. Returns True if matched,
+* False if failed. This is the 'new' NT style matcher.
+*********************************************************/
-
-/****************************************************************************
-become a daemon, discarding the controlling terminal
-****************************************************************************/
-void become_daemon(void)
+BOOL do_match(char *str, char *regexp, int case_sig)
{
-#ifndef NO_FORK_DEBUG
- if (fork())
- exit(0);
+ char *p;
- /* detach from the terminal */
-#ifdef USE_SETSID
- setsid();
-#else /* USE_SETSID */
-#ifdef TIOCNOTTY
- {
- int i = open("/dev/tty", O_RDWR);
- if (i >= 0)
- {
- ioctl(i, (int) TIOCNOTTY, (char *)0);
- close(i);
+ 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++;
+ /* Now eat all characters that match, as
+ we want the *last* character to match. */
+ while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
+ str++;
+ str--; /* We've eaten the match char after the '*' */
+ 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;
+ }
}
-#endif /* TIOCNOTTY */
-#endif /* USE_SETSID */
- /* Close fd's 0,1,2. Needed if started by rsh */
- close_low_fds();
-#endif /* NO_FORK_DEBUG */
+
+ 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.
+* The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
+* This is the new 'NT style' matcher.
+*********************************************************/
+
+BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
+{
+ char *p;
+ pstring t_pattern, t_filename, te_pattern, te_filename;
+ fstring ebase,eext,sbase,sext;
+
+ BOOL matched = False;
+
+ /* Make local copies of str and regexp */
+ pstrcpy(t_pattern,regexp);
+ pstrcpy(t_filename,str);
+
+#if 0
+ /*
+ * Not sure if this is a good idea. JRA.
+ */
+ if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
+ trans2 = False;
+#endif
+
+#if 0
+ if (!strchr(t_filename,'.')) {
+ pstrcat(t_filename,".");
+ }
+#endif
+
+ /* Remove any *? and ** as they are meaningless */
+ string_sub(t_pattern, "*?", "*");
+ string_sub(t_pattern, "**", "*");
+
+ if (strequal(t_pattern,"*"))
+ return(True);
+
+ DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
+
+ if(trans2) {
+ /*
+ * Match each component of the regexp, split up by '.'
+ * characters.
+ */
+ char *fp, *rp, *cp2, *cp1;
+ BOOL last_wcard_was_star = False;
+ int num_path_components, num_regexp_components;
+
+ pstrcpy(te_pattern,t_pattern);
+ pstrcpy(te_filename,t_filename);
+ /*
+ * Remove multiple "*." patterns.
+ */
+ string_sub(te_pattern, "*.*.", "*.");
+ num_regexp_components = count_chars(te_pattern, '.');
+ num_path_components = count_chars(te_filename, '.');
+
+ /*
+ * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
+ */
+ if(num_regexp_components == 0)
+ matched = do_match( te_filename, te_pattern, case_sig);
+ else {
+ for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
+ fp = strchr(cp2, '.');
+ if(fp)
+ *fp = '\0';
+ rp = strchr(cp1, '.');
+ if(rp)
+ *rp = '\0';
+
+ if(cp1[strlen(cp1)-1] == '*')
+ last_wcard_was_star = True;
+ else
+ last_wcard_was_star = False;
+
+ if(!do_match(cp2, cp1, case_sig))
+ break;
+
+ cp1 = rp ? rp + 1 : NULL;
+ cp2 = fp ? fp + 1 : "";
+
+ if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
+ /* Eat the extra path components. */
+ int i;
+
+ for(i = 0; i < num_path_components - num_regexp_components; i++) {
+ fp = strchr(cp2, '.');
+ if(fp)
+ *fp = '\0';
+
+ if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) {
+ cp2 = fp ? fp + 1 : "";
+ break;
+ }
+ cp2 = fp ? fp + 1 : "";
+ }
+ num_path_components -= i;
+ }
+ }
+ if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
+ matched = True;
+ }
+ } else {
+
+ /* -------------------------------------------------
+ * Behaviour of Win95
+ * for 8.3 filenames and 8.3 Wildcards
+ * -------------------------------------------------
+ */
+ if (strequal (t_filename, ".")) {
+ /*
+ * Patterns: *.* *. ?. ? are valid
+ *
+ */
+ if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
+ strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
+ matched = True;
+ } else if (strequal (t_filename, "..")) {
+ /*
+ * Patterns: *.* *. ?. ? *.? are valid
+ *
+ */
+ if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
+ strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
+ strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
+ matched = True;
+ } else {
+
+ if ((p = strrchr (t_pattern, '.'))) {
+ /*
+ * Wildcard has a suffix.
+ */
+ *p = 0;
+ fstrcpy (ebase, t_pattern);
+ if (p[1]) {
+ fstrcpy (eext, p + 1);
+ } else {
+ /* pattern ends in DOT: treat as if there is no DOT */
+ *eext = 0;
+ if (strequal (ebase, "*"))
+ return (True);
+ }
+ } else {
+ /*
+ * No suffix for wildcard.
+ */
+ fstrcpy (ebase, t_pattern);
+ eext[0] = 0;
+ }
+
+ p = strrchr (t_filename, '.');
+ if (p && (p[1] == 0) ) {
+ /*
+ * Filename has an extension of '.' only.
+ */
+ *p = 0; /* nuke dot at end of string */
+ p = 0; /* and treat it as if there is no extension */
+ }
+
+ if (p) {
+ /*
+ * Filename has an extension.
+ */
+ *p = 0;
+ fstrcpy (sbase, t_filename);
+ fstrcpy (sext, p + 1);
+ if (*eext) {
+ matched = do_match(sbase, ebase, case_sig)
+ && do_match(sext, eext, case_sig);
+ } else {
+ /* pattern has no extension */
+ /* Really: match complete filename with pattern ??? means exactly 3 chars */
+ matched = do_match(str, ebase, case_sig);
+ }
+ } else {
+ /*
+ * Filename has no extension.
+ */
+ fstrcpy (sbase, t_filename);
+ fstrcpy (sext, "");
+ if (*eext) {
+ /* pattern has extension */
+ matched = do_match(sbase, ebase, case_sig)
+ && do_match(sext, eext, case_sig);
+ } else {
+ matched = do_match(sbase, ebase, case_sig);
+#ifdef EMULATE_WEIRD_W95_MATCHING
+ /*
+ * Even Microsoft has some problems
+ * Behaviour Win95 -> local disk
+ * is different from Win95 -> smb drive from Nt 4.0
+ * This branch would reflect the Win95 local disk behaviour
+ */
+ if (!matched) {
+ /* a? matches aa and a in w95 */
+ fstrcat (sbase, ".");
+ matched = do_match(sbase, ebase, case_sig);
+ }
+#endif
+ }
+ }
+ }
+ }
+
+ DEBUG(8,("mask_match returning %d\n", matched));
+
+ return matched;
+}
+
+/****************************************************************************
+become a daemon, discarding the controlling terminal
+****************************************************************************/
+void become_daemon(void)
+{
+ if (fork()) {
+ _exit(0);
+ }
+
+ /* detach from the terminal */
+#ifdef HAVE_SETSID
+ setsid();
+#elif defined(TIOCNOTTY)
+ {
+ int i = open("/dev/tty", O_RDWR);
+ if (i != -1) {
+ ioctl(i, (int) TIOCNOTTY, (char *)0);
+ close(i);
+ }
+ }
+#endif /* HAVE_SETSID */
+
+ /* Close fd's 0,1,2. Needed if started by rsh */
+ close_low_fds();
}
extend a file with ftruncate. Provide alternate implementation
for this */
-#if FTRUNCATE_CAN_EXTEND
+#ifdef HAVE_FTRUNCATE_EXTEND
return ftruncate(fd, len);
#else
struct stat st;
char *p = strrchr(path,'\\');
if (!p)
- strcpy(buf,path);
+ pstrcpy(buf,path);
else
{
*p = 0;
- strcpy(buf,path);
+ pstrcpy(buf,path);
*p = '\\';
}
char *p = strrchr(path,'\\');
if (!p)
- strcpy(buf,path);
+ pstrcpy(buf,path);
else
- strcpy(buf,p+1);
+ pstrcpy(buf,p+1);
return(buf);
}
return(ret);
}
-#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
-
/****************************************************************************
Signal handler for SIGPIPE (write on a disconnected socket)
/* get host info */
if ((hp = Get_Hostbyname(hostname)) == 0)
{
- DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
+ DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
return False;
}
/* get host info */
if ((hp = Get_Hostbyname(host_name)) == 0)
{
- DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
+ 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__) /* XXX not the right ifdef */
+
+#ifdef HAVE_SOCK_SIN_LEN
sock.sin_len = sizeof(sock);
#endif
sock.sin_port = htons( port );
if (ret < 0) {
DEBUG(1,("error connecting to %s:%d (%s)\n",
inet_ntoa(*addr),port,strerror(errno)));
+ close(res);
return -1;
}
if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
for (i=0; pure_address && str[i]; i++)
- if (!(isdigit(str[i]) || str[i] == '.'))
+ if (!(isdigit((int)str[i]) || str[i] == '.'))
pure_address = False;
/* if it's in the form of an IP address then get the lib to interpret it */
return 0;
}
if(hp->h_addr == NULL) {
- DEBUG(3,("Get_Hostbyname: host address is invalid for host %s.\n",str));
+ DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
return 0;
}
putip((char *)&res,(char *)hp->h_addr);
static BOOL global_client_name_done = False;
static BOOL global_client_addr_done = False;
-void reset_globals_after_fork()
+void reset_globals_after_fork(void)
{
global_client_name_done = False;
global_client_addr_done = False;
+
+ /*
+ * Re-seed the random crypto generator, so all smbd's
+ * started from the same parent won't generate the same
+ * sequence.
+ */
+ {
+ unsigned char dummy;
+ generate_random_buffer( &dummy, 1, True);
+ }
}
/*******************************************************************
return the DNS name of the client
******************************************************************/
-char *client_name(void)
+char *client_name(int fd)
+{
+ struct sockaddr sa;
+ struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+ int length = sizeof(sa);
+ static pstring name_buf;
+ struct hostent *hp;
+ static int last_fd=-1;
+
+ if (global_client_name_done && last_fd == fd)
+ return name_buf;
+
+ last_fd = fd;
+ global_client_name_done = False;
+
+ pstrcpy(name_buf,"UNKNOWN");
+
+ if (fd == -1) {
+ return name_buf;
+ }
+
+ if (getpeername(fd, &sa, &length) < 0) {
+ DEBUG(0,("getpeername failed\n"));
+ return name_buf;
+ }
+
+ /* Look up the remote host name. */
+ if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
+ sizeof(sockin->sin_addr),
+ AF_INET)) == 0) {
+ DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr(fd)));
+ StrnCpy(name_buf,client_addr(fd),sizeof(name_buf) - 1);
+ } else {
+ StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
+ if (!matchname(name_buf, sockin->sin_addr)) {
+ DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr(fd)));
+ pstrcpy(name_buf,"UNKNOWN");
+ }
+ }
+ global_client_name_done = True;
+ return name_buf;
+}
+
+/*******************************************************************
+ return the IP addr of the client as a string
+ ******************************************************************/
+char *client_addr(int fd)
{
- extern int Client;
- struct sockaddr sa;
- struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
- int length = sizeof(sa);
- static pstring name_buf;
- struct hostent *hp;
+ struct sockaddr sa;
+ struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+ int length = sizeof(sa);
+ static fstring addr_buf;
+ static int last_fd = -1;
- if (global_client_name_done)
- return name_buf;
+ if (global_client_addr_done && fd == last_fd)
+ return addr_buf;
- strcpy(name_buf,"UNKNOWN");
+ last_fd = fd;
+ global_client_addr_done = False;
- if (Client == -1) {
- return name_buf;
- }
+ fstrcpy(addr_buf,"0.0.0.0");
- if (getpeername(Client, &sa, &length) < 0) {
- DEBUG(0,("getpeername failed\n"));
- return name_buf;
- }
+ if (fd == -1) {
+ return addr_buf;
+ }
+
+ if (getpeername(fd, &sa, &length) < 0) {
+ DEBUG(0,("getpeername failed\n"));
+ return addr_buf;
+ }
+
+ fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
+
+ global_client_addr_done = True;
+ return addr_buf;
+}
- /* Look up the remote host name. */
- if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
- sizeof(sockin->sin_addr),
- AF_INET)) == 0) {
- DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr()));
- StrnCpy(name_buf,client_addr(),sizeof(name_buf) - 1);
- } else {
- StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
- if (!matchname(name_buf, sockin->sin_addr)) {
- DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr()));
- strcpy(name_buf,"UNKNOWN");
+#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
+/******************************************************************
+ Remove any mount options such as -rsize=2048,wsize=2048 etc.
+ Based on a fix from <Thomas.Hepper@icem.de>.
+*******************************************************************/
+
+static void strip_mount_options( pstring *str)
+{
+ if (**str == '-')
+ {
+ char *p = *str;
+ while(*p && !isspace(*p))
+ p++;
+ while(*p && isspace(*p))
+ p++;
+ if(*p) {
+ pstring tmp_str;
+
+ pstrcpy(tmp_str, p);
+ pstrcpy(*str, tmp_str);
}
}
- global_client_name_done = True;
- return name_buf;
}
/*******************************************************************
- return the IP addr of the client as a string
- ******************************************************************/
-char *client_addr(void)
+ Patch from jkf@soton.ac.uk
+ Split Luke's automount_server into YP lookup and string splitter
+ so can easily implement automount_path().
+ As we may end up doing both, cache the last YP result.
+*******************************************************************/
+
+#ifdef WITH_NISPLUS_HOME
+static char *automount_lookup(char *user_name)
{
- extern int Client;
- struct sockaddr sa;
- struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
- int length = sizeof(sa);
- static fstring addr_buf;
+ static fstring last_key = "";
+ static pstring last_value = "";
+
+ char *nis_map = (char *)lp_nis_home_map_name();
+
+ char nis_domain[NIS_MAXNAMELEN + 1];
+ char buffer[NIS_MAXATTRVAL + 1];
+ nis_result *result;
+ nis_object *object;
+ entry_obj *entry;
+
+ strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
+ nis_domain[NIS_MAXNAMELEN] = '\0';
+
+ DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
+
+ if (strcmp(user_name, last_key))
+ {
+ slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
+ DEBUG(5, ("NIS+ querystring: %s\n", buffer));
+
+ if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
+ {
+ if (result->status != NIS_SUCCESS)
+ {
+ DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
+ fstrcpy(last_key, ""); pstrcpy(last_value, "");
+ }
+ else
+ {
+ object = result->objects.objects_val;
+ if (object->zo_data.zo_type == ENTRY_OBJ)
+ {
+ entry = &object->zo_data.objdata_u.en_data;
+ DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
+ DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
+
+ pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
+ string_sub(last_value, "&", user_name);
+ fstrcpy(last_key, user_name);
+ }
+ }
+ }
+ nis_freeresult(result);
+ }
- if (global_client_addr_done)
- return addr_buf;
+ strip_mount_options(&last_value);
- strcpy(addr_buf,"0.0.0.0");
+ DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
+ return last_value;
+}
+#else /* WITH_NISPLUS_HOME */
+static char *automount_lookup(char *user_name)
+{
+ static fstring last_key = "";
+ static pstring last_value = "";
+
+ int nis_error; /* returned by yp all functions */
+ char *nis_result; /* yp_match inits this */
+ int nis_result_len; /* and set this */
+ char *nis_domain; /* yp_get_default_domain inits this */
+ char *nis_map = (char *)lp_nis_home_map_name();
- if (Client == -1) {
- return addr_buf;
+ if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
+ {
+ DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
+ return last_value;
}
- if (getpeername(Client, &sa, &length) < 0) {
- DEBUG(0,("getpeername failed\n"));
- return addr_buf;
+ DEBUG(5, ("NIS Domain: %s\n", nis_domain));
+
+ if (!strcmp(user_name, last_key))
+ {
+ nis_result = last_value;
+ nis_result_len = strlen(last_value);
+ nis_error = 0;
+ }
+ else
+ {
+ if ((nis_error = yp_match(nis_domain, nis_map,
+ user_name, strlen(user_name),
+ &nis_result, &nis_result_len)) != 0)
+ {
+ DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
+ yperr_string(nis_error), user_name, nis_map));
+ }
+ if (!nis_error && nis_result_len >= sizeof(pstring))
+ {
+ nis_result_len = sizeof(pstring)-1;
+ }
+ fstrcpy(last_key, user_name);
+ strncpy(last_value, nis_result, nis_result_len);
+ last_value[nis_result_len] = '\0';
}
- fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
+ strip_mount_options(&last_value);
- global_client_addr_done = True;
- return addr_buf;
+ DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
+ return last_value;
}
+#endif /* WITH_NISPLUS_HOME */
+#endif
+
+/*******************************************************************
+ Patch from jkf@soton.ac.uk
+ This is Luke's original function with the NIS lookup code
+ moved out to a separate function.
+*******************************************************************/
char *automount_server(char *user_name)
{
static pstring server_name;
-#if (defined(NETGROUP) && defined (AUTOMOUNT))
- int nis_error; /* returned by yp all functions */
- char *nis_result; /* yp_match inits this */
- int nis_result_len; /* and set this */
- char *nis_domain; /* yp_get_default_domain inits this */
- char *nis_map = (char *)lp_nis_home_map_name();
- int home_server_len;
-
- /* set to default of local machine */
+ /* use the local machine name as the default */
+ /* this will be the default if WITH_AUTOMOUNT is not used or fails */
pstrcpy(server_name, local_machine);
- if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
- {
- DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
- }
-
- DEBUG(5, ("NIS Domain: %s\n", nis_domain));
+#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
- if ((nis_error = yp_match(nis_domain, nis_map,
- user_name, strlen(user_name),
- &nis_result, &nis_result_len)) != 0)
+ if (lp_nis_home_map())
{
- DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
- }
-
- if (!nis_error && lp_nis_home_map())
- {
- home_server_len = strcspn(nis_result,":");
+ int home_server_len;
+ char *automount_value = automount_lookup(user_name);
+ home_server_len = strcspn(automount_value,":");
DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
if (home_server_len > sizeof(pstring))
{
home_server_len = sizeof(pstring);
}
- strncpy(server_name, nis_result, home_server_len);
+ strncpy(server_name, automount_value, home_server_len);
server_name[home_server_len] = '\0';
}
-#else
- /* use the local machine name instead of the auto-map server */
- pstrcpy(server_name, local_machine);
#endif
DEBUG(4,("Home server: %s\n", server_name));
return server_name;
}
+/*******************************************************************
+ Patch from jkf@soton.ac.uk
+ Added this to implement %p (NIS auto-map version of %H)
+*******************************************************************/
+
+char *automount_path(char *user_name)
+{
+ static pstring server_path;
+
+ /* use the passwd entry as the default */
+ /* this will be the default if WITH_AUTOMOUNT is not used or fails */
+ /* pstrcpy() copes with get_home_dir() returning NULL */
+ pstrcpy(server_path, get_home_dir(user_name));
+
+#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
+
+ if (lp_nis_home_map())
+ {
+ char *home_path_start;
+ char *automount_value = automount_lookup(user_name);
+ home_path_start = strchr(automount_value,':');
+ if (home_path_start != NULL)
+ {
+ DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
+ home_path_start?(home_path_start+1):""));
+ pstrcpy(server_path, home_path_start+1);
+ }
+ }
+#endif
+
+ DEBUG(4,("Home server path: %s\n", server_path));
+
+ return server_path;
+}
+
+
/*******************************************************************
sub strings with useful parameters
Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
{
case 'G' :
{
- if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL)
+ if ((pass = Get_Pwnam(username,False))!=NULL)
{
string_sub(p,"%G",gidtoname(pass->pw_gid));
}
break;
}
case 'N' : string_sub(p,"%N", automount_server(username)); break;
- case 'I' : string_sub(p,"%I", client_addr()); break;
+ case 'I' : string_sub(p,"%I", client_addr(Client)); break;
case 'L' : string_sub(p,"%L", local_machine); break;
- case 'M' : string_sub(p,"%M", client_name()); break;
+ case 'M' : string_sub(p,"%M", client_name(Client)); break;
case 'R' : string_sub(p,"%R", remote_proto); break;
case 'T' : string_sub(p,"%T", timestring()); break;
case 'U' : string_sub(p,"%U", username); break;
case 'a' : string_sub(p,"%a", remote_arch); break;
case 'd' :
{
- sprintf(pidstr,"%d",(int)getpid());
+ slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
string_sub(p,"%d", pidstr);
break;
}
case 'h' : string_sub(p,"%h", myhostname); break;
case 'm' : string_sub(p,"%m", remote_machine); break;
case 'v' : string_sub(p,"%v", VERSION); break;
- case '$' : /* Expand environment variables */
- {
- /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
- fstring envname;
- char *envval;
- char *q, *r;
- int copylen;
-
- if (*(p+2) != '(') { p+=2; break; }
- if ((q = strchr(p,')')) == NULL)
- {
- DEBUG(0,("standard_sub_basic: Unterminated environment \
-variable [%s]\n", p));
- p+=2; break;
- }
-
- r = p+3;
- copylen = MIN((q-r),(sizeof(envname)-1));
- strncpy(envname,r,copylen);
- envname[copylen] = '\0';
- if ((envval = getenv(envname)) == NULL)
- {
- DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
- envname));
- p+=2; break;
- }
- copylen = MIN((q+1-p),(sizeof(envname)-1));
- strncpy(envname,p,copylen);
- envname[copylen] = '\0';
- string_sub(p,envname,envval);
- break;
- }
+ case '$' : /* Expand environment variables */
+ {
+ /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
+ fstring envname;
+ char *envval;
+ char *q, *r;
+ int copylen;
+
+ if (*(p+2) != '(')
+ {
+ p+=2;
+ break;
+ }
+ if ((q = strchr(p,')')) == NULL)
+ {
+ DEBUG(0,("standard_sub_basic: Unterminated environment \
+ variable [%s]\n", p));
+ p+=2;
+ break;
+ }
+
+ r = p+3;
+ copylen = MIN((q-r),(sizeof(envname)-1));
+ strncpy(envname,r,copylen);
+ envname[copylen] = '\0';
+
+ if ((envval = getenv(envname)) == NULL)
+ {
+ DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
+ envname));
+ p+=2;
+ break;
+ }
+
+ copylen = MIN((q+1-p),(sizeof(envname)-1));
+ strncpy(envname,p,copylen);
+ envname[copylen] = '\0';
+ string_sub(p,envname,envval);
+ break;
+ }
case '\0': p++; break; /* don't run off end if last character is % */
default : p+=2; break;
}
return;
}
+
+/****************************************************************************
+do some standard substitutions in a string
+****************************************************************************/
+void standard_sub(connection_struct *conn,char *str)
+{
+ char *p, *s, *home;
+
+ for (s=str; (p=strchr(s, '%'));s=p) {
+ switch (*(p+1)) {
+ case 'H':
+ if ((home = get_home_dir(conn->user))) {
+ string_sub(p,"%H",home);
+ } else {
+ p += 2;
+ }
+ break;
+
+ case 'P':
+ string_sub(p,"%P",conn->connectpath);
+ break;
+
+ case 'S':
+ string_sub(p,"%S",
+ lp_servicename(SNUM(conn)));
+ break;
+
+ case 'g':
+ string_sub(p,"%g",
+ gidtoname(conn->gid));
+ break;
+ case 'u':
+ string_sub(p,"%u",conn->user);
+ break;
+
+ /* Patch from jkf@soton.ac.uk Left the %N (NIS
+ * server name) in standard_sub_basic as it is
+ * a feature for logon servers, hence uses the
+ * username. The %p (NIS server path) code is
+ * here as it is used instead of the default
+ * "path =" string in [homes] and so needs the
+ * service name, not the username. */
+ case 'p':
+ string_sub(p,"%p",
+ automount_path(lp_servicename(SNUM(conn))));
+ break;
+ case '\0':
+ p++;
+ break; /* don't run off the end of the string
+ */
+
+ default: p+=2;
+ break;
+ }
+ }
+
+ standard_sub_basic(str);
+}
+
+
+
/*******************************************************************
are two IPs on the same subnet?
********************************************************************/
exit(0);
}
+
+ /*
+ * This next test is redundent and causes some systems (with
+ * broken isalnum() calls) problems.
+ * JRA.
+ */
+
+#if 0
if (!isalnum(*name2))
{
free(name2);
return(NULL);
}
+#endif /* 0 */
ret = sys_gethostbyname(name2);
if (ret != NULL)
static char name[40];
struct passwd *pass = getpwuid(uid);
if (pass) return(pass->pw_name);
- sprintf(name,"%d",uid);
+ slprintf(name, sizeof(name) - 1, "%d",uid);
return(name);
}
********************************************************************/
char *gidtoname(int gid)
{
- static char name[40];
- struct group *grp = getgrgid(gid);
- if (grp) return(grp->gr_name);
- sprintf(name,"%d",gid);
- return(name);
-}
-
-/*******************************************************************
-block sigs
-********************************************************************/
-void BlockSignals(BOOL block,int signum)
-{
-#ifdef USE_SIGBLOCK
- int block_mask = sigmask(signum);
- static int oldmask = 0;
- if (block)
- oldmask = sigblock(block_mask);
- else
- sigsetmask(oldmask);
-#elif defined(USE_SIGPROCMASK)
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set,signum);
- sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL);
-#endif
+ static char name[40];
+ struct group *grp = getgrgid(gid);
+ if (grp) return(grp->gr_name);
+ slprintf(name,sizeof(name) - 1, "%d",gid);
+ return(name);
}
-#if AJT
/*******************************************************************
-my own panic function - not suitable for general use
+something really nasty happened - panic!
********************************************************************/
-void ajt_panic(void)
+void smb_panic(char *why)
{
- system("/usr/bin/X11/xedit -display solen:0 /tmp/ERROR_FAULT");
+ char *cmd = lp_panic_action();
+ if (cmd && *cmd) {
+ system(cmd);
+ exit(1);
+ }
}
-#endif
-#ifdef USE_DIRECT
-#define DIRECT direct
-#else
-#define DIRECT dirent
-#endif
/*******************************************************************
a readdir wrapper which just returns the file name
********************************************************************/
char *readdirname(void *p)
{
- struct DIRECT *ptr;
- char *dname;
+ struct dirent *ptr;
+ char *dname;
- if (!p) return(NULL);
+ if (!p) return(NULL);
- ptr = (struct DIRECT *)readdir(p);
- if (!ptr) return(NULL);
+ ptr = (struct dirent *)readdir(p);
+ if (!ptr) return(NULL);
- dname = ptr->d_name;
+ dname = ptr->d_name;
#ifdef NEXT2
- if (telldir(p) < 0) return(NULL);
+ 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)
- dname = dname - 2;
- }
+#ifdef HAVE_BROKEN_READDIR
+ /* using /usr/ucb/cc is BAD */
+ dname = dname - 2;
#endif
- {
- static pstring buf;
- pstrcpy(buf, dname);
- unix_to_dos(buf, True);
- dname = buf;
- }
+ {
+ static pstring buf;
+ memcpy(buf, dname, NAMLEN(ptr)+1);
+ unix_to_dos(buf, True);
+ dname = buf;
+ }
- return(dname);
+ return(dname);
}
/*******************************************************************
/* Get the last component of the unix name. */
p = strrchr(name, '/');
- strncpy(last_component, p ? p : name, sizeof(last_component)-1);
+ strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
last_component[sizeof(last_component)-1] = '\0';
for(; namelist->name != NULL; namelist++)
{
if(namelist->is_wild)
{
- /* look for a wildcard match. */
- if (mask_match(last_component, namelist->name, case_sensitive, False))
+ /*
+ * Look for a wildcard match. Use the old
+ * 'unix style' mask match, rather than the
+ * new NT one.
+ */
+ if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
{
DEBUG(8,("is_in_path: mask match succeeded\n"));
return True;
struct flock lock;
int ret;
-#if 1
- uint32 mask = 0xC0000000;
-
- /* make sure the count is reasonable, we might kill the lockd otherwise */
- count &= ~mask;
+ /*
+ * FIXME.
+ * NB - this code will need re-writing to cope with large (64bit)
+ * lock requests. JRA.
+ */
- /* 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
- uint32 mask = ((unsigned)1<<31);
+ if(lp_ole_locking_compat()) {
+ uint32 mask = 0xC0000000;
- /* interpret negative counts as large numbers */
- if (count < 0)
+ /* make sure the count is reasonable, we might kill the lockd otherwise */
count &= ~mask;
- /* no negative offsets */
- offset &= ~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 {
+ uint32 mask = ((unsigned)1<<31);
+ int32 s_count = (int32) count; /* Signed count. */
+ int32 s_offset = (int32)offset; /* Signed offset. */
+
+ /* interpret negative counts as large numbers */
+ if (s_count < 0)
+ s_count &= ~mask;
+
+ /* no negative offsets */
+ if(s_offset < 0)
+ s_offset &= ~mask;
- /* count + offset must be in range */
- while ((offset < 0 || (offset + count < 0)) && mask)
+ /* count + offset must be in range */
+ while ((s_offset < 0 || (s_offset + s_count < 0)) && mask)
{
- offset &= ~mask;
+ s_offset &= ~mask;
mask = mask >> 1;
}
-#endif
+
+ offset = (uint32)s_offset;
+ count = (uint32)s_count;
+ }
DEBUG(8,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
(lock.l_pid != 0) &&
(lock.l_pid != getpid()))
{
- DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
+ DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
return(True);
}
switch( type )
{
case RA_WFWG:
- strcpy(remote_arch, "WfWg");
+ fstrcpy(remote_arch, "WfWg");
return;
case RA_OS2:
- strcpy(remote_arch, "OS2");
+ fstrcpy(remote_arch, "OS2");
return;
case RA_WIN95:
- strcpy(remote_arch, "Win95");
+ fstrcpy(remote_arch, "Win95");
return;
case RA_WINNT:
- strcpy(remote_arch, "WinNT");
+ fstrcpy(remote_arch, "WinNT");
return;
case RA_SAMBA:
- strcpy(remote_arch,"Samba");
+ fstrcpy(remote_arch,"Samba");
return;
default:
ra_type = RA_UNKNOWN;
- strcpy(remote_arch, "UNKNOWN");
+ fstrcpy(remote_arch, "UNKNOWN");
break;
}
}
/*******************************************************************
Get the remote_arch type.
********************************************************************/
-enum remote_arch_types get_remote_arch()
+enum remote_arch_types get_remote_arch(void)
{
return ra_type;
}
return num_wchars;
}
-
/*******************************************************************
-safe string copy into a fstring
+safe string copy into a known length string. maxlength does not
+include the terminating zero.
********************************************************************/
-void fstrcpy(char *dest, char *src)
+char *safe_strcpy(char *dest, char *src, int maxlength)
{
- int maxlength = sizeof(fstring) - 1;
+ int len;
+
if (!dest) {
- DEBUG(0,("ERROR: NULL dest in fstrcpy\n"));
- return;
+ DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
+ return NULL;
}
if (!src) {
*dest = 0;
- return;
+ return dest;
}
+
+ len = strlen(src);
+
+ if (len > maxlength) {
+ DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
+ len-maxlength, src));
+ len = maxlength;
+ }
- while (maxlength-- && *src)
- *dest++ = *src++;
- *dest = 0;
- if (*src) {
- DEBUG(0,("ERROR: string overflow by %d in fstrcpy\n",
- strlen(src)));
- }
-}
+ memcpy(dest, src, len);
+ dest[len] = 0;
+ return dest;
+}
/*******************************************************************
-safe string copy into a pstring
+safe string cat into a string. maxlength does not
+include the terminating zero.
********************************************************************/
-void pstrcpy(char *dest, char *src)
+char *safe_strcat(char *dest, char *src, int maxlength)
{
- int maxlength = sizeof(pstring) - 1;
+ int src_len, dest_len;
+
if (!dest) {
- DEBUG(0,("ERROR: NULL dest in pstrcpy\n"));
- return;
+ DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
+ return NULL;
}
-
+
if (!src) {
- *dest = 0;
- return;
- }
-
- while (maxlength-- && *src)
- *dest++ = *src++;
- *dest = 0;
- if (*src) {
- DEBUG(0,("ERROR: string overflow by %d in pstrcpy\n",
- strlen(src)));
- }
-}
+ return dest;
+ }
+ src_len = strlen(src);
+ dest_len = strlen(dest);
+
+ if (src_len + dest_len > maxlength) {
+ DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
+ src_len + dest_len - maxlength, src));
+ src_len = maxlength - dest_len;
+ }
+
+ memcpy(&dest[dest_len], src, src_len);
+ dest[dest_len + src_len] = 0;
+ return dest;
+}
/*******************************************************************
align a pointer to a multiple of 4 bytes
return spaces;
}
+/*****************************************************************
+ Convert a SID to an ascii string.
+*****************************************************************/
+
+char *sid_to_string(pstring sidstr_out, DOM_SID *sid)
+{
+ char subauth[16];
+ int i;
+ /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
+ uint32 ia = (sid->id_auth[5]) +
+ (sid->id_auth[4] << 8 ) +
+ (sid->id_auth[3] << 16) +
+ (sid->id_auth[2] << 24);
+
+ slprintf(sidstr_out, sizeof(pstring) - 1, "S-%d-%d", sid->sid_rev_num, ia);
+
+ for (i = 0; i < sid->num_auths; i++)
+ {
+ slprintf(subauth, sizeof(subauth)-1, "-%d", sid->sub_auths[i]);
+ pstrcat(sidstr_out, subauth);
+ }
+
+ DEBUG(7,("sid_to_string returning %s\n", sidstr_out));
+ return sidstr_out;
+}
+
+/*****************************************************************
+ Convert a string to a SID. Returns True on success, False on fail.
+*****************************************************************/
+
+BOOL string_to_sid(DOM_SID *sidout, char *sidstr)
+{
+ pstring tok;
+ char *p = sidstr;
+ /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
+ uint32 ia;
+
+ memset((char *)sidout, '\0', sizeof(DOM_SID));
+
+ if(StrnCaseCmp( sidstr, "S-", 2)) {
+ DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr));
+ return False;
+ }
+ p += 2;
+ if(!next_token(&p, tok, "-")) {
+ DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
+ return False;
+ }
+
+ /* Get the revision number. */
+ sidout->sid_rev_num = atoi(tok);
+
+ if(!next_token(&p, tok, "-")) {
+ DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
+ return False;
+ }
+
+ /* identauth in decimal should be < 2^32 */
+ ia = atoi(tok);
+
+ /* NOTE - the ia value is in big-endian format. */
+ sidout->id_auth[0] = 0;
+ sidout->id_auth[1] = 0;
+ sidout->id_auth[2] = (ia & 0xff000000) >> 24;
+ sidout->id_auth[3] = (ia & 0x00ff0000) >> 16;
+ sidout->id_auth[4] = (ia & 0x0000ff00) >> 8;
+ sidout->id_auth[5] = (ia & 0x000000ff);
+
+ sidout->num_auths = 0;
+
+ while(next_token(&p, tok, "-") && sidout->num_auths < MAXSUBAUTHS) {
+ /*
+ * NOTE - the subauths are in native machine-endian format. They
+ * are converted to little-endian when linearized onto the wire.
+ */
+ sidout->sub_auths[sidout->num_auths++] = atoi(tok);
+ }
+
+ DEBUG(7,("string_to_sid: converted SID %s ok\n", sidstr));
+
+ return True;
+}
+
+/*****************************************************************************
+ * Provide a checksum on a string
+ *
+ * Input: s - the nul-terminated character string for which the checksum
+ * will be calculated.
+ *
+ * Output: The checksum value calculated for s.
+ *
+ * ****************************************************************************
+ */
+int str_checksum(char *s)
+{
+ int res = 0;
+ int c;
+ int i=0;
+
+ while(*s) {
+ c = *s;
+ res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
+ s++;
+ i++;
+ }
+ return(res);
+} /* str_checksum */