diff options
author | Andrew Tridgell <tridge@samba.org> | 1999-12-13 13:27:58 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1999-12-13 13:27:58 +0000 |
commit | 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 (patch) | |
tree | 866dd15416c3d8554bb207709f433a87ad0c012d /source3/lib | |
parent | f6276724bafdb6145c0c7b565172d80cb04516ea (diff) | |
download | samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.gz samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.bz2 samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.zip |
first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
(This used to be commit 453a822a76780063dff23526c35408866d0c0154)
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/access.c | 38 | ||||
-rw-r--r-- | source3/lib/bitmap.c | 2 | ||||
-rw-r--r-- | source3/lib/charcnv.c | 204 | ||||
-rw-r--r-- | source3/lib/charset.c | 6 | ||||
-rw-r--r-- | source3/lib/crc32.c | 6 | ||||
-rw-r--r-- | source3/lib/debug.c | 256 | ||||
-rw-r--r-- | source3/lib/doscalls.c | 51 | ||||
-rw-r--r-- | source3/lib/genrand.c | 6 | ||||
-rw-r--r-- | source3/lib/interface.c | 452 | ||||
-rw-r--r-- | source3/lib/kanji.c | 195 | ||||
-rw-r--r-- | source3/lib/md4.c | 4 | ||||
-rw-r--r-- | source3/lib/pidfile.c | 9 | ||||
-rw-r--r-- | source3/lib/replace.c | 5 | ||||
-rw-r--r-- | source3/lib/signal.c | 68 | ||||
-rw-r--r-- | source3/lib/smbrun.c | 86 | ||||
-rw-r--r-- | source3/lib/snprintf.c | 62 | ||||
-rw-r--r-- | source3/lib/system.c | 197 | ||||
-rw-r--r-- | source3/lib/time.c | 68 | ||||
-rw-r--r-- | source3/lib/username.c | 542 | ||||
-rw-r--r-- | source3/lib/util.c | 1456 | ||||
-rw-r--r-- | source3/lib/util_file.c | 70 | ||||
-rw-r--r-- | source3/lib/util_sid.c | 708 | ||||
-rw-r--r-- | source3/lib/util_sock.c | 529 | ||||
-rw-r--r-- | source3/lib/util_str.c | 281 | ||||
-rw-r--r-- | source3/lib/util_unistr.c | 639 |
25 files changed, 2890 insertions, 3050 deletions
diff --git a/source3/lib/access.c b/source3/lib/access.c index 0fa383d84a..01f559750f 100644 --- a/source3/lib/access.c +++ b/source3/lib/access.c @@ -38,12 +38,14 @@ static int masked_match(char *tok, char *slash, char *s) } /* string_match - match string against token */ -static int string_match(char *tok,char *s) +static int string_match(char *tok,char *s, char *invalid_char) { - int tok_len; - int str_len; + size_t tok_len; + size_t str_len; char *cut; + *invalid_char = '\0'; + /* Return True if a token has the magic value "ALL". Return * FAIL if the token is "FAIL". If the token starts with a "." * (domain name), return True if it matches the last fields of @@ -108,6 +110,10 @@ static int string_match(char *tok,char *s) } else if ((cut = strchr(tok, '/')) != 0) { /* netnumber/netmask */ if (isdigit((int)s[0]) && masked_match(tok, cut, s)) return (True); + } else if (strchr(tok, '*') != 0) { + *invalid_char = '*'; + } else if (strchr(tok, '?') != 0) { + *invalid_char = '?'; } return (False); } @@ -118,15 +124,26 @@ static int client_match(char *tok,char *item) { char **client = (char **)item; int match; + char invalid_char = '\0'; /* * Try to match the address first. If that fails, try to match the host * name if available. */ - if ((match = string_match(tok, client[1])) == 0) - if (client[0][0] != 0) - match = string_match(tok, client[0]); + if ((match = string_match(tok, client[1], &invalid_char)) == 0) { + if(invalid_char) + DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \ +token '%s' in an allow/deny hosts line.\n", invalid_char, tok )); + + if (client[0][0] != 0) + match = string_match(tok, client[0], &invalid_char); + + if(invalid_char) + DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \ +token '%s' in an allow/deny hosts line.\n", invalid_char, tok )); + } + return (match); } @@ -184,6 +201,15 @@ BOOL allow_access(char *deny_list,char *allow_list, client[0] = cname; client[1] = caddr; + /* if it is loopback then always allow unless specifically denied */ + if (strcmp(caddr, "127.0.0.1") == 0) { + if (deny_list && + list_match(deny_list,(char *)client,client_match)) { + return False; + } + return True; + } + /* if theres no deny list and no allow list then allow access */ if ((!deny_list || *deny_list == 0) && (!allow_list || *allow_list == 0)) { diff --git a/source3/lib/bitmap.c b/source3/lib/bitmap.c index 93c821c528..1813d63ff7 100644 --- a/source3/lib/bitmap.c +++ b/source3/lib/bitmap.c @@ -35,10 +35,10 @@ struct bitmap *bitmap_allocate(int n) struct bitmap *bm; bm = (struct bitmap *)malloc(sizeof(*bm)); - bm->n = n; if (!bm) return NULL; + bm->n = n; bm->b = (uint32 *)malloc(sizeof(bm->b[0])*(n+31)/32); if (!bm->b) { free(bm); diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 29ef72d7ac..8f91e4573a 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -23,7 +23,7 @@ #define CTRLZ 26 extern int DEBUGLEVEL; -static char cvtbuf[1024]; +static char cvtbuf[sizeof(pstring)]; static BOOL mapsinited = 0; @@ -39,7 +39,7 @@ static void initmaps(void) { mapsinited = True; } -static void update_map(char * str) { +static void update_map(char *str) { char *p; for (p = str; *p; p++) { @@ -51,47 +51,55 @@ static void update_map(char * str) { } } -static void init_iso8859_1(void) { - +static void setupmaps(void) +{ int i; if (!mapsinited) initmaps(); /* Do not map undefined characters to some accidental code */ - for (i = 128; i < 256; i++) + for (i = 128; i < 256; i++) { unix2dos[i] = CTRLZ; dos2unix[i] = CTRLZ; } +} -/* MSDOS Code Page 850 -> ISO-8859 */ -update_map("\240\377\241\255\242\275\243\234\244\317\245\276\246\335\247\365"); -update_map("\250\371\251\270\252\246\253\256\254\252\255\360\256\251\257\356"); -update_map("\260\370\261\361\262\375\263\374\264\357\265\346\266\364\267\372"); -update_map("\270\367\271\373\272\247\273\257\274\254\275\253\276\363\277\250"); -update_map("\300\267\301\265\302\266\303\307\304\216\305\217\306\222\307\200"); -update_map("\310\324\311\220\312\322\313\323\314\336\315\326\316\327\317\330"); -update_map("\320\321\321\245\322\343\323\340\324\342\325\345\326\231\327\236"); -update_map("\330\235\331\353\332\351\333\352\334\232\335\355\336\350\337\341"); -update_map("\340\205\341\240\342\203\343\306\344\204\345\206\346\221\347\207"); -update_map("\350\212\351\202\352\210\353\211\354\215\355\241\356\214\357\213"); -update_map("\360\320\361\244\362\225\363\242\364\223\365\344\366\224\367\366"); -update_map("\370\233\371\227\372\243\373\226\374\201\375\354\376\347\377\230"); +static void init_iso8859_1(int codepage) { + setupmaps(); + + if (codepage == 437) { + /* MSDOS Code Page 437 -> ISO-8859-1 */ + update_map("\xA1\xAD\xA2\x98\xA3\x9C\xA4\xED\xA5\x9D\xA6\xB3\xA7\xEE"); + update_map("\xAA\xA6\xAB\xAE\xAC\xAA\xAE\xE9\xAF\xC4"); + update_map("\xB0\xF8\xB1\xF1\xB2\xFD\xB5\xE6\xB7\xFA\xBA\xA7\xBC\xAC\xBD\xAB\xBF\xA8"); + update_map("\xC0\x85\xC1\xA0\xC2\x83\xC4\x8E\xC5\x8F\xC6\x92\xC7\x80\xC8\x8A"); + update_map("\xC9\x90\xCA\x88\xCB\x89\xCC\x8D\xCD\xA1\xCE\x8C\xCF\x8B"); + update_map("\xD1\xA5\xD2\x96\xD3\xA2\xD4\x93\xD6\x99\xD9\x97\xDA\xA3\xDB\x96\xDC\x9A\xDF\xE1"); + update_map("\xE0\x85\xE1\xA0\xE2\x83\xE4\x84\xE5\x86\xE6\x91\xE7\x87\xE8\x8A\xE9\x82\xEA\x88\xEB\x89\xEC\x8D\xED\xA1\xEE\x8C\xEF\x8B"); + update_map("\xF0\xEB\xF1\xA4\xF2\x95\xF3\xA2\xF4\x93\xF6\x94\xF7\xF6\xF8\xED\xF9\x97\xFA\xA3\xFB\x96\xFC\x81\xFF\x98"); + } else { + /* MSDOS Code Page 850 -> ISO-8859-1 */ + update_map("\240\377\241\255\242\275\243\234\244\317\245\276\246\335\247\365"); + update_map("\250\371\251\270\252\246\253\256\254\252\255\360\256\251\257\356"); + update_map("\260\370\261\361\262\375\263\374\264\357\265\346\266\364\267\372"); + update_map("\270\367\271\373\272\247\273\257\274\254\275\253\276\363\277\250"); + update_map("\300\267\301\265\302\266\303\307\304\216\305\217\306\222\307\200"); + update_map("\310\324\311\220\312\322\313\323\314\336\315\326\316\327\317\330"); + update_map("\320\321\321\245\322\343\323\340\324\342\325\345\326\231\327\236"); + update_map("\330\235\331\353\332\351\333\352\334\232\335\355\336\350\337\341"); + update_map("\340\205\341\240\342\203\343\306\344\204\345\206\346\221\347\207"); + update_map("\350\212\351\202\352\210\353\211\354\215\355\241\356\214\357\213"); + update_map("\360\320\361\244\362\225\363\242\364\223\365\344\366\224\367\366"); + update_map("\370\233\371\227\372\243\373\226\374\201\375\354\376\347\377\230"); + } } /* Init for eastern european languages. */ static void init_iso8859_2(void) { - int i; - if (!mapsinited) initmaps(); - - /* Do not map undefined characters to some accidental code */ - for (i = 128; i < 256; i++) - { - unix2dos[i] = CTRLZ; - dos2unix[i] = CTRLZ; - } + setupmaps(); /* * Tranlation table created by Petr Hubeny <psh@capitol.cz> @@ -120,36 +128,48 @@ update_map("\370\375\371\205\372\243\373\373\374\201\375\354\376\356\377\372"); static void init_iso8859_5(void) { - int i; - if (!mapsinited) initmaps(); - - /* Do not map undefined characters to some accidental code */ - for (i = 128; i < 256; i++) - { - unix2dos[i] = CTRLZ; - dos2unix[i] = CTRLZ; - } + setupmaps(); /* MSDOS Code Page 866 -> ISO8859-5 */ -update_map("\200\260\201\261\202\262\203\263\204\264\205\265\206\266\207\267"); -update_map("\210\270\211\271\212\272\213\273\214\274\215\275\216\276\217\277"); -update_map("\220\300\221\301\222\302\223\303\224\304\225\305\226\306\227\307"); -update_map("\230\310\231\311\232\312\233\313\234\314\235\315\236\316\237\317"); -update_map("\240\320\241\321\242\322\243\323\244\324\245\325\246\326\247\327"); -update_map("\250\330\251\331\252\332\253\333\254\334\255\335\256\336\257\337"); +update_map("\260\200\261\201\262\202\263\203\264\204\265\205\266\206\267\207"); +update_map("\270\210\271\211\272\212\273\213\274\214\275\215\276\216\277\217"); +update_map("\300\220\301\221\302\222\303\223\304\224\305\225\306\226\307\227"); +update_map("\310\230\311\231\312\232\313\233\314\234\315\235\316\236\317\237"); +update_map("\320\240\321\241\322\242\323\243\324\244\325\245\326\246\327\247"); +update_map("\330\250\331\251\332\252\333\253\334\254\335\255\336\256\337\257"); update_map("\340\340\341\341\342\342\343\343\344\344\345\345\346\346\347\347"); update_map("\350\350\351\351\352\352\353\353\354\354\355\355\356\356\357\357"); -update_map("\360\241\361\361\362\244\363\364\364\247\365\367\366\256\367\376"); -update_map("\374\360\377\240"); +update_map("\241\360\361\361\244\362\364\363\247\364\367\365\256\366\376\367"); +update_map("\360\374\240\377"); +} + +/* Added by Antonios Kavarnos (Antonios.Kavarnos@softlab.ece.ntua.gr */ + +static void init_iso8859_7(void) +{ + setupmaps(); + +/* MSDOS Code Page 737 -> ISO-8859-7 (Greek-Hellenic) */ + +update_map("\301\200\302\201\303\202\304\203\305\204\306\205\307\206"); +update_map("\310\207\311\210\312\211\313\212\314\213\315\214\316\215\317\216"); +update_map("\320\217\321\220\323\221\324\222\325\223\326\224\327\225"); +update_map("\330\226\331\227"); +update_map("\341\230\342\231\343\232\344\233\345\234\346\235\347\236"); +update_map("\350\237\351\240\352\241\353\242\354\243\355\244\356\245\357\246"); +update_map("\360\247\361\250\362\252\363\251\364\253\365\254\366\255\367\256"); +update_map("\370\257\371\340"); +update_map("\332\364\333\365\334\341\335\342\336\343\337\345"); +update_map("\372\344\373\350\374\346\375\347\376\351"); +update_map("\266\352"); +update_map("\270\353\271\354\272\355\274\356\276\357\277\360"); } /* Init for russian language (koi8) */ static void init_koi8_r(void) { - if (!mapsinited) initmaps(); - - /* There aren't undefined characters between 128 and 255 */ + setupmaps(); /* MSDOS Code Page 866 -> KOI8-R */ update_map("\200\304\201\263\202\332\203\277\204\300\205\331\206\303\207\264"); @@ -170,24 +190,49 @@ update_map("\360\217\361\237\362\220\363\221\364\222\365\223\366\206\367\202"); update_map("\370\234\371\233\372\207\373\230\374\235\375\231\376\227\377\232"); } + +/* Init for ROMAN-8 (HP-UX) */ + +static void init_roman8(void) { + + setupmaps(); + +/* MSDOS Code Page 850 -> ROMAN8 */ +update_map("\240\377\241\267\242\266\243\324\244\322\245\323\246\327\247\330"); +update_map("\250\357\253\371\255\353\256\352\257\234"); +update_map("\260\356\261\355\262\354\263\370\264\200\265\207\266\245\267\244"); +update_map("\270\255\271\250\272\317\273\234\274\276\275\365\276\237\277\275"); +update_map("\300\203\301\210\302\223\303\226\304\240\305\202\306\242\307\243"); +update_map("\310\205\311\212\312\225\313\227\314\204\315\211\316\224\317\201"); +update_map("\320\217\321\214\322\235\323\222\324\206\325\241\326\233\327\221"); +update_map("\330\216\331\215\332\231\333\232\334\220\335\213\336\341\337\342"); +update_map("\340\265\341\307\342\306\343\321\344\320\345\326\346\336\347\340"); +update_map("\350\343\351\345\352\344\355\351\357\230"); +update_map("\360\350\361\347\362\372\363\346\364\364\365\363\366\360\367\254"); +update_map("\370\253\371\246\372\247\373\256\374\376\375\257\376\361"); +} + /* * Convert unix to dos */ char *unix2dos_format(char *str,BOOL overwrite) { - char *p; - char *dp; - - if (!mapsinited) initmaps(); - - if (overwrite) { - for (p = str; *p; p++) *p = unix2dos[(unsigned char)*p]; - return str; - } else { - for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = unix2dos[(unsigned char)*p]; - *dp = 0; - return cvtbuf; - } + char *p; + char *dp; + + if (!mapsinited) + initmaps(); + + if (overwrite) { + for (p = str; *p; p++) + *p = unix2dos[(unsigned char)*p]; + return str; + } else { + for (p = str, dp = cvtbuf;*p && (dp - cvtbuf < sizeof(cvtbuf) - 1); p++,dp++) + *dp = unix2dos[(unsigned char)*p]; + *dp = 0; + return cvtbuf; + } } /* @@ -195,36 +240,45 @@ char *unix2dos_format(char *str,BOOL overwrite) */ char *dos2unix_format(char *str, BOOL overwrite) { - char *p; - char *dp; - - if (!mapsinited) initmaps(); - - if (overwrite) { - for (p = str; *p; p++) *p = dos2unix[(unsigned char)*p]; - return str; - } else { - for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = dos2unix[(unsigned char)*p]; - *dp = 0; - return cvtbuf; - } + char *p; + char *dp; + + if (!mapsinited) + initmaps(); + + if (overwrite) { + for (p = str; *p; p++) + *p = dos2unix[(unsigned char)*p]; + return str; + } else { + for (p = str, dp = cvtbuf;*p && (dp - cvtbuf < sizeof(cvtbuf) - 1); p++,dp++) + *dp = dos2unix[(unsigned char)*p]; + *dp = 0; + return cvtbuf; + } } /* * Interpret character set. */ -void interpret_character_set(char *str) +void interpret_character_set(char *str, int codepage) { if (strequal (str, "iso8859-1")) { - init_iso8859_1(); + init_iso8859_1(codepage); } else if (strequal (str, "iso8859-2")) { init_iso8859_2(); } else if (strequal (str, "iso8859-5")) { init_iso8859_5(); + } else if (strequal (str, "iso8859-7")) { + init_iso8859_7(); } else if (strequal (str, "koi8-r")) { init_koi8_r(); + } else if (strequal (str, "roman8")) { + init_roman8(); } else { DEBUG(0,("unrecognized character set %s\n", str)); } + + load_unix_unicode_map(str); } diff --git a/source3/lib/charset.c b/source3/lib/charset.c index fc2924a155..6e5a4b48cb 100644 --- a/source3/lib/charset.c +++ b/source3/lib/charset.c @@ -320,8 +320,9 @@ clean_and_exit: } /**************************************************************************** -initialise the client codepage. + Initialise the client codepage. ****************************************************************************/ + void codepage_initialise(int client_codepage) { int i; @@ -369,6 +370,9 @@ for code page %d failed. Using default client codepage 850\n", for(i = 0; !((cp[i][0] == '\0') && (cp[i][1] == '\0')); i++) add_dos_char(cp[i][0], (BOOL)cp[i][2], cp[i][1], (BOOL)cp[i][3]); } + + /* Try and load the unicode map. */ + load_dos_unicode_map(client_codepage); } /******************************************************************* diff --git a/source3/lib/crc32.c b/source3/lib/crc32.c index 39c01fa30f..16b337c764 100644 --- a/source3/lib/crc32.c +++ b/source3/lib/crc32.c @@ -56,14 +56,12 @@ static unsigned long CRCTable[256] = 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D }; -uint32 crc32_calc_buffer( uint32 count, char *buffer) +uint32 crc32_calc_buffer( char *buffer, uint32 count) { uint32 crc=0xffffffff; - uint32 i; + int i; for(i=0;i<count;i++) - { crc = (crc>>8) ^ CRCTable[(buffer[i] ^ crc) & 0xff]; - } crc^=0xffffffff; DEBUG(10,("crc32_calc_buffer: %x\n", crc)); dump_data(100, buffer, count); diff --git a/source3/lib/debug.c b/source3/lib/debug.c index ab11d81a21..a0dfe61f7d 100644 --- a/source3/lib/debug.c +++ b/source3/lib/debug.c @@ -75,7 +75,6 @@ * debugf - Debug file name. * append_log - If True, then the output file will be opened in append * mode. - * timestamp_log - * DEBUGLEVEL - System-wide debug message limit. Messages with message- * levels higher than DEBUGLEVEL will not be processed. */ @@ -83,7 +82,6 @@ FILE *dbf = NULL; pstring debugf = ""; BOOL append_log = False; -BOOL timestamp_log = True; int DEBUGLEVEL = 1; @@ -114,51 +112,40 @@ static int debug_count = 0; static int syslog_level = 0; #endif static pstring format_bufr = { '\0' }; -static int format_pos = 0; +static size_t format_pos = 0; /* -------------------------------------------------------------------------- ** * Functions... */ -/* ************************************************************************** ** - * tells us if interactive logging was requested - * ************************************************************************** ** - */ -BOOL dbg_interactive(void) -{ - return stdout_logging; -} - -#if defined(SIGUSR2) && !defined(MEM_MAN) +#if defined(SIGUSR2) /* ************************************************************************** ** * catch a sigusr2 - decrease the debug log level. * ************************************************************************** ** */ void sig_usr2( int sig ) { - BlockSignals( True, SIGUSR2 ); - DEBUGLEVEL--; if( DEBUGLEVEL < 0 ) DEBUGLEVEL = 0; DEBUG( 0, ( "Got SIGUSR2; set debug level to %d.\n", DEBUGLEVEL ) ); - BlockSignals( False, SIGUSR2 ); +#if !defined(HAVE_SIGACTION) CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 ); +#endif } /* sig_usr2 */ #endif /* SIGUSR2 */ -#if defined(SIGUSR1) && !defined(MEM_MAN) +#if defined(SIGUSR1) /* ************************************************************************** ** * catch a sigusr1 - increase the debug log level. * ************************************************************************** ** */ void sig_usr1( int sig ) { - BlockSignals( True, SIGUSR1 ); DEBUGLEVEL++; @@ -167,8 +154,9 @@ void sig_usr1( int sig ) DEBUG( 0, ( "Got SIGUSR1; set debug level to %d.\n", DEBUGLEVEL ) ); - BlockSignals( False, SIGUSR1 ); +#if !defined(HAVE_SIGACTION) CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 ); +#endif } /* sig_usr1 */ #endif /* SIGUSR1 */ @@ -260,11 +248,11 @@ void force_check_log_size( void ) * ************************************************************************** ** */ static void check_log_size( void ) - { +{ int maxlog; SMB_STRUCT_STAT st; - if( debug_count++ < 100 || getuid() != 0 ) + if( debug_count++ < 100 || geteuid() != 0 ) return; maxlog = lp_max_log_size() * 1024; @@ -276,7 +264,7 @@ static void check_log_size( void ) (void)fclose( dbf ); dbf = NULL; reopen_logs(); - if( dbf && file_size( debugf ) > maxlog ) + if( dbf && get_file_size( debugf ) > maxlog ) { pstring name; @@ -287,8 +275,23 @@ static void check_log_size( void ) reopen_logs(); } } + /* + * Here's where we need to panic if dbf == NULL.. + */ + if(dbf == NULL) { + dbf = sys_fopen( "/dev/console", "w" ); + if(dbf) { + DEBUG(0,("check_log_size: open of debug file %s failed - using console.\n", + debugf )); + } else { + /* + * We cannot continue without a debug file handle. + */ + abort(); + } + } debug_count = 0; - } /* check_log_size */ +} /* check_log_size */ /* ************************************************************************** ** * Write an debug message on the debugfile. @@ -382,6 +385,8 @@ va_dcl } #endif + check_log_size(); + #ifdef WITH_SYSLOG if( !lp_syslog_only() ) #endif @@ -397,8 +402,6 @@ va_dcl (void)fflush( dbf ); } - check_log_size(); - errno = old_errno; return( 0 ); @@ -439,8 +442,8 @@ static void bufr_print( void ) */ static void format_debug_text( char *msg ) { - int i; - BOOL timestamp = (timestamp_log && !stdout_logging && (lp_timestamp_logs() || + size_t i; + BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() || !(lp_loaded()))); for( i = 0; msg[i]; i++ ) @@ -510,10 +513,13 @@ void dbgflush( void ) * * ************************************************************************** ** */ + BOOL dbghdr( int level, char *file, char *func, int line ) - { - if( format_pos ) - { +{ + /* Ensure we don't lose any real errno value. */ + int old_errno = errno; + + if( format_pos ) { /* This is a fudge. If there is stuff sitting in the format_bufr, then * the *right* thing to do is to call * format_debug_text( "\n" ); @@ -524,7 +530,7 @@ BOOL dbghdr( int level, char *file, char *func, int line ) * that a new header is *not* desired. */ return( True ); - } + } #ifdef WITH_SYSLOG /* Set syslog_level. */ @@ -538,15 +544,32 @@ BOOL dbghdr( int level, char *file, char *func, int line ) /* Print the header if timestamps are turned on. If parameters are * not yet loaded, then default to timestamps on. */ - if( timestamp_log && (lp_timestamp_logs() || !(lp_loaded()) )) - { + if( lp_timestamp_logs() || !(lp_loaded()) ) { + char header_str[200]; + + header_str[0] = '\0'; + + if( lp_debug_pid()) + slprintf(header_str,sizeof(header_str)-1,", pid=%u",(unsigned int)getpid()); + + if( lp_debug_uid()) { + size_t hs_len = strlen(header_str); + slprintf(header_str + hs_len, + sizeof(header_str) - 1 - hs_len, + ", effective(%u, %u), real(%u, %u)", + (unsigned int)geteuid(), (unsigned int)getegid(), + (unsigned int)getuid(), (unsigned int)getgid()); + } + /* Print it all out at once to prevent split syslog output. */ - (void)Debug1( "[%s, %d] %s:%s(%d)\n", - timestring(), level, file, func, line ); - } + (void)Debug1( "[%s, %d%s] %s:%s(%d)\n", + timestring(lp_debug_hires_timestamp()), level, + header_str, file, func, line ); + } + errno = old_errno; return( True ); - } /* dbghdr */ +} /* ************************************************************************** ** * Add text to the body of the "current" debug message via the format buffer. @@ -596,163 +619,4 @@ BOOL dbghdr( int level, char *file, char *func, int line ) #endif -dbg_Token dbg_char2token( dbg_Token *state, int c ) - /* ************************************************************************ ** - * Parse input one character at a time. - * - * Input: state - A pointer to a token variable. This is used to - * maintain the parser state between calls. For - * each input stream, you should set up a separate - * state variable and initialize it to dbg_null. - * Pass a pointer to it into this function with each - * character in the input stream. See dbg_test() - * for an example. - * c - The "current" character in the input stream. - * - * Output: A token. - * The token value will change when delimiters are found, - * which indicate a transition between syntactical objects. - * Possible return values are: - * - * dbg_null - The input character was an end-of-line. - * This resets the parser to its initial state - * in preparation for parsing the next line. - * dbg_eof - Same as dbg_null, except that the character - * was an end-of-file. - * dbg_ignore - Returned for whitespace and delimiters. - * These lexical tokens are only of interest - * to the parser. - * dbg_header - Indicates the start of a header line. The - * input character was '[' and was the first on - * the line. - * dbg_timestamp - Indicates that the input character was part - * of a header timestamp. - * dbg_level - Indicates that the input character was part - * of the debug-level value in the header. - * dbg_sourcefile - Indicates that the input character was part - * of the sourcefile name in the header. - * dbg_function - Indicates that the input character was part - * of the function name in the header. - * dbg_lineno - Indicates that the input character was part - * of the DEBUG call line number in the header. - * dbg_message - Indicates that the input character was part - * of the DEBUG message text. - * - * ************************************************************************ ** - */ - { - /* The terminating characters that we see will greatly depend upon - * how they are read. For example, if gets() is used instead of - * fgets(), then we will not see newline characters. A lot also - * depends on the calling function, which may handle terminators - * itself. - * - * '\n', '\0', and EOF are all considered line terminators. The - * dbg_eof token is sent back if an EOF is encountered. - * - * Warning: only allow the '\0' character to be sent if you are - * using gets() to read whole lines (thus replacing '\n' - * with '\0'). Sending '\0' at the wrong time will mess - * up the parsing. - */ - switch( c ) - { - case EOF: - *state = dbg_null; /* Set state to null (initial state) so */ - return( dbg_eof ); /* that we can restart with new input. */ - case '\n': - case '\0': - *state = dbg_null; /* A newline or eoln resets to the null state. */ - return( dbg_null ); - } - - /* When within the body of the message, only a line terminator - * can cause a change of state. We've already checked for line - * terminators, so if the current state is dbg_msgtxt, simply - * return that as our current token. - */ - if( dbg_message == *state ) - return( dbg_message ); - - /* If we are at the start of a new line, and the input character - * is an opening bracket, then the line is a header line, otherwise - * it's a message body line. - */ - if( dbg_null == *state ) - { - if( '[' == c ) - { - *state = dbg_timestamp; - return( dbg_header ); - } - *state = dbg_message; - return( dbg_message ); - } - - /* We've taken care of terminators, text blocks and new lines. - * The remaining possibilities are all within the header line - * itself. - */ - - /* Within the header line, whitespace can be ignored *except* - * within the timestamp. - */ - if( isspace( c ) ) - { - /* Fudge. The timestamp may contain space characters. */ - if( (' ' == c) && (dbg_timestamp == *state) ) - return( dbg_timestamp ); - /* Otherwise, ignore whitespace. */ - return( dbg_ignore ); - } - - /* Okay, at this point we know we're somewhere in the header. - * Valid header *states* are: dbg_timestamp, dbg_level, - * dbg_sourcefile, dbg_function, and dbg_lineno. - */ - switch( c ) - { - case ',': - if( dbg_timestamp == *state ) - { - *state = dbg_level; - return( dbg_ignore ); - } - break; - case ']': - if( dbg_level == *state ) - { - *state = dbg_sourcefile; - return( dbg_ignore ); - } - break; - case ':': - if( dbg_sourcefile == *state ) - { - *state = dbg_function; - return( dbg_ignore ); - } - break; - case '(': - if( dbg_function == *state ) - { - *state = dbg_lineno; - return( dbg_ignore ); - } - break; - case ')': - if( dbg_lineno == *state ) - { - *state = dbg_null; - return( dbg_ignore ); - } - break; - } - - /* If the previous block did not result in a state change, then - * return the current state as the current token. - */ - return( *state ); - } /* dbg_char2token */ - /* ************************************************************************** */ diff --git a/source3/lib/doscalls.c b/source3/lib/doscalls.c index 2098b5e350..e6f9d19879 100644 --- a/source3/lib/doscalls.c +++ b/source3/lib/doscalls.c @@ -52,23 +52,18 @@ int dos_open(char *fname,int flags,mode_t mode) } /******************************************************************* - Opendir() wrapper that calls dos_to_unix. Should use the - vfs_ops->opendir() function instead. + Opendir() wrapper that calls dos_to_unix. ********************************************************************/ -#if 0 DIR *dos_opendir(char *dname) { return(opendir(dos_to_unix(dname,False))); } -#endif /******************************************************************* - Readdirname() wrapper that calls unix_to_dos. Should use the - vfs_readdirname() function instead. + Readdirname() wrapper that calls unix_to_dos. ********************************************************************/ -#if 0 char *dos_readdirname(DIR *p) { char *dname = readdirname(p); @@ -79,7 +74,15 @@ char *dos_readdirname(DIR *p) unix_to_dos(dname, True); return(dname); } -#endif + +/******************************************************************* + A chown() wrapper that calls dos_to_unix. +********************************************************************/ + +int dos_chown(char *fname, uid_t uid, gid_t gid) +{ + return(sys_chown(dos_to_unix(fname,False),uid,gid)); +} /******************************************************************* A stat() wrapper that calls dos_to_unix. @@ -100,14 +103,18 @@ int dos_lstat(char *fname,SMB_STRUCT_STAT *sbuf) } /******************************************************************* - Mkdir() that calls dos_to_unix. Don't use this call unless you - really want to access a file on disk. Use the vfs_ops.mkdir() - function instead. + Mkdir() that calls dos_to_unix. + Cope with UNIXes that don't allow high order mode bits on mkdir. + Patch from gcarter@lanier.com. ********************************************************************/ int dos_mkdir(char *dname,mode_t mode) { - return(mkdir(dos_to_unix(dname,False),mode)); + int ret = mkdir(dos_to_unix(dname,False),mode); + if(!ret) + return(dos_chmod(dname,mode)); + else + return ret; } /******************************************************************* @@ -151,7 +158,7 @@ int dos_utime(char *fname,struct utimbuf *times) <warrenb@hpcvscdp.cv.hp.com> **********************************************************/ -int copy_reg(char *source, const char *dest) +static int copy_reg(char *source, const char *dest) { SMB_STRUCT_STAT source_stats; int ifd; @@ -243,11 +250,19 @@ int copy_reg(char *source, const char *dest) int dos_rename(char *from, char *to) { + int rcode; pstring zfrom, zto; pstrcpy (zfrom, dos_to_unix (from, False)); pstrcpy (zto, dos_to_unix (to, False)); - return file_rename(zfrom, zto); + rcode = rename (zfrom, zto); + + if (errno == EXDEV) + { + /* Rename across filesystems needed. */ + rcode = copy_reg (zfrom, zto); + } + return rcode; } /******************************************************************* @@ -274,15 +289,13 @@ char *dos_getwd(char *unix_path) } /******************************************************************* - Check if a DOS file exists. Use vfs_file_exist function instead. + Check if a DOS file exists. ********************************************************************/ -#if 0 BOOL dos_file_exist(char *fname,SMB_STRUCT_STAT *sbuf) { return file_exist(dos_to_unix(fname, False), sbuf); } -#endif /******************************************************************* Check if a DOS directory exists. @@ -308,7 +321,7 @@ time_t dos_file_modtime(char *fname) SMB_OFF_T dos_file_size(char *file_name) { - return file_size(dos_to_unix(file_name, False)); + return get_file_size(dos_to_unix(file_name, False)); } /******************************************************************* @@ -404,7 +417,7 @@ char *dos_GetWd(char *path) if (sys_stat(".",&st) == -1) { - DEBUG(0,("Very strange, couldn't stat \".\"\n")); + DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path)); return(dos_getwd(path)); } diff --git a/source3/lib/genrand.c b/source3/lib/genrand.c index ab0dadebcf..a9698d4cd1 100644 --- a/source3/lib/genrand.c +++ b/source3/lib/genrand.c @@ -58,8 +58,8 @@ static void do_dirrand(char *name, unsigned char *buf, int buf_len) { DIR *dp = opendir(name); pstring fullname; - size_t len_left; - size_t fullname_len; + int len_left; + int fullname_len; char *pos; pstrcpy(fullname, name); @@ -150,7 +150,7 @@ static uint32 do_reseed(unsigned char *md4_outbuf) /* add in the root encrypted password. On any system where security is taken seriously this will be secret */ - pw = getpwnam("root"); + pw = sys_getpwnam("root"); if (pw && pw->pw_passwd) { int i; unsigned char md4_tmp[16]; diff --git a/source3/lib/interface.c b/source3/lib/interface.c index 65d276021c..9266427959 100644 --- a/source3/lib/interface.c +++ b/source3/lib/interface.c @@ -21,230 +21,225 @@ #include "includes.h" +#define MAX_INTERFACES 128 + +static struct iface_struct *probed_ifaces; +static int total_probed; + extern int DEBUGLEVEL; struct in_addr ipzero; struct in_addr allones_ip; struct in_addr loopback_ip; -static struct in_addr default_ip; -static struct in_addr default_bcast; -static struct in_addr default_nmask; -static BOOL got_ip=False; -static BOOL got_bcast=False; -static BOOL got_nmask=False; static struct interface *local_interfaces = NULL; -struct interface *last_iface; - #define ALLONES ((uint32)0xFFFFFFFF) #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES)) +#define MKNETADDR(_IP, _NM) (_IP & _NM) + /**************************************************************************** -calculate the default netmask for an address -****************************************************************************/ -static void default_netmask(struct in_addr *inm, struct in_addr *iad) +Try and find an interface that matches an ip. If we cannot, return NULL + **************************************************************************/ +static struct interface *iface_find(struct in_addr ip) { - /* - ** Guess a netmask based on the class of the IP address given. - */ - switch((ntohl(iad->s_addr) & 0xE0000000)) { - case 0x00000000: /* Class A addr */ - case 0x20000000: - case 0x40000000: - case 0x60000000: - inm->s_addr = htonl(0xFF000000); - break; - - case 0x80000000: /* Class B addr */ - case 0xA0000000: - inm->s_addr = htonl(0xFFFF0000); - break; - - case 0xC0000000: /* Class C addr */ - inm->s_addr = htonl(0xFFFFFF00); - break; - - default: /* ??? */ - inm->s_addr = htonl(0xFFFFFFF0); - } + struct interface *i; + if (zero_ip(ip)) return local_interfaces; + + for (i=local_interfaces;i;i=i->next) + if (same_net(i->ip,ip,i->nmask)) return i; + + return NULL; } /**************************************************************************** - get the broadcast address for our address -(troyer@saifr00.ateng.az.honeywell.com) +add an interface to the linked list of interfaces ****************************************************************************/ -static void get_broadcast(struct in_addr *if_ipaddr, - struct in_addr *if_bcast, - struct in_addr *if_nmask) -{ - uint32 nm; - short onbc; - short offbc; - - /* get a default netmask and broadcast */ - default_netmask(if_nmask, if_ipaddr); - - get_netmask(if_ipaddr, if_nmask); - - /* sanity check on the netmask */ - nm = ntohl(if_nmask->s_addr); - onbc = 0; - offbc = 0; - while((onbc + offbc) < 32) { - if(nm & 0x80000000) { - onbc++; - if(offbc) { - /* already found an off bit, so mask - is wrong */ - onbc = 34; - } - } else { - offbc++; - } - nm <<= 1; +static void add_interface(struct in_addr ip, struct in_addr nmask) +{ + struct interface *iface; + if (iface_find(ip)) { + DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip))); + return; } - if ((onbc < 8)||(onbc == 34)) { - DEBUG(0,("Impossible netmask %s - using defaults\n", - inet_ntoa(*if_nmask))); - default_netmask(if_nmask, if_ipaddr); + + if (ip_equal(nmask, allones_ip)) { + DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip))); + return; } - /* 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 */ - if_bcast->s_addr = MKBCADDR(if_ipaddr->s_addr, if_nmask->s_addr); - - DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast))); + iface = (struct interface *)malloc(sizeof(*iface)); + if (!iface) return; + + ZERO_STRUCTPN(iface); + + iface->ip = ip; + iface->nmask = nmask; + iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); + + DLIST_ADD(local_interfaces, iface); + + DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip))); + DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); + DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask))); } /**************************************************************************** -load a list of network interfaces +interpret a single element from a interfaces= config line + +This handles the following different forms: + +1) wildcard interface name +2) DNS name +3) IP/masklen +4) ip/mask +5) bcast/mask ****************************************************************************/ -static void interpret_interfaces(char *s, struct interface **interfaces, - char *description) +static void interpret_interface(char *token) { - char *ptr; - fstring token; - struct interface *iface; - struct in_addr ip; - - ptr = s; - ipzero = *interpret_addr2("0.0.0.0"); - allones_ip = *interpret_addr2("255.255.255.255"); - loopback_ip = *interpret_addr2("127.0.0.1"); - - while (next_token(&ptr,token,NULL,sizeof(token))) { - /* parse it into an IP address/netmasklength pair */ - char *p = strchr(token,'/'); - if (p) *p++ = 0; - - ip = *interpret_addr2(token); - - /* maybe we already have it listed */ - { - struct interface *i; - for (i=(*interfaces);i;i=i->next) - if (ip_equal(ip,i->ip)) break; - if (i) continue; - } - - iface = (struct interface *)malloc(sizeof(*iface)); - if (!iface) return; - - iface->ip = ip; - - if (p) { - if (strlen(p) > 2) - iface->nmask = *interpret_addr2(p); - else - iface->nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); - } else { - default_netmask(&iface->nmask,&iface->ip); - } - iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); - iface->next = NULL; - - if (!(*interfaces)) { - (*interfaces) = iface; - } else { - last_iface->next = iface; - } - last_iface = iface; - DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip))); - DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask))); - } - - if (*interfaces) return; - - /* setup a default interface */ - iface = (struct interface *)malloc(sizeof(*iface)); - if (!iface) return; - - iface->next = NULL; - - if (got_ip) { - iface->ip = default_ip; - } else { - get_myname(NULL,&iface->ip); - } - - if (got_bcast) { - iface->bcast = default_bcast; - } else { - get_broadcast(&iface->ip,&iface->bcast,&iface->nmask); - } - - if (got_nmask) { - iface->nmask = default_nmask; - iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); - } - - if (iface->bcast.s_addr != MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr)) { - DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip))); - } - - iface->next = NULL; - (*interfaces) = last_iface = iface; - - DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip))); - DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask))); + struct in_addr ip, nmask; + char *p; + int i, added=0; + + ip = ipzero; + nmask = ipzero; + + /* first check if it is an interface name */ + for (i=0;i<total_probed;i++) { + if (fnmatch(token, probed_ifaces[i].name, 0) == 0) { + add_interface(probed_ifaces[i].ip, + probed_ifaces[i].netmask); + added = 1; + } + } + if (added) return; + + /* maybe it is a DNS name */ + p = strchr(token,'/'); + if (!p) { + ip = *interpret_addr2(token); + for (i=0;i<total_probed;i++) { + if (ip.s_addr == probed_ifaces[i].ip.s_addr && + !ip_equal(allones_ip, probed_ifaces[i].netmask)) { + add_interface(probed_ifaces[i].ip, + probed_ifaces[i].netmask); + return; + } + } + DEBUG(2,("can't determine netmask for %s\n", token)); + return; + } + + /* parse it into an IP address/netmasklength pair */ + *p++ = 0; + + ip = *interpret_addr2(token); + + if (strlen(p) > 2) { + nmask = *interpret_addr2(p); + } else { + nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); + } + + /* maybe the first component was a broadcast address */ + if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) || + ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) { + for (i=0;i<total_probed;i++) { + if (same_net(ip, probed_ifaces[i].ip, nmask)) { + add_interface(probed_ifaces[i].ip, nmask); + return; + } + } + DEBUG(2,("Can't determine ip for broadcast address %s\n", token)); + return; + } + + add_interface(ip, nmask); } /**************************************************************************** -load the remote and local interfaces +load the list of network interfaces ****************************************************************************/ void load_interfaces(void) { - /* add the machine's interfaces to local interface structure*/ - interpret_interfaces(lp_interfaces(), &local_interfaces,"interface"); + char *ptr; + fstring token; + int i; + struct iface_struct ifaces[MAX_INTERFACES]; + + ptr = lp_interfaces(); + + ipzero = *interpret_addr2("0.0.0.0"); + allones_ip = *interpret_addr2("255.255.255.255"); + loopback_ip = *interpret_addr2("127.0.0.1"); + + if (probed_ifaces) { + free(probed_ifaces); + probed_ifaces = NULL; + } + + /* dump the current interfaces if any */ + while (local_interfaces) { + struct interface *iface = local_interfaces; + DLIST_REMOVE(local_interfaces, local_interfaces); + ZERO_STRUCTPN(iface); + free(iface); + } + + /* probe the kernel for interfaces */ + total_probed = get_interfaces(ifaces, MAX_INTERFACES); + + if (total_probed > 0) { + probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed); + } + + /* if we don't have a interfaces line then use all broadcast capable + interfaces except loopback */ + if (!ptr || !*ptr) { + if (total_probed <= 0) { + DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n")); + exit(1); + } + for (i=0;i<total_probed;i++) { + if (probed_ifaces[i].netmask.s_addr != allones_ip.s_addr && + probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) { + add_interface(probed_ifaces[i].ip, + probed_ifaces[i].netmask); + } + } + return; + } + + while (next_token(&ptr,token,NULL,sizeof(token))) { + interpret_interface(token); + } + + if (!local_interfaces) { + DEBUG(0,("WARNING: no network interfaces found\n")); + } } /**************************************************************************** - override the defaults - **************************************************************************/ -void iface_set_default(char *ip,char *bcast,char *nmask) +return True if the list of probed interfaces has changed +****************************************************************************/ +BOOL interfaces_changed(void) { - if (ip) { - got_ip = True; - default_ip = *interpret_addr2(ip); - } - - if (bcast) { - got_bcast = True; - default_bcast = *interpret_addr2(bcast); - } - - if (nmask) { - got_nmask = True; - default_nmask = *interpret_addr2(nmask); - } + int n; + struct iface_struct ifaces[MAX_INTERFACES]; + + n = get_interfaces(ifaces, MAX_INTERFACES); + + if (n != total_probed || + memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n)) { + return True; + } + + return False; } @@ -253,10 +248,10 @@ void iface_set_default(char *ip,char *bcast,char *nmask) **************************************************************************/ BOOL ismyip(struct in_addr ip) { - struct interface *i; - for (i=local_interfaces;i;i=i->next) - if (ip_equal(i->ip,ip)) return True; - return False; + struct interface *i; + for (i=local_interfaces;i;i=i->next) + if (ip_equal(i->ip,ip)) return True; + return False; } /**************************************************************************** @@ -264,11 +259,13 @@ BOOL ismyip(struct in_addr ip) **************************************************************************/ BOOL is_local_net(struct in_addr from) { - struct interface *i; - for (i=local_interfaces;i;i=i->next) - if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr)) - return True; - return False; + struct interface *i; + for (i=local_interfaces;i;i=i->next) { + if((from.s_addr & i->nmask.s_addr) == + (i->ip.s_addr & i->nmask.s_addr)) + return True; + } + return False; } /**************************************************************************** @@ -276,12 +273,12 @@ BOOL is_local_net(struct in_addr from) **************************************************************************/ int iface_count(void) { - int ret = 0; - struct interface *i; + int ret = 0; + struct interface *i; - for (i=local_interfaces;i;i=i->next) - ret++; - return ret; + for (i=local_interfaces;i;i=i->next) + ret++; + return ret; } /**************************************************************************** @@ -289,12 +286,12 @@ int iface_count(void) **************************************************************************/ BOOL we_are_multihomed(void) { - static int multi = -1; + static int multi = -1; - if(multi == -1) - multi = (iface_count() > 1 ? True : False); - - return multi; + if(multi == -1) + multi = (iface_count() > 1 ? True : False); + + return multi; } /**************************************************************************** @@ -302,13 +299,13 @@ BOOL we_are_multihomed(void) **************************************************************************/ struct interface *get_interface(int n) { - struct interface *i; + struct interface *i; - for (i=local_interfaces;i && n;i=i->next) - n--; + for (i=local_interfaces;i && n;i=i->next) + n--; - if (i) return i; - return NULL; + if (i) return i; + return NULL; } /**************************************************************************** @@ -316,27 +313,27 @@ struct interface *get_interface(int n) **************************************************************************/ struct in_addr *iface_n_ip(int n) { - struct interface *i; + struct interface *i; - for (i=local_interfaces;i && n;i=i->next) - n--; + for (i=local_interfaces;i && n;i=i->next) + n--; - if (i) return &i->ip; - return NULL; + if (i) return &i->ip; + return NULL; } /**************************************************************************** -Try and find an interface that matches an ip. If we cannot, return NULL + return bcast of the Nth interface **************************************************************************/ -static struct interface *iface_find(struct in_addr ip) +struct in_addr *iface_n_bcast(int n) { - struct interface *i; - if (zero_ip(ip)) return local_interfaces; - - for (i=local_interfaces;i;i=i->next) - if (same_net(i->ip,ip,i->nmask)) return i; + struct interface *i; + + for (i=local_interfaces;i && n;i=i->next) + n--; - return NULL; + if (i) return &i->bcast; + return NULL; } @@ -368,15 +365,12 @@ unsigned iface_hash(void) struct in_addr *iface_bcast(struct in_addr ip) { - struct interface *i = iface_find(ip); - return(i ? &i->bcast : &local_interfaces->bcast); + struct interface *i = iface_find(ip); + return(i ? &i->bcast : &local_interfaces->bcast); } struct in_addr *iface_ip(struct in_addr ip) { - struct interface *i = iface_find(ip); - return(i ? &i->ip : &local_interfaces->ip); + struct interface *i = iface_find(ip); + return(i ? &i->ip : &local_interfaces->ip); } - - - diff --git a/source3/lib/kanji.c b/source3/lib/kanji.c index 871a4a059c..1983bb1161 100644 --- a/source3/lib/kanji.c +++ b/source3/lib/kanji.c @@ -377,7 +377,7 @@ static size_t skip_generic_multibyte_char(char c) ********************************************************************/ /* convesion buffer */ -static char cvtbuf[1024]; +static char cvtbuf[2*sizeof(pstring)]; /******************************************************************* EUC <-> SJIS @@ -412,7 +412,7 @@ static char *sj_to_euc(char *from, BOOL overwrite) char *save; save = (char *) from; - for (out = cvtbuf; *from;) { + for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3);) { if (is_shift_jis (*from)) { int code = sjis2euc ((int) from[0] & 0xff, (int) from[1] & 0xff); *out++ = (code >> 8) & 0xff; @@ -445,7 +445,7 @@ static char *euc_to_sj(char *from, BOOL overwrite) char *save; save = (char *) from; - for (out = cvtbuf; *from; ) { + for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3); ) { if (is_euc (*from)) { int code = euc2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff); *out++ = (code >> 8) & 0xff; @@ -496,48 +496,51 @@ static int jis2sjis(int hi, int lo) static char *jis8_to_sj(char *from, BOOL overwrite) { - char *out; - int shifted; - char *save; + char *out; + int shifted; + char *save; - shifted = _KJ_ROMAN; - save = (char *) from; - for (out = cvtbuf; *from;) { - if (is_esc (*from)) { - if (is_so1 (from[1]) && is_so2 (from[2])) { - shifted = _KJ_KANJI; - from += 3; - } else if (is_si1 (from[1]) && is_si2 (from[2])) { - shifted = _KJ_ROMAN; - from += 3; - } else { /* sequence error */ - goto normal; - } - } else { - normal: - switch (shifted) { - default: - case _KJ_ROMAN: - *out++ = *from++; - break; - case _KJ_KANJI: - { - int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } - break; - } - } - } - *out = 0; - if (overwrite) { - pstrcpy (save, (char *) cvtbuf); - return save; + shifted = _KJ_ROMAN; + save = (char *) from; + for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3);) { + if (is_esc (*from)) { + if (is_so1 (from[1]) && is_so2 (from[2])) { + shifted = _KJ_KANJI; + from += 3; + } else if (is_si1 (from[1]) && is_si2 (from[2])) { + shifted = _KJ_ROMAN; + from += 3; + } else { /* sequence error */ + goto normal; + } } else { - return cvtbuf; + +normal: + + switch (shifted) { + default: + case _KJ_ROMAN: + *out++ = *from++; + break; + case _KJ_KANJI: + { + int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff); + *out++ = (code >> 8) & 0xff; + *out++ = code; + from += 2; + break; + } + } } + } + + *out = 0; + if (overwrite) { + pstrcpy (save, (char *) cvtbuf); + return save; + } else { + return cvtbuf; + } } /******************************************************************* @@ -547,54 +550,55 @@ static char *jis8_to_sj(char *from, BOOL overwrite) static char *sj_to_jis8(char *from, BOOL overwrite) { - char *out; - int shifted; - char *save; + char *out; + int shifted; + char *save; - shifted = _KJ_ROMAN; - save = (char *) from; - for (out = cvtbuf; *from; ) { - if (is_shift_jis (*from)) { - int code; - switch (shifted) { - case _KJ_ROMAN: /* to KANJI */ - *out++ = jis_esc; - *out++ = jis_so1; - *out++ = jis_kso; - shifted = _KJ_KANJI; - break; - } - code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } else { - switch (shifted) { - case _KJ_KANJI: /* to ROMAN/KANA */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_ksi; - shifted = _KJ_ROMAN; - break; - } - *out++ = *from++; - } - } - switch (shifted) { - case _KJ_KANJI: /* to ROMAN/KANA */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_ksi; - shifted = _KJ_ROMAN; - break; - } - *out = 0; - if (overwrite) { - pstrcpy (save, (char *) cvtbuf); - return save; + shifted = _KJ_ROMAN; + save = (char *) from; + for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-4); ) { + if (is_shift_jis (*from)) { + int code; + switch (shifted) { + case _KJ_ROMAN: /* to KANJI */ + *out++ = jis_esc; + *out++ = jis_so1; + *out++ = jis_kso; + shifted = _KJ_KANJI; + break; + } + code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff); + *out++ = (code >> 8) & 0xff; + *out++ = code; + from += 2; } else { - return cvtbuf; + switch (shifted) { + case _KJ_KANJI: /* to ROMAN/KANA */ + *out++ = jis_esc; + *out++ = jis_si1; + *out++ = jis_ksi; + shifted = _KJ_ROMAN; + break; + } + *out++ = *from++; } + } + + switch (shifted) { + case _KJ_KANJI: /* to ROMAN/KANA */ + *out++ = jis_esc; + *out++ = jis_si1; + *out++ = jis_ksi; + shifted = _KJ_ROMAN; + break; + } + *out = 0; + if (overwrite) { + pstrcpy (save, (char *) cvtbuf); + return save; + } else { + return cvtbuf; + } } /******************************************************************* @@ -609,7 +613,7 @@ static char *jis7_to_sj(char *from, BOOL overwrite) shifted = _KJ_ROMAN; save = (char *) from; - for (out = cvtbuf; *from;) { + for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3);) { if (is_esc (*from)) { if (is_so1 (from[1]) && is_so2 (from[2])) { shifted = _KJ_KANJI; @@ -668,7 +672,7 @@ static char *sj_to_jis7(char *from, BOOL overwrite) shifted = _KJ_ROMAN; save = (char *) from; - for (out = cvtbuf; *from; ) { + for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-4); ) { if (is_shift_jis (*from)) { int code; switch (shifted) { @@ -736,6 +740,7 @@ static char *sj_to_jis7(char *from, BOOL overwrite) Convert FROM contain 7 bits JIS(junet) codes to SHIFT JIS codes return converted buffer ********************************************************************/ + static char *junet_to_sj(char *from, BOOL overwrite) { char *out; @@ -744,7 +749,7 @@ static char *junet_to_sj(char *from, BOOL overwrite) shifted = _KJ_ROMAN; save = (char *) from; - for (out = cvtbuf; *from;) { + for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-3);) { if (is_esc (*from)) { if (is_so1 (from[1]) && is_so2 (from[2])) { shifted = _KJ_KANJI; @@ -800,7 +805,7 @@ static char *sj_to_junet(char *from, BOOL overwrite) shifted = _KJ_ROMAN; save = (char *) from; - for (out = cvtbuf; *from; ) { + for (out = cvtbuf; *from && (out - cvtbuf < sizeof(cvtbuf)-4); ) { if (is_shift_jis (*from)) { int code; switch (shifted) { @@ -867,7 +872,7 @@ static char *hex_to_sj(char *from, BOOL overwrite) sp = (char *) from; dp = cvtbuf; - while (*sp) { + while (*sp && (dp - cvtbuf < sizeof(cvtbuf)-3)) { if (*sp == hex_tag && isxdigit((int)sp[1]) && isxdigit((int)sp[2])) { *dp++ = (hex2bin (sp[1])<<4) | (hex2bin (sp[2])); sp += 3; @@ -892,7 +897,7 @@ static char *sj_to_hex(char *from, BOOL overwrite) sp = (unsigned char*) from; dp = (unsigned char*) cvtbuf; - while (*sp) { + while (*sp && (((char *)dp)- cvtbuf < sizeof(cvtbuf)-7)) { if (is_kana(*sp)) { *dp++ = hex_tag; *dp++ = bin2hex (((*sp)>>4)&0x0f); @@ -929,7 +934,7 @@ static char *cap_to_sj(char *from, BOOL overwrite) sp = (char *) from; dp = cvtbuf; - while (*sp) { + while (*sp && (dp- cvtbuf < sizeof(cvtbuf)-2)) { /* * The only change between this and hex_to_sj is here. sj_to_cap only * translates characters greater or equal to 0x80 - make sure that here @@ -960,7 +965,7 @@ static char *sj_to_cap(char *from, BOOL overwrite) sp = (unsigned char*) from; dp = (unsigned char*) cvtbuf; - while (*sp) { + while (*sp && (((char *)dp) - cvtbuf < sizeof(cvtbuf)-4)) { if (*sp >= 0x80) { *dp++ = hex_tag; *dp++ = bin2hex (((*sp)>>4)&0x0f); diff --git a/source3/lib/md4.c b/source3/lib/md4.c index 56c9e02ffb..30f2b6b8c6 100644 --- a/source3/lib/md4.c +++ b/source3/lib/md4.c @@ -101,7 +101,7 @@ static void mdfour64(uint32 *M) X[j] = 0; } -static void copy64(uint32 *M, const unsigned char *in) +static void copy64(uint32 *M, unsigned char *in) { int i; @@ -119,7 +119,7 @@ static void copy4(unsigned char *out,uint32 x) } /* produce a md4 message digest from data of length n bytes */ -void mdfour(unsigned char *out, const unsigned char *in, int n) +void mdfour(unsigned char *out, unsigned char *in, int n) { unsigned char buf[128]; uint32 M[16]; diff --git a/source3/lib/pidfile.c b/source3/lib/pidfile.c index 6fc64aafe2..726e8c1f21 100644 --- a/source3/lib/pidfile.c +++ b/source3/lib/pidfile.c @@ -39,7 +39,7 @@ pid_t pidfile_pid(char *name) slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_lockdir(), name); - fd = open(pidFile, O_NONBLOCK | O_RDWR); + fd = sys_open(pidFile, O_NONBLOCK | O_RDWR, 0644); if (fd == -1) { return 0; } @@ -52,7 +52,7 @@ pid_t pidfile_pid(char *name) ret = atoi(pidstr); - if (!process_exists(ret)) { + if (!process_exists((pid_t)ret)) { goto ok; } @@ -76,14 +76,14 @@ void pidfile_create(char *name) int fd; char buf[20]; pstring pidFile; - int pid; + pid_t pid; slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_lockdir(), name); pid = pidfile_pid(name); if (pid != 0) { DEBUG(0,("ERROR: %s is already running. File %s exists and process id %d is running.\n", - name, pidFile, pid)); + name, pidFile, (int)pid)); exit(1); } @@ -109,4 +109,3 @@ void pidfile_create(char *name) } /* Leave pid file open & locked for the duration... */ } - diff --git a/source3/lib/replace.c b/source3/lib/replace.c index c6a4259417..6a492f977c 100644 --- a/source3/lib/replace.c +++ b/source3/lib/replace.c @@ -70,7 +70,7 @@ Corrections by richard.kettlewell@kewill.com epoch = (t->tm_year - 70) * YEAR + ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY; - y = t->tm_year; + y = t->tm_year + 1900; m = 0; for(i = 0; i < t->tm_mon; i++) { @@ -168,7 +168,6 @@ Corrections by richard.kettlewell@kewill.com struct group *g; char *gr; - setgrent(); grouplst[0] = id; i = 1; while (i < NGROUPS_MAX && @@ -188,7 +187,7 @@ Corrections by richard.kettlewell@kewill.com } } endgrent(); - return(setgroups(i,grouplst)); + return(sys_setgroups(i,grouplst)); #endif /* HAVE_SETGROUPS */ } #endif /* HAVE_INITGROUPS */ diff --git a/source3/lib/signal.c b/source3/lib/signal.c index bb1c6fe189..5651e942d7 100644 --- a/source3/lib/signal.c +++ b/source3/lib/signal.c @@ -22,22 +22,51 @@ #include "includes.h" - /**************************************************************************** -catch child exits + Catch child exits and reap the child zombie status. ****************************************************************************/ + static void sig_cld(int signum) { - while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) ; + while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) + ; + + /* + * Turns out it's *really* important not to + * restore the signal handler here if we have real POSIX + * signal handling. If we do, then we get the signal re-delivered + * immediately - hey presto - instant loop ! JRA. + */ +#if !defined(HAVE_SIGACTION) CatchSignal(SIGCLD, sig_cld); +#endif } +/**************************************************************************** +catch child exits - leave status; +****************************************************************************/ +static void sig_cld_leave_status(int signum) +{ + /* + * Turns out it's *really* important not to + * restore the signal handler here if we have real POSIX + * signal handling. If we do, then we get the signal re-delivered + * immediately - hey presto - instant loop ! JRA. + */ + +#if !defined(HAVE_SIGACTION) + CatchSignal(SIGCLD, sig_cld_leave_status); +#else + ; +#endif +} /******************************************************************* -block sigs + Block sigs. ********************************************************************/ + void BlockSignals(BOOL block,int signum) { #ifdef HAVE_SIGPROCMASK @@ -63,14 +92,13 @@ void BlockSignals(BOOL block,int signum) #endif } - - /******************************************************************* -catch a signal. This should implement the following semantics: + Catch a signal. This should implement the following semantics: -1) the handler remains installed after being called -2) the signal should be blocked during handler execution + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. ********************************************************************/ + void CatchSignal(int signum,void (*handler)(int )) { #ifdef HAVE_SIGACTION @@ -80,23 +108,35 @@ void CatchSignal(int signum,void (*handler)(int )) act.sa_handler = handler; #ifdef SA_RESTART - act.sa_flags = SA_RESTART; + /* + * We *want* SIGALRM to interrupt a system call. + */ + if(signum != SIGALRM) + act.sa_flags = SA_RESTART; #endif sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask,signum); sigaction(signum,&act,NULL); -#else +#else /* !HAVE_SIGACTION */ /* FIXME: need to handle sigvec and systems with broken signal() */ signal(signum, handler); #endif } - - /******************************************************************* -ignore SIGCLD via whatever means is necessary for this OS + Ignore SIGCLD via whatever means is necessary for this OS. ********************************************************************/ + void CatchChild(void) { CatchSignal(SIGCLD, sig_cld); } + +/******************************************************************* + Catch SIGCLD but leave the child around so it's status can be reaped. +********************************************************************/ + +void CatchChildLeaveStatus(void) +{ + CatchSignal(SIGCLD, sig_cld_leave_status); +} diff --git a/source3/lib/smbrun.c b/source3/lib/smbrun.c index da7632a67a..5a016cd5cd 100644 --- a/source3/lib/smbrun.c +++ b/source3/lib/smbrun.c @@ -28,7 +28,7 @@ extern int DEBUGLEVEL; /**************************************************************************** This is a utility function of smbrun(). It must be called only from -the child as it may leave the caller in a privilaged state. +the child as it may leave the caller in a privileged state. ****************************************************************************/ static BOOL setup_stdout_file(char *outfile,BOOL shared) { @@ -40,14 +40,9 @@ static BOOL setup_stdout_file(char *outfile,BOOL shared) close(1); if (shared) { - /* become root - unprivilaged users can't delete these files */ -#ifdef HAVE_SETRESUID - setresgid(0,0,0); - setresuid(0,0,0); -#else - setuid(0); - seteuid(0); -#endif + /* become root - unprivileged users can't delete these files */ + gain_root_privilege(); + gain_root_group_privilege(); } if(sys_stat(outfile, &st) == 0) { @@ -85,9 +80,10 @@ if shared is not set then open the file with O_EXCL set ****************************************************************************/ int smbrun(char *cmd,char *outfile,BOOL shared) { - int fd,pid; - int uid = current_user.uid; - int gid = current_user.gid; + int fd; + pid_t pid; + uid_t uid = current_user.uid; + gid_t gid = current_user.gid; /* * Lose any kernel oplock capabilities we may have. @@ -110,7 +106,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared) } slprintf(syscmd,sizeof(syscmd)-1,"%s %d %d \"(%s 2>&1) > %s\"", - path,uid,gid,cmd, + path,(int)uid,(int)gid,cmd, outfile?outfile:"/dev/null"); DEBUG(5,("smbrun - running %s ",syscmd)); @@ -120,17 +116,52 @@ int smbrun(char *cmd,char *outfile,BOOL shared) #else /* in this newer method we will exec /bin/sh with the correct arguments, after first setting stdout to point at the file */ - - if ((pid=fork())) { + + /* + * We need to temporarily stop CatchChild from eating + * SIGCLD signals as it also eats the exit status code. JRA. + */ + + CatchChildLeaveStatus(); + + if ((pid=fork()) < 0) { + DEBUG(0,("smbrun: fork failed with error %s\n", strerror(errno) )); + CatchChild(); + return errno; + } + + if (pid) { + /* + * Parent. + */ int status=0; + pid_t wpid; + + /* the parent just waits for the child to exit */ - if (sys_waitpid(pid,&status,0) != pid) { - DEBUG(2,("waitpid(%d) : %s\n",pid,strerror(errno))); + while((wpid = sys_waitpid(pid,&status,0)) < 0) { + if(errno == EINTR) { + errno = 0; + continue; + } + break; + } + + CatchChild(); + + if (wpid != pid) { + DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno))); return -1; } +#if defined(WIFEXITED) && defined(WEXITSTATUS) + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } +#endif return status; } + CatchChild(); /* we are in the child. we exec /bin/sh to do the work for us. we don't directly exec the command we want because it may be a @@ -141,25 +172,14 @@ int smbrun(char *cmd,char *outfile,BOOL shared) exit(80); } - /* now completely lose our privilages. This is a fairly paranoid + /* now completely lose our privileges. This is a fairly paranoid way of doing it, but it does work on all systems that I know of */ -#ifdef HAVE_SETRESUID - setresgid(0,0,0); - setresuid(0,0,0); - setresgid(gid,gid,gid); - setresuid(uid,uid,uid); -#else - setuid(0); - seteuid(0); - setgid(gid); - setegid(gid); - setuid(uid); - seteuid(uid); -#endif - + + become_user_permanently(uid, gid); + if (getuid() != uid || geteuid() != uid || getgid() != gid || getegid() != gid) { - /* we failed to lose our privilages - do not execute + /* we failed to lose our privileges - do not execute the command */ exit(81); /* we can't print stuff at this stage, instead use exit codes for debugging */ diff --git a/source3/lib/snprintf.c b/source3/lib/snprintf.c index 5798732643..f149d3e667 100644 --- a/source3/lib/snprintf.c +++ b/source3/lib/snprintf.c @@ -581,8 +581,21 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, { int signvalue = 0; LDOUBLE ufvalue; +#ifndef HAVE_FCVT char iconvert[20]; char fconvert[20]; +#else + char iconvert[311]; + char fconvert[311]; + char *result; + int dec_pt, sig; + int r_length; +# ifdef HAVE_FCVTL + extern char *fcvtl(long double value, int ndigit, int *decpt, int *sign); +# else + extern char *fcvt(double value, int ndigit, int *decpt, int *sign); +# endif +#endif int iplace = 0; int fplace = 0; int padlen = 0; /* amount to pad */ @@ -613,6 +626,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ #endif +#ifndef HAVE_FCVT intpart = (long)ufvalue; /* @@ -655,7 +669,53 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, } while(fracpart && (fplace < 20)); if (fplace == 20) fplace--; fconvert[fplace] = 0; +#else /* use fcvt() */ + if (max > 310) + max = 310; +# ifdef HAVE_FCVTL + result = fcvtl(ufvalue, max, &dec_pt, &sig); +# else + result = fcvt(ufvalue, max, &dec_pt, &sig); +# endif + + r_length = strlen(result); + + if (r_length == 0) + { + result[0] = '0'; + result[1] = '\0'; + r_length = 1; + } + + if (dec_pt <= 0) + { + iplace = 1; + iconvert[0] = '0'; + iconvert[1] = '\0'; + + fplace = 0; + + while(r_length) + fconvert[fplace++] = result[--r_length]; + while(dec_pt < 0) + fconvert[fplace++] = '0'; + } + else + { + int c; + + iplace=0; + for(c=dec_pt; c; iconvert[iplace++] = result[--c]); + iconvert[iplace] = '\0'; + + result += dec_pt; + fplace = 0; + + for(c=(r_length-dec_pt); c; fconvert[fplace++] = result[--c]); + } +#endif /* fcvt */ + /* -1 for decimal point, another -1 if we are printing a sign */ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); zpadlen = max - fplace; @@ -791,7 +851,7 @@ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) NULL }; double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, - 0.9996, 1.996, 4.136, 0}; + 0.9996, 1.996, 4.136, 6442452944.1234, 0}; char *int_fmt[] = { "%-1.5d", "%1.5d", diff --git a/source3/lib/system.c b/source3/lib/system.c index f9de800bd3..a59f94a6a9 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -60,7 +60,7 @@ static int pollfd(int fd) return(r); } -int sys_select(int maxfd, fd_set *fds, fd_set *w_fds, struct timeval *tval) +int sys_select(int maxfd, fd_set *fds,struct timeval *tval) { fd_set fds2; int counter=0; @@ -90,7 +90,7 @@ int sys_select(int maxfd, fd_set *fds, fd_set *w_fds, struct timeval *tval) } #else /* !NO_SELECT */ -int sys_select(int maxfd, fd_set *r_fds, fd_set *w_fds, struct timeval *tval) +int sys_select(int maxfd, fd_set *fds,struct timeval *tval) { #ifdef USE_POLL struct pollfd pfd[256]; @@ -131,8 +131,7 @@ int sys_select(int maxfd, fd_set *r_fds, fd_set *w_fds, struct timeval *tval) do { if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2)); errno = 0; - selrtn = select(maxfd,SELECT_CAST r_fds,SELECT_CAST w_fds, - NULL,tval?&t2:NULL); + selrtn = select(maxfd,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL); } while (selrtn<0 && errno == EINTR); return(selrtn); @@ -141,16 +140,54 @@ int sys_select(int maxfd, fd_set *r_fds, fd_set *w_fds, struct timeval *tval) #endif /* NO_SELECT */ /******************************************************************* + A wrapper for usleep in case we don't have one. +********************************************************************/ + +int sys_usleep(long usecs) +{ +#ifndef HAVE_USLEEP + struct timeval tval; +#endif + + /* + * We need this braindamage as the glibc usleep + * is not SPEC1170 complient... grumble... JRA. + */ + + if(usecs < 0 || usecs > 1000000) { + errno = EINVAL; + return -1; + } + +#if HAVE_USLEEP + usleep(usecs); + return 0; +#else /* HAVE_USLEEP */ + /* + * Fake it with select... + */ + tval.tv_sec = 0; + tval.tv_usec = usecs/1000; + select(0,NULL,NULL,NULL,&tval); + return 0; +#endif /* HAVE_USLEEP */ +} + +/******************************************************************* A stat() wrapper that will deal with 64 bit filesizes. ********************************************************************/ int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf) { -#if defined(HAVE_OFF64_T) && defined(HAVE_STAT64) - return stat64(fname, sbuf); + int ret; +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64) + ret = stat64(fname, sbuf); #else - return stat(fname, sbuf); + ret = stat(fname, sbuf); #endif + /* we always want directories to appear zero size */ + if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + return ret; } /******************************************************************* @@ -159,11 +196,15 @@ int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf) int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf) { -#if defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64) - return fstat64(fd, sbuf); + int ret; +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64) + ret = fstat64(fd, sbuf); #else - return fstat(fd, sbuf); + ret = fstat(fd, sbuf); #endif + /* we always want directories to appear zero size */ + if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + return ret; } /******************************************************************* @@ -172,11 +213,15 @@ int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf) int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf) { -#if defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64) - return lstat64(fname, sbuf); + int ret; +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64) + ret = lstat64(fname, sbuf); #else - return lstat(fname, sbuf); + ret = lstat(fname, sbuf); #endif + /* we always want directories to appear zero size */ + if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + return ret; } /******************************************************************* @@ -185,7 +230,7 @@ int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf) int sys_ftruncate(int fd, SMB_OFF_T offset) { -#if defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64) return ftruncate64(fd, offset); #else return ftruncate(fd, offset); @@ -198,7 +243,7 @@ int sys_ftruncate(int fd, SMB_OFF_T offset) SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence) { -#if defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64) return lseek64(fd, offset, whence); #else return lseek(fd, offset, whence); @@ -211,8 +256,10 @@ SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence) int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence) { -#if defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64) return fseek64(fp, offset, whence); +#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64) + return fseeko64(fp, offset, whence); #else return fseek(fp, offset, whence); #endif @@ -224,8 +271,10 @@ int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence) SMB_OFF_T sys_ftell(FILE *fp) { -#if defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64) return (SMB_OFF_T)ftell64(fp); +#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64) + return (SMB_OFF_T)ftello64(fp); #else return (SMB_OFF_T)ftell(fp); #endif @@ -237,7 +286,7 @@ SMB_OFF_T sys_ftell(FILE *fp) int sys_creat(const char *path, mode_t mode) { -#if defined(HAVE_CREAT64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64) return creat64(path, mode); #else /* @@ -254,7 +303,7 @@ int sys_creat(const char *path, mode_t mode) int sys_open(const char *path, int oflag, mode_t mode) { -#if defined(HAVE_OPEN64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64) return open64(path, oflag, mode); #else return open(path, oflag, mode); @@ -267,26 +316,43 @@ int sys_open(const char *path, int oflag, mode_t mode) FILE *sys_fopen(const char *path, const char *type) { -#if defined(HAVE_FOPEN64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64) return fopen64(path, type); #else return fopen(path, type); #endif } +#if defined(HAVE_MMAP) + /******************************************************************* An mmap() wrapper that will deal with 64 bit filesizes. ********************************************************************/ void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, SMB_OFF_T offset) { -#if defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64) return mmap64(addr, len, prot, flags, fd, offset); #else return mmap(addr, len, prot, flags, fd, offset); #endif } +#endif /* HAVE_MMAP */ + +/******************************************************************* + A readdir wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64) + return readdir64(dirp); +#else + return readdir(dirp); +#endif +} + /******************************************************************* The wait() calls vary between systems ********************************************************************/ @@ -305,18 +371,19 @@ system wrapper for getwd ********************************************************************/ char *sys_getwd(char *s) { - char *wd; + char *wd; #ifdef HAVE_GETCWD - wd = (char *)getcwd(s, sizeof (pstring)); + wd = (char *)getcwd(s, sizeof (pstring)); #else - wd = (char *)getwd(s); + wd = (char *)getwd(s); #endif - return wd; + return wd; } /******************************************************************* chown isn't used much but OS/2 doesn't have it ********************************************************************/ + int sys_chown(const char *fname,uid_t uid,gid_t gid) { #ifndef HAVE_CHOWN @@ -413,9 +480,12 @@ BOOL set_process_capability( uint32 cap_flag, BOOL enable ) if (cap_set_proc(cap) == -1) { DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n", strerror(errno))); + cap_free(cap); return False; } + cap_free(cap); + DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); } #endif @@ -447,9 +517,12 @@ BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable ) if (cap_set_proc(cap) == -1) { DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", strerror(errno))); + cap_free(cap); return False; } + cap_free(cap); + DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); } #endif @@ -516,7 +589,8 @@ int sys_getgroups(int setlen, gid_t *gidset) return -1; } - if (setlen == 0) setlen = 1; + if (setlen == 0) + setlen = 1; if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) { DEBUG(0,("sys_getgroups: Malloc fail.\n")); @@ -538,6 +612,62 @@ int sys_getgroups(int setlen, gid_t *gidset) #endif /* HAVE_BROKEN_GETGROUPS */ } +#ifdef HAVE_SETGROUPS + +/************************************************************************** + Wrapper for setgroups. Deals with broken (int) case. Automatically used + if we have broken getgroups. +****************************************************************************/ + +int sys_setgroups(int setlen, gid_t *gidset) +{ +#if !defined(HAVE_BROKEN_GETGROUPS) + return setgroups(setlen, gidset); +#else + + GID_T *group_list; + int i ; + + if (setlen == 0) + return 0 ; + +#ifdef NGROUPS_MAX + if (setlen > NGROUPS_MAX) { + errno = EINVAL; + return -1; + } +#endif + + /* + * Broken case. We need to allocate a + * GID_T array of size setlen. + */ + + if (setlen == 0) + setlen = 1; + + if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) { + DEBUG(0,("sys_setgroups: Malloc fail.\n")); + return -1; + } + + for(i = 0; i < setlen; i++) + group_list[i] = (GID_T) gidset[i]; + + if(setgroups(setlen, group_list) != 0) { + int saved_errno = errno; + free((char *)group_list); + errno = saved_errno; + return -1; + } + + free((char *)group_list); + return 0 ; +#endif /* HAVE_BROKEN_GETGROUPS */ +} + +#endif /* HAVE_SETGROUPS */ + /* * We only wrap pw_name and pw_passwd for now as these * are the only potentially modified fields. @@ -547,7 +677,7 @@ int sys_getgroups(int setlen, gid_t *gidset) Helper function for getpwnam/getpwuid wrappers. ****************************************************************************/ -struct passwd *copy_passwd_struct(struct passwd *pass) +static struct passwd *setup_pwret(struct passwd *pass) { static pstring pw_name; static pstring pw_passwd; @@ -558,25 +688,16 @@ struct passwd *copy_passwd_struct(struct passwd *pass) return NULL; } - if (pass == &pw_ret) - { - /* catch silly error where buffer was already copied */ - DEBUG(0,("copy_passwd_struct: can't copy internal buffer!\n")); - return NULL; - } - memcpy((char *)&pw_ret, pass, sizeof(struct passwd)); if (pass->pw_name) { - pw_name[0] = '\0'; pw_ret.pw_name = pw_name; pstrcpy(pw_ret.pw_name, pass->pw_name); } if (pass->pw_passwd) { - pw_passwd[0] = '\0'; pw_ret.pw_passwd = pw_passwd; pstrcpy(pw_ret.pw_passwd, pass->pw_passwd); } @@ -590,7 +711,7 @@ struct passwd *copy_passwd_struct(struct passwd *pass) struct passwd *sys_getpwnam(const char *name) { - return copy_passwd_struct(getpwnam(name)); + return setup_pwret(getpwnam(name)); } /************************************************************************** @@ -599,5 +720,5 @@ struct passwd *sys_getpwnam(const char *name) struct passwd *sys_getpwuid(uid_t uid) { - return copy_passwd_struct(getpwuid(uid)); + return setup_pwret(getpwuid(uid)); } diff --git a/source3/lib/time.c b/source3/lib/time.c index c332b906a0..5fd260e5c9 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -247,7 +247,7 @@ 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 nt_time_to_unix(const NTTIME *nt) +time_t nt_time_to_unix(NTTIME *nt) { double d; time_t ret; @@ -298,6 +298,13 @@ void unix_to_nt_time(NTTIME *nt, time_t t) { double d; + if (t==0) + { + nt->low = 0; + nt->high = 0; + return; + } + /* this converts GMT to kludge-GMT */ t -= LocTimeDiff(t) - serverzone; @@ -309,15 +316,6 @@ void unix_to_nt_time(NTTIME *nt, time_t t) nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); } -/**************************************************************************** -initialise an NTTIME to -1, which means "unknown" or "don't expire" -****************************************************************************/ - -void init_nt_time(NTTIME *nt) -{ - nt->high = 0x7FFFFFFF; - nt->low = 0xFFFFFFFF; -} /**************************************************************************** take an NTTIME structure, containing high / low time. convert to unix time. @@ -506,21 +504,57 @@ char *http_timestring(time_t t) /**************************************************************************** - return the date and time as a string + Return the date and time as a string ****************************************************************************/ -char *timestring(void ) + +char *timestring(BOOL hires) { static fstring TimeBuf; - time_t t = time(NULL); - struct tm *tm = LocalTime(&t); + struct timeval tp; + time_t t; + struct tm *tm; + if (hires) { + GetTimeOfDay(&tp); + t = (time_t)tp.tv_sec; + } else { + t = time(NULL); + } + tm = LocalTime(&t); if (!tm) { - slprintf(TimeBuf,sizeof(TimeBuf)-1,"%ld seconds since the Epoch",(long)t); + if (hires) { + slprintf(TimeBuf, + sizeof(TimeBuf)-1, + "%ld.%06ld seconds since the Epoch", + (long)tp.tv_sec, + (long)tp.tv_usec); + } else { + slprintf(TimeBuf, + sizeof(TimeBuf)-1, + "%ld seconds since the Epoch", + (long)t); + } } else { #ifdef HAVE_STRFTIME - strftime(TimeBuf,100,"%Y/%m/%d %T",tm); + if (hires) { + strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm); + slprintf(TimeBuf+strlen(TimeBuf), + sizeof(TimeBuf)-1 - strlen(TimeBuf), + ".%06ld", + (long)tp.tv_usec); + } else { + strftime(TimeBuf,100,"%Y/%m/%d %H:%M:%S",tm); + } #else - fstrcpy(TimeBuf, asctime(tm)); + if (hires)() { + slprintf(TimeBuf, + sizeof(TimeBuf)-1, + "%s.%06ld", + asctime(tm), + (long)tp.tv_usec); + } else { + fstrcpy(TimeBuf, asctime(tm)); + } #endif } return(TimeBuf); diff --git a/source3/lib/username.c b/source3/lib/username.c index 23bdb54faf..9a189980d5 100644 --- a/source3/lib/username.c +++ b/source3/lib/username.c @@ -27,306 +27,31 @@ static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) ( static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (char *), int N); /**************************************************************************** - Since getpwnam() makes samba really slow with the NT-domain code - (reading /etc/passwd again and again and again), here is an implementation - of very simple passwd cache + Get a users home directory. ****************************************************************************/ -#define PASSWD_HASH_SIZE 1009 -/* The hashtable is rebuild every 15 seconds */ -#define PASSWD_HASH_AGE 15 -struct passwd_hash_entry { - int entry; - int next; -}; - -struct passwd_hash_table_s { - struct passwd *passwds; - int passwds_size; - int *names; - int *uids; - struct passwd_hash_entry *entries; - int entries_size; - struct timeval build_time; -} passwd_hash_table = { - NULL,0,NULL,NULL,NULL,0,{0,0} -}; - -static int name_hash_function(const char *name) -{ - /* I guess that there must be better hash functions. This one was the - * first to come into mind :) */ - unsigned int value=0; - while (*name) { - value=(value<<8)|(unsigned char)(*name); - if (value>1048576) value=value%PASSWD_HASH_SIZE; - name++; - } - value=value%PASSWD_HASH_SIZE; - return value; -} - -static int uid_hash_function(uid_t uid) -{ - return uid%PASSWD_HASH_SIZE; -} - -static BOOL build_passwd_hash_table(void) +char *get_user_home_dir(char *user) { - struct passwd_hash_table_s *pht=&passwd_hash_table; /* Convenience */ - int num_passwds=0; - int num_entries=0; - struct passwd *pass; - int i; - int name_i,uid_i; - - DEBUG(3,("Building passwd hash table\n")); - /* Free the allocated strings in old hash table */ - for (i=0;i<pht->passwds_size;i++) { - free(pht->passwds[i].pw_name); - free(pht->passwds[i].pw_passwd); - free(pht->passwds[i].pw_gecos); - free(pht->passwds[i].pw_dir); - free(pht->passwds[i].pw_shell); - } - - /* Initialize hash table if first table build */ - if (pht->passwds_size==0) { - DEBUG(3,("Building passwd hash table for the first time\n")); - pht->passwds=malloc(sizeof(struct passwd)*64); /* A reasonable default */ - pht->passwds_size=64; - } - if (pht->names==NULL) { - pht->names=malloc(sizeof(struct passwd_hash_entry *)*PASSWD_HASH_SIZE); - } - if (pht->uids==NULL) { - pht->uids=malloc(sizeof(struct passwd_hash_entry *)*PASSWD_HASH_SIZE); - } - if (pht->entries==NULL) { - pht->entries=malloc(sizeof(struct passwd_hash_entry)*128); - pht->entries_size=128; - } - if (pht->passwds==NULL || pht->names==NULL || - pht->uids==NULL || pht->entries==NULL) { - goto fail; - } - - /* Clear out the hash table */ - for(i=0;i<PASSWD_HASH_SIZE;i++) pht->uids[i]=-1; - for(i=0;i<PASSWD_HASH_SIZE;i++) pht->names[i]=-1; - - /* Now do the build */ - setpwent(); - - while((pass=getpwent())) { - - /* Check that we have enough space */ - if (num_passwds==pht->passwds_size) { - struct passwd *new_passwds=NULL; - pht->passwds_size+=pht->passwds_size/2; - new_passwds=realloc(pht->passwds, - sizeof(struct passwd)*pht->passwds_size); - if (new_passwds==NULL) goto fail; - pht->passwds=new_passwds; - } - if (num_entries+1>=pht->entries_size) { - pht->entries_size+=pht->entries_size/2; - pht->entries=realloc(pht->entries, - sizeof(struct passwd_hash_entry)*pht->entries_size); - if (pht->entries==NULL) goto fail; - } + static struct passwd *pass; - /* Copy the passwd struct */ - memset(&pht->passwds[num_passwds],0,sizeof(struct passwd)); - pht->passwds[num_passwds].pw_uid=pass->pw_uid; - pht->passwds[num_passwds].pw_gid=pass->pw_gid; - if ( - (pht->passwds[num_passwds].pw_name=strdup(pass->pw_name))==NULL || - (pht->passwds[num_passwds].pw_passwd=strdup(pass->pw_passwd))==NULL || - (pht->passwds[num_passwds].pw_gecos=strdup(pass->pw_gecos))==NULL || - (pht->passwds[num_passwds].pw_dir=strdup(pass->pw_dir))==NULL || - (pht->passwds[num_passwds].pw_shell=strdup(pass->pw_shell))==NULL ) { - num_passwds++; - goto fail; - } - - /* Add to the hash table */ - /* Add the name */ - pht->entries[num_entries].entry=num_passwds; - name_i=name_hash_function(pass->pw_name); - pht->entries[num_entries].next=pht->names[name_i]; - pht->names[name_i]=num_entries; - num_entries++; - /* Add the uid */ - pht->entries[num_entries].entry=num_passwds; - uid_i=uid_hash_function(pass->pw_uid); - pht->entries[num_entries].next=pht->uids[uid_i]; - pht->uids[uid_i]=num_entries; - num_entries++; - - /* This entry has been done */ - num_passwds++; - } - endpwent(); - - if (pht->passwds_size>num_passwds) { - struct passwd *passwds; - passwds=realloc(pht->passwds,sizeof(pht->passwds[0])*num_passwds); - if (passwds==NULL) goto fail; - pht->passwds=passwds; - pht->passwds_size=num_passwds; - } - if (pht->entries_size>num_entries) { - struct passwd_hash_entry *entries; - entries=realloc(pht->entries,sizeof(pht->entries[0])*num_entries); - if (entries==NULL) goto fail; - pht->entries=entries; - pht->entries_size=num_entries; - } + pass = Get_Pwnam(user, False); - /* Mark the creation time */ - GetTimeOfDay(&pht->build_time); - /* Everything went smoothly. */ - return True; - - fail: - DEBUG(0,("Failed to create passwd hash table: %s",strerror(errno))); - /* OK: now the untested part. Normally this should never happen: - * Only running out of memory could cause this and even then - * we have enough trouble already. */ - while (num_passwds>0) { - num_passwds--; - free(pht->passwds[num_passwds].pw_name); - free(pht->passwds[num_passwds].pw_passwd); - free(pht->passwds[num_passwds].pw_gecos); - free(pht->passwds[num_passwds].pw_dir); - free(pht->passwds[num_passwds].pw_shell); - } - free(pht->entries); - free(pht->uids); - free(pht->names); - free(pht->passwds); - pht->passwds_size=0; - pht->entries_size=0; - /* Also mark fail time, so that retry will happen after PASSWD_HASH_AGE */ - GetTimeOfDay(&pht->build_time); - return False; + if (!pass) return(NULL); + return(pass->pw_dir); } -static BOOL have_passwd_hash(void) -{ - struct passwd_hash_table_s *pht=&passwd_hash_table; - struct timeval tv; - GetTimeOfDay(&tv); - /* I'm ignoring microseconds. If you think they matter, go ahead - * and implement them */ - if (tv.tv_sec - pht->build_time.tv_sec > PASSWD_HASH_AGE) { - return build_passwd_hash_table(); - } - return pht->passwds_size>0; -} - -struct passwd *hashed_getpwnam(const char *name) -{ - struct passwd_hash_table_s *pht=&passwd_hash_table; - - DEBUG(5,("getpwnam(%s)\n", name)); - - if (have_passwd_hash()) - { - int name_i=name_hash_function(name); - int hash_index=pht->names[name_i]; - while(hash_index!=-1) { - struct passwd *pass=&pht->passwds[pht->entries[hash_index].entry]; - if (strcmp(name,pass->pw_name)==0) { - DEBUG(5,("Found: %s:%s:%d:%d:%s:%s:%s\n", - pass->pw_name, - pass->pw_passwd, - pass->pw_uid, - pass->pw_gid, - pass->pw_gecos, - pass->pw_dir, - pass->pw_shell)); - return copy_passwd_struct(pass); - } - hash_index=pht->entries[hash_index].next; - } - - /* Not found */ - DEBUG(5,("%s not found\n",name)); - return NULL; - } - - /* Fall back to real getpwnam() */ - return sys_getpwnam(name); -} /******************************************************************* -turn a uid into a user name + Map a username from a dos name to a unix name by looking in the username + map. Note that this modifies the name in place. + This is the main function that should be called *once* on + any incoming or new username - in order to canonicalize the name. + This is being done to de-couple the case conversions from the user mapping + function. Previously, the map_username was being called + every time Get_Pwnam was called. + Returns True if username was changed, false otherwise. ********************************************************************/ -char *uidtoname(uid_t uid) -{ - static char name[40]; - struct passwd_hash_table_s *pht=&passwd_hash_table; - struct passwd *pass=NULL; - - DEBUG(5,("uidtoname(%d)\n",uid)); - if (have_passwd_hash()) { - int hash_index=pht->uids[uid_hash_function(uid)]; - while(hash_index!=-1) { - pass=&pht->passwds[pht->entries[hash_index].entry]; - if (pass->pw_uid==uid) { - DEBUG(5,("Found: %s:%s:%d:%d:%s:%s:%s\n", - pass->pw_name, - pass->pw_passwd, - pass->pw_uid, - pass->pw_gid, - pass->pw_gecos, - pass->pw_dir, - pass->pw_shell)); - return pass->pw_name; - } - hash_index=pht->entries[hash_index].next; - } - DEBUG(5,("Hash miss")); - pass=NULL; - } else { - /* No hash table, fall back to getpwuid */ - pass = getpwuid(uid); - } - if (pass) return(pass->pw_name); - slprintf(name, sizeof(name) - 1, "%d",(int)uid); - return(name); -} - -/**************************************************************************** -get a users home directory. -****************************************************************************/ -char *get_unixhome_dir(char *user) -{ - const struct passwd *pass; - static pstring home_dir; - pass = Get_Pwnam(user, False); - - if (pass == NULL || pass->pw_dir == NULL) return(NULL); - - pstrcpy(home_dir, pass->pw_dir); - DEBUG(10,("get_smbhome_dir: returning %s for user %s\n", home_dir, user)); - return home_dir; -} - - -/******************************************************************* -map a username from a dos name to a unix name by looking in the username -map. Note that this modifies the name in place. -This is the main function that should be called *once* on -any incoming or new username - in order to canonicalize the name. -This is being done to de-couple the case conversions from the user mapping -function. Previously, the map_username was being called -every time Get_Pwnam was called. -Returns True if username was changed, false otherwise. -********************************************************************/ BOOL map_username(char *user) { static BOOL initialised=False; @@ -420,38 +145,36 @@ BOOL map_username(char *user) return mapped_user; } - /**************************************************************************** Get_Pwnam wrapper ****************************************************************************/ + static struct passwd *_Get_Pwnam(char *s) { - struct passwd *ret; + struct passwd *ret; - ret = hashed_getpwnam(s); + ret = sys_getpwnam(s); + if (ret) { #ifdef HAVE_GETPWANAM - if (ret) - { - struct passwd_adjunct *pwret; - pwret = getpwanam(s); - if (pwret != NULL && pwret->pwa_passwd != NULL) - { - pstrcpy(ret->pw_passwd, pwret->pwa_passwd); - } - } + struct passwd_adjunct *pwret; + pwret = getpwanam(s); + if (pwret && pwret->pwa_passwd) { + pstrcpy(ret->pw_passwd,pwret->pwa_passwd); + } #endif + } - return ret; + return(ret); } + /**************************************************************************** -a wrapper for getpwnam() that tries with all lower and all upper case -if the initial name fails. Also tried with first letter capitalised -Note that this can change user! Function returns const to emphasise -the fact that most of the members of the struct passwd * returned are -dynamically allocated. + A wrapper for getpwnam() that tries with all lower and all upper case + if the initial name fails. Also tried with first letter capitalised + Note that this can change user! ****************************************************************************/ -const struct passwd *Get_Pwnam(char *user,BOOL allow_change) + +struct passwd *Get_Pwnam(char *user,BOOL allow_change) { fstring user2; int last_char; @@ -469,33 +192,39 @@ const struct passwd *Get_Pwnam(char *user,BOOL allow_change) } ret = _Get_Pwnam(user); - if (ret) return(ret); + if (ret) + return(ret); strlower(user); ret = _Get_Pwnam(user); - if (ret) return(ret); + if (ret) + return(ret); strupper(user); ret = _Get_Pwnam(user); - if (ret) return(ret); + if (ret) + return(ret); - /* try with first letter capitalised */ + /* Try with first letter capitalised. */ if (strlen(user) > 1) strlower(user+1); ret = _Get_Pwnam(user); - if (ret) return(ret); + if (ret) + return(ret); /* try with last letter capitalised */ strlower(user); last_char = strlen(user)-1; user[last_char] = toupper(user[last_char]); ret = _Get_Pwnam(user); - if (ret) return(ret); + if (ret) + return(ret); - /* try all combinations up to usernamelevel */ + /* Try all combinations up to usernamelevel. */ strlower(user); ret = uname_string_combinations(user, _Get_Pwnam, usernamelevel); - if (ret) return(ret); + if (ret) + return(ret); if (allow_change) fstrcpy(user,user2); @@ -504,8 +233,9 @@ const struct passwd *Get_Pwnam(char *user,BOOL allow_change) } /**************************************************************************** -check if a user is in a netgroup user list + Check if a user is in a netgroup user list. ****************************************************************************/ + static BOOL user_in_netgroup_list(char *user,char *ngname) { #ifdef HAVE_NETGROUP @@ -513,12 +243,9 @@ static BOOL user_in_netgroup_list(char *user,char *ngname) if (mydomain == NULL) yp_get_default_domain(&mydomain); - if(mydomain == NULL) - { + if(mydomain == NULL) { DEBUG(5,("Unable to get default yp domain\n")); - } - else - { + } else { DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", user, mydomain, ngname)); DEBUG(5,("innetgr is %s\n", @@ -533,78 +260,51 @@ static BOOL user_in_netgroup_list(char *user,char *ngname) } /**************************************************************************** -check if a user is in a UNIX user list + Check if a user is in a UNIX user list. ****************************************************************************/ + static BOOL user_in_group_list(char *user,char *gname) { -#ifdef HAVE_GETGRNAM - struct group *gptr; - char **member; - const struct passwd *pass = Get_Pwnam(user,False); - - if (pass) - { - gptr = getgrgid(pass->pw_gid); - if (gptr && strequal(gptr->gr_name,gname)) - return(True); - } - - gptr = (struct group *)getgrnam(gname); - - if (gptr) - { - member = gptr->gr_mem; - while (member && *member) - { - if (strequal(*member,user)) - return(True); - member++; - } - } +#ifdef HAVE_GETGRENT + struct group *gptr; + char **member; + struct passwd *pass = Get_Pwnam(user,False); + + if (pass) { + gptr = getgrgid(pass->pw_gid); + if (gptr && strequal(gptr->gr_name,gname)) + return(True); + } + + while ((gptr = (struct group *)getgrent())) { + if (!strequal(gptr->gr_name,gname)) + continue; + member = gptr->gr_mem; + while (member && *member) { + if (strequal(*member,user)) { + endgrent(); + return(True); + } + member++; + } + } + + endgrent(); #endif /* HAVE_GETGRNAM */ - return False; + return False; } /**************************************************************************** -check if a username is valid + Check if a user is in a user list - can check combinations of UNIX + and netgroup lists. ****************************************************************************/ -BOOL user_ok(char *user,int snum) -{ - pstring valid, invalid; - BOOL ret; - - StrnCpy(valid, lp_valid_users(snum), sizeof(pstring)); - StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring)); - - string_sub(valid,"%S",lp_servicename(snum)); - string_sub(invalid,"%S",lp_servicename(snum)); - - ret = !user_in_list(user,invalid); - - if (ret && valid && *valid) { - ret = user_in_list(user,valid); - } - - if (ret && lp_onlyuser(snum)) { - char *user_list = lp_username(snum); - string_sub(user_list,"%S",lp_servicename(snum)); - ret = user_in_list(user,user_list); - } - return(ret); -} - -/**************************************************************************** -check if a user is in a user list - can check combinations of UNIX -and netgroup lists. -****************************************************************************/ BOOL user_in_list(char *user,char *list) { pstring tok; char *p=list; - while (next_token(&p,tok,LIST_SEP, sizeof(tok))) - { + while (next_token(&p,tok,LIST_SEP, sizeof(tok))) { /* * Check raw username. */ @@ -616,8 +316,7 @@ BOOL user_in_list(char *user,char *list) * of UNIX and netgroups has been specified. */ - if(*tok == '@') - { + if(*tok == '@') { /* * Old behaviour. Check netgroup list * followed by UNIX list. @@ -626,11 +325,9 @@ BOOL user_in_list(char *user,char *list) return True; if(user_in_group_list(user,&tok[1])) return True; - } - else if (*tok == '+') - { - if(tok[1] == '&') - { + } else if (*tok == '+') { + + if(tok[1] == '&') { /* * Search UNIX list followed by netgroup. */ @@ -638,20 +335,20 @@ BOOL user_in_list(char *user,char *list) return True; if(user_in_netgroup_list(user,&tok[2])) return True; - } - else - { + + } else { + /* * Just search UNIX list. */ + if(user_in_group_list(user,&tok[1])) return True; } - } - else if (*tok == '&') - { - if(tok[1] == '&') - { + + } else if (*tok == '&') { + + if(tok[1] == '+') { /* * Search netgroup list followed by UNIX list. */ @@ -659,9 +356,7 @@ BOOL user_in_list(char *user,char *list) return True; if(user_in_group_list(user,&tok[2])) return True; - } - else - { + } else { /* * Just search netgroup list. */ @@ -675,15 +370,16 @@ BOOL user_in_list(char *user,char *list) /* The functions below have been taken from password.c and slightly modified */ /**************************************************************************** -apply a function to upper/lower case combinations -of a string and return true if one of them returns true. -try all combinations with N uppercase letters. -offset is the first char to try and change (start with 0) -it assumes the string starts lowercased + Apply a function to upper/lower case combinations + of a string and return true if one of them returns true. + Try all combinations with N uppercase letters. + offset is the first char to try and change (start with 0) + it assumes the string starts lowercased ****************************************************************************/ + static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(char *),int N) { - int len = strlen(s); + ssize_t len = (ssize_t)strlen(s); int i; struct passwd *ret; @@ -694,36 +390,36 @@ static struct passwd *uname_string_combinations2(char *s,int offset,struct passw if (N <= 0 || offset >= len) return(fn(s)); - - for (i=offset;i<(len-(N-1));i++) - - { - char c = s[i]; - if (!islower(c)) continue; - s[i] = toupper(c); - ret = uname_string_combinations2(s,i+1,fn,N-1); - if(ret) return(ret); - s[i] = c; - } + for (i=offset;i<(len-(N-1));i++) { + char c = s[i]; + if (!islower(c)) + continue; + s[i] = toupper(c); + ret = uname_string_combinations2(s,i+1,fn,N-1); + if(ret) + return(ret); + s[i] = c; + } return(NULL); } /**************************************************************************** -apply a function to upper/lower case combinations -of a string and return true if one of them returns true. -try all combinations with up to N uppercase letters. -offset is the first char to try and change (start with 0) -it assumes the string starts lowercased + Apply a function to upper/lower case combinations + of a string and return true if one of them returns true. + Try all combinations with up to N uppercase letters. + offset is the first char to try and change (start with 0) + it assumes the string starts lowercased ****************************************************************************/ + static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(char *),int N) { int n; struct passwd *ret; - for (n=1;n<=N;n++) - { + for (n=1;n<=N;n++) { ret = uname_string_combinations2(s,0,fn,n); - if(ret) return(ret); + if(ret) + return(ret); } return(NULL); } diff --git a/source3/lib/util.c b/source3/lib/util.c index 25769298be..8f904d486d 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -23,12 +23,34 @@ #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT)) #ifdef WITH_NISPLUS_HOME -#include <rpcsvc/nis.h> -#else -#include "rpcsvc/ypclnt.h" +#ifdef BROKEN_NISPLUS_INCLUDE_FILES +/* + * The following lines are needed due to buggy include files + * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and + * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA. + * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as + * an enum in /usr/include/rpcsvc/nis.h. + */ + +#if defined(GROUP) +#undef GROUP #endif + +#if defined(GROUP_OBJ) +#undef GROUP_OBJ #endif +#endif /* BROKEN_NISPLUS_INCLUDE_FILES */ + +#include <rpcsvc/nis.h> + +#else /* !WITH_NISPLUS_HOME */ + +#include "rpcsvc/ypclnt.h" + +#endif /* WITH_NISPLUS_HOME */ +#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */ + #ifdef WITH_SSL #include <ssl.h> #undef Realloc /* SSLeay defines this and samba has a function of this name */ @@ -71,8 +93,7 @@ fstring local_machine=""; fstring remote_arch="UNKNOWN"; static enum remote_arch_types ra_type = RA_UNKNOWN; fstring remote_proto="UNKNOWN"; -pstring myhostname=""; -pstring user_socket_options=""; +pstring user_socket_options=DEFAULT_SOCKET_OPTIONS; pstring sesssetup_user=""; pstring samlogon_user=""; @@ -85,23 +106,7 @@ char **my_netbios_names; static char *filename_dos(char *path,char *buf); -char *daynames[] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}; -char *daynames_short[] = {"M", "Tu", "W", "Th", "F", "Sa", "Su"}; - -/************************************************************* - initialise password databases, domain names, domain sid. -**************************************************************/ -BOOL init_myworkgroup(void) -{ - fstrcpy(global_myworkgroup, lp_workgroup()); - if (strequal(global_myworkgroup,"*")) - { - DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); - return False; - } - return True; -} /**************************************************************************** find a suitable temporary directory. The result should be copied immediately @@ -135,39 +140,19 @@ BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups) /**************************************************************************** -gets either a hex number (0xNNN) or decimal integer (NNN). -****************************************************************************/ -uint32 get_number(const char *tmp) -{ - if (strnequal(tmp, "0x", 2)) - { - return strtoul(tmp, (char**)NULL, 16); - } - else - { - return strtoul(tmp, (char**)NULL, 10); - } -} - -/**************************************************************************** like atoi but gets the value up to the separater character ****************************************************************************/ char *Atoic(char *p, int *n, char *c) { - if (!isdigit(*p)) + if (!isdigit((int)*p)) { DEBUG(5, ("Atoic: malformed number\n")); return NULL; } - (*n) = (int)get_number(p); + (*n) = atoi(p); - if (strnequal(p, "0x", 2)) - { - p += 2; - } - - while ((*p) && isdigit(*p)) + while ((*p) && isdigit((int)*p)) { p++; } @@ -181,19 +166,6 @@ char *Atoic(char *p, int *n, char *c) return p; } -uint32 *add_num_to_list(uint32 **num, int *count, int val) -{ - (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32)); - if ((*num) == NULL) - { - return NULL; - } - (*num)[(*count)] = val; - (*count)++; - - return (*num); -} - /************************************************************************* reads a list of numbers *************************************************************************/ @@ -211,10 +183,13 @@ char *get_numlist(char *p, uint32 **num, int *count) while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') { - if (add_num_to_list(num, count, val) == NULL) + (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32)); + if ((*num) == NULL) { return NULL; } + (*num)[(*count)] = val; + (*count)++; p++; } @@ -357,7 +332,7 @@ int name_mangle( char *In, char *Out, char name_type ) case '.': p[0] = len; p += (len + 1); - len = 0; + len = -1; break; default: p[len+1] = scope[i]; @@ -383,21 +358,6 @@ BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf) } /******************************************************************* - rename a unix file -********************************************************************/ -int file_rename(char *from, char *to) -{ - int rcode = rename (from, to); - - if (errno == EXDEV) - { - /* Rename across filesystems needed. */ - rcode = copy_reg (from, to); - } - return rcode; -} - -/******************************************************************* check a files mod time ********************************************************************/ time_t file_modtime(char *fname) @@ -432,7 +392,7 @@ BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st) /******************************************************************* returns the size in bytes of the named file ********************************************************************/ -SMB_OFF_T file_size(char *file_name) +SMB_OFF_T get_file_size(char *file_name) { SMB_STRUCT_STAT buf; buf.st_size = 0; @@ -460,6 +420,8 @@ char *attrib_string(uint16 mode) return(attrstr); } + + /**************************************************************************** make a file into unix format ****************************************************************************/ @@ -558,7 +520,7 @@ void smb_setlen(char *buf,int len) int set_message(char *buf,int num_words,int num_bytes,BOOL zero) { if (zero) - bzero(buf + smb_size,num_words*2 + num_bytes); + memset(buf + smb_size,'\0',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); @@ -605,8 +567,6 @@ int smb_offset(char *p,char *buf) return(PTR_DIFF(p,buf+4) + chain_size); } - - /******************************************************************* reduce a file name, removing .. elements. ********************************************************************/ @@ -617,7 +577,7 @@ void dos_clean_name(char *s) DEBUG(3,("dos_clean_name [%s]\n",s)); /* remove any double slashes */ - string_sub(s, "\\\\", "\\"); + all_string_sub(s, "\\\\", "\\", 0); while ((p = strstr(s,"\\..\\")) != NULL) { @@ -635,7 +595,7 @@ void dos_clean_name(char *s) trim_string(s,NULL,"\\.."); - string_sub(s, "\\.\\", "\\"); + all_string_sub(s, "\\.\\", "\\", 0); } /******************************************************************* @@ -648,7 +608,7 @@ void unix_clean_name(char *s) DEBUG(3,("unix_clean_name [%s]\n",s)); /* remove any double slashes */ - string_sub(s, "//","/"); + all_string_sub(s, "//","/", 0); /* Remove leading ./ characters */ if(strncmp(s, "./", 2) == 0) { @@ -676,7 +636,7 @@ void unix_clean_name(char *s) /******************************************************************* reduce a file name, removing .. elements and checking that -it is below dir in the heirachy. This uses GetWd() and so must be run +it is below dir in the heirachy. This uses dos_GetWd() and so must be run on the system that has the referenced file system. widelinks are allowed if widelinks is true @@ -697,25 +657,25 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks) *dir2 = *wd = *base_name = *newname = 0; if (widelinks) + { + unix_clean_name(s); + /* can't have a leading .. */ + if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/')) { - unix_clean_name(s); - /* can't have a leading .. */ - if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/')) - { - DEBUG(3,("Illegal file name? (%s)\n",s)); - return(False); - } + DEBUG(3,("Illegal file name? (%s)\n",s)); + return(False); + } - if (strlen(s) == 0) - pstrcpy(s,"./"); + if (strlen(s) == 0) + pstrcpy(s,"./"); - return(True); - } + return(True); + } DEBUG(3,("reduce_name [%s] [%s]\n",s,dir)); /* remove any double slashes */ - string_sub(s,"//","/"); + all_string_sub(s,"//","/",0); pstrcpy(base_name,s); p = strrchr(base_name,'/'); @@ -724,53 +684,52 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks) return(True); if (!dos_GetWd(wd)) - { - DEBUG(0,("couldn't getwd for %s %s\n",s,dir)); - return(False); - } + { + DEBUG(0,("couldn't getwd for %s %s\n",s,dir)); + return(False); + } if (dos_ChDir(dir) != 0) - { - DEBUG(0,("couldn't chdir to %s\n",dir)); - return(False); - } + { + DEBUG(0,("couldn't chdir to %s\n",dir)); + return(False); + } if (!dos_GetWd(dir2)) - { - DEBUG(0,("couldn't getwd for %s\n",dir)); - dos_ChDir(wd); - return(False); - } - + { + DEBUG(0,("couldn't getwd for %s\n",dir)); + dos_ChDir(wd); + return(False); + } - if (p && (p != base_name)) - { - *p = 0; - if (strcmp(p+1,".")==0) - p[1]=0; - if (strcmp(p+1,"..")==0) - *p = '/'; - } + if (p && (p != base_name)) + { + *p = 0; + if (strcmp(p+1,".")==0) + p[1]=0; + if (strcmp(p+1,"..")==0) + *p = '/'; + } if (dos_ChDir(base_name) != 0) - { - dos_ChDir(wd); - DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name)); - return(False); - } + { + dos_ChDir(wd); + DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name)); + return(False); + } if (!dos_GetWd(newname)) - { - dos_ChDir(wd); - DEBUG(2,("couldn't get wd for %s %s\n",s,dir2)); - return(False); - } + { + dos_ChDir(wd); + DEBUG(2,("couldn't get wd for %s %s\n",s,dir2)); + return(False); + } if (p && (p != base_name)) - { - pstrcat(newname,"/"); - pstrcat(newname,p+1); - } + { + pstrcat(newname,"/"); + pstrcat(newname,p+1); + } { size_t l = strlen(dir2); @@ -778,19 +737,19 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks) l--; if (strncmp(newname,dir2,l) != 0) - { - dos_ChDir(wd); - DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l)); - return(False); - } + { + dos_ChDir(wd); + DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l)); + return(False); + } if (relative) - { - if (newname[l] == '/') - pstrcpy(s,newname + l + 1); - else - pstrcpy(s,newname+l); - } + { + if (newname[l] == '/') + pstrcpy(s,newname + l + 1); + else + pstrcpy(s,newname+l); + } else pstrcpy(s,newname); } @@ -918,7 +877,7 @@ void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,ti else memcpy(buf+1,mask2,MIN(strlen(mask2),11)); - bzero(buf+21,DIR_STRUCT_SIZE-21); + memset(buf+21,'\0',DIR_STRUCT_SIZE-21); CVAL(buf,21) = mode; put_dos_date(buf,22,date); SSVAL(buf,26,size & 0xFFFF); @@ -1083,11 +1042,7 @@ static char *name_ptr(char *buf,int ofs) if ((c & 0xC0) == 0xC0) { - uint16 l; - char p[2]; - memcpy(p,buf+ofs,2); - p[0] &= ~0xC0; - l = RSVAL(p,0); + uint16 l = RSVAL(buf, ofs) & 0x3FFF; DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l)); return(buf + l); } @@ -1148,7 +1103,7 @@ void msleep(int t) FD_ZERO(&fds); errno = 0; - sys_select(0,&fds,NULL, &tval); + sys_select(0,&fds,&tval); GetTimeOfDay(&t2); tdiff = TvalDiff(&t1,&t2); @@ -1161,7 +1116,8 @@ void msleep(int t) * Does the actual matching. This is the 'original code' * used by the unix matcher. *********************************************************/ -static BOOL unix_do_match(char *str, char *regexp, int case_sig) + +BOOL unix_do_match(char *str, char *regexp, BOOL case_sig) { char *p; @@ -1226,7 +1182,7 @@ static BOOL unix_do_match(char *str, char *regexp, int case_sig) * This is the 'original code' used by the unix matcher. *********************************************************/ -static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2) +static BOOL unix_mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2) { char *p; pstring p1, p2; @@ -1286,9 +1242,14 @@ static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2) * 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. +* The win9x_semantics parameter is needed as Win9x matching +* is *actually different*. In Win9x, trailing '?' characters +* will only match the *exact* number of characters. Under +* DOS and NT they match any number. This makes no +* sense..... *********************************************************/ -BOOL do_match(char *str, char *regexp, int case_sig) +static BOOL do_match(char *str, char *regexp, int case_sig, BOOL win9x_semantics) { char *p; @@ -1312,7 +1273,7 @@ BOOL do_match(char *str, char *regexp, int case_sig) 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)) { + if(do_match(str,p,case_sig,win9x_semantics)) { return True; } if(!*str) { @@ -1345,10 +1306,12 @@ BOOL do_match(char *str, char *regexp, int case_sig) return(True); } - if (!*str && *p == '?') { - while (*p == '?') - p++; - return(!*p); + if (!win9x_semantics) { + if (!*str && *p == '?') { + while (*p == '?') + p++; + return(!*p); + } } if(!*str && (*p == '*' && p[1] == '\0')) { @@ -1358,6 +1321,15 @@ BOOL do_match(char *str, char *regexp, int case_sig) return False; } +/********************************************************* +* Routine to check if a given string matches exactly. +* Case can be significant or not. +**********************************************************/ + +BOOL exact_match(char *str, char *regexp, BOOL case_sig) +{ + return ((case_sig?strcmp(str,regexp):strcasecmp(str,regexp)) == 0); +} /********************************************************* * Routine to match a given string with a regexp - uses @@ -1367,18 +1339,37 @@ BOOL do_match(char *str, char *regexp, int case_sig) * This is the new 'NT style' matcher. *********************************************************/ -BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) +BOOL mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2) { char *p; pstring t_pattern, t_filename, te_pattern, te_filename; fstring ebase,eext,sbase,sext; - BOOL matched = False; + BOOL win9x_semantics = (get_remote_arch() == RA_WIN95) && trans2; + + /* special case - if it is exactly the same then it always matches! */ + if(exact_match(str, regexp, case_sig)) + return True; /* Make local copies of str and regexp */ pstrcpy(t_pattern,regexp); pstrcpy(t_filename,str); + if(trans2) { + + /* a special case for 16 bit apps */ + if (strequal(t_pattern,"????????.???")) + pstrcpy(t_pattern,"*"); + +#if 0 + /* + * Handle broken clients that send us old 8.3 format. + */ + pstring_sub(t_pattern,"????????","*"); + pstring_sub(t_pattern,".???",".*"); +#endif + } + #if 0 /* * Not sure if this is a good idea. JRA. @@ -1394,8 +1385,8 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) #endif /* Remove any *? and ** as they are meaningless */ - string_sub(t_pattern, "*?", "*"); - string_sub(t_pattern, "**", "*"); + pstring_sub(t_pattern, "*?", "*"); + pstring_sub(t_pattern, "**", "*"); if (strequal(t_pattern,"*")) return(True); @@ -1416,7 +1407,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) /* * Remove multiple "*." patterns. */ - string_sub(te_pattern, "*.*.", "*."); + pstring_sub(te_pattern, "*.*.", "*."); num_regexp_components = count_chars(te_pattern, '.'); num_path_components = count_chars(te_filename, '.'); @@ -1424,7 +1415,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) * 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); + matched = do_match( te_filename, te_pattern, case_sig, win9x_semantics); else { for( cp1 = te_pattern, cp2 = te_filename; cp1;) { fp = strchr(cp2, '.'); @@ -1434,14 +1425,24 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) if(rp) *rp = '\0'; - if(cp1[strlen(cp1)-1] == '*') + if(cp1[0] && cp1[strlen(cp1)-1] == '*') last_wcard_was_star = True; else last_wcard_was_star = False; - if(!do_match(cp2, cp1, case_sig)) + if(!do_match(cp2, cp1, case_sig, win9x_semantics)) break; + /* + * Ugly ! Special case for Win9x *only*. If filename is XXXX and pattern extension + * is '*' or all '?' then disallow match. + */ + + if (win9x_semantics) { + if (*cp2 == '\0' && str_is_all(cp1, '?')) + break; + } + cp1 = rp ? rp + 1 : NULL; cp2 = fp ? fp + 1 : ""; @@ -1454,7 +1455,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) if(fp) *fp = '\0'; - if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) { + if((cp1 != NULL) && do_match( cp2, cp1, case_sig, win9x_semantics)) { cp2 = fp ? fp + 1 : ""; break; } @@ -1475,19 +1476,21 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) */ if (strequal (t_filename, ".")) { /* - * Patterns: *.* *. ?. ? are valid - * + * Patterns: *.* *. ?. ? ????????.??? are valid. + * */ if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") || - strequal(t_pattern, "?.") || strequal(t_pattern, "?")) + strequal(t_pattern, "????????.???") || + strequal(t_pattern, "?.") || strequal(t_pattern, "?")) matched = True; } else if (strequal (t_filename, "..")) { /* - * Patterns: *.* *. ?. ? *.? are valid + * Patterns: *.* *. ?. ? *.? ????????.??? are valid. * */ if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") || strequal(t_pattern, "?.") || strequal(t_pattern, "?") || + strequal(t_pattern, "????????.???") || strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*")) matched = True; } else { @@ -1531,12 +1534,12 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) fstrcpy (sbase, t_filename); fstrcpy (sext, p + 1); if (*eext) { - matched = do_match(sbase, ebase, case_sig) - && do_match(sext, eext, case_sig); + matched = do_match(sbase, ebase, case_sig, False) + && do_match(sext, eext, case_sig, False); } else { /* pattern has no extension */ /* Really: match complete filename with pattern ??? means exactly 3 chars */ - matched = do_match(str, ebase, case_sig); + matched = do_match(str, ebase, case_sig, False); } } else { /* @@ -1546,10 +1549,11 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) fstrcpy (sext, ""); if (*eext) { /* pattern has extension */ - matched = do_match(sbase, ebase, case_sig) - && do_match(sext, eext, case_sig); + matched = do_match(sbase, ebase, case_sig, False) + && do_match(sext, eext, case_sig, False); + } else { - matched = do_match(sbase, ebase, case_sig); + matched = do_match(sbase, ebase, case_sig, False); #ifdef EMULATE_WEIRD_W95_MATCHING /* * Even Microsoft has some problems @@ -1560,7 +1564,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) if (!matched) { /* a? matches aa and a in w95 */ fstrcat (sbase, "."); - matched = do_match(sbase, ebase, case_sig); + matched = do_match(sbase, ebase, case_sig, False); } #endif } @@ -1617,12 +1621,11 @@ BOOL yesno(char *p) return(False); } - - /**************************************************************************** set the length of a file from a filedescriptor. Returns 0 on success, -1 on failure. ****************************************************************************/ + int set_filelen(int fd, SMB_OFF_T len) { /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot @@ -1646,7 +1649,8 @@ int set_filelen(int fd, SMB_OFF_T len) return -1; #ifdef S_ISFIFO - if (S_ISFIFO(st.st_mode)) return 0; + if (S_ISFIFO(st.st_mode)) + return 0; #endif if(st.st_size == len) @@ -1720,7 +1724,7 @@ void *Realloc(void *p,size_t size) #endif if (!ret) - DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size)); + DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size)); return(ret); } @@ -1729,40 +1733,30 @@ void *Realloc(void *p,size_t size) /**************************************************************************** get my own name and IP ****************************************************************************/ -BOOL get_myname(char *my_name,struct in_addr *ip) +BOOL get_myname(char *my_name) { - 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; - } + pstring hostname; - if (my_name) - { - /* split off any parts after an initial . */ - char *p = strchr(hostname,'.'); - if (p) *p = 0; + *hostname = 0; - fstrcpy(my_name,hostname); - } + /* get my host name */ + if (gethostname(hostname, sizeof(hostname)) == -1) { + DEBUG(0,("gethostname failed\n")); + return False; + } - if (ip) - putip((char *)ip,(char *)hp->h_addr); + /* Ensure null termination. */ + hostname[sizeof(hostname)-1] = '\0'; - return(True); + if (my_name) { + /* split off any parts after an initial . */ + char *p = strchr(hostname,'.'); + if (p) *p = 0; + + fstrcpy(my_name,hostname); + } + + return(True); } @@ -1771,10 +1765,7 @@ true if two IP addresses are equal ****************************************************************************/ BOOL ip_equal(struct in_addr ip1,struct in_addr ip2) { - uint32 a1,a2; - a1 = ntohl(ip1.s_addr); - a2 = ntohl(ip2.s_addr); - return(a1 == a2); + return ip1.s_addr == ip2.s_addr; } @@ -1801,26 +1792,39 @@ int interpret_protocol(char *str,int def) return(def); } +/**************************************************************************** + Return true if a string could be a pure IP address. +****************************************************************************/ + +BOOL is_ipaddress(const char *str) +{ + BOOL pure_address = True; + int i; + + for (i=0; pure_address && str[i]; i++) + if (!(isdigit((int)str[i]) || str[i] == '.')) + pure_address = False; + + /* Check that a pure number is not misinterpreted as an IP */ + pure_address = pure_address && (strchr(str, '.') != NULL); + + return pure_address; +} /**************************************************************************** interpret an internet address or name into an IP address in 4 byte form ****************************************************************************/ + uint32 interpret_addr(char *str) { struct hostent *hp; uint32 res; - int i; - BOOL pure_address = True; if (strcmp(str,"0.0.0.0") == 0) return(0); if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF); - for (i=0; pure_address && str[i]; 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 */ - if (pure_address) { + if (is_ipaddress(str)) { res = inet_addr(str); } else { /* otherwise assume it's a network name of some sort and use @@ -1872,7 +1876,7 @@ BOOL matchname(char *remotehost,struct in_addr addr) int i; if ((hp = Get_Hostbyname(remotehost)) == 0) { - DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost)); + DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost)); return False; } @@ -1886,7 +1890,7 @@ BOOL matchname(char *remotehost,struct in_addr addr) if (strcasecmp(remotehost, hp->h_name) && strcasecmp(remotehost, "localhost")) { - DEBUG(0,("host name/name mismatch: %s != %s", + DEBUG(0,("host name/name mismatch: %s != %s\n", remotehost, hp->h_name)); return False; } @@ -1903,7 +1907,7 @@ BOOL matchname(char *remotehost,struct in_addr addr) * it, but that could be dangerous, too. */ - DEBUG(0,("host name/address mismatch: %s != %s", + DEBUG(0,("host name/address mismatch: %s != %s\n", inet_ntoa(addr), hp->h_name)); return False; } @@ -1981,7 +1985,7 @@ static char *automount_lookup(char *user_name) 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); + pstring_sub(last_value, "&", user_name); fstrcpy(last_key, user_name); } } @@ -2091,8 +2095,8 @@ static char *automount_path(char *user_name) /* use the passwd entry as the default */ /* this will be the default if WITH_AUTOMOUNT is not used or fails */ - /* pstrcpy() copes with get_unixhome_dir() returning NULL */ - pstrcpy(server_path, get_unixhome_dir(user_name)); + /* pstrcpy() copes with get_user_home_dir() returning NULL */ + pstrcpy(server_path, get_user_home_dir(user_name)); #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT)) @@ -2115,92 +2119,114 @@ static char *automount_path(char *user_name) return server_path; } +/******************************************************************* + Given a pointer to a %$(NAME) expand it as an environment variable. + Return the number of characters by which the pointer should be advanced. + Based on code by Branko Cibej <branko.cibej@hermes.si> + When this is called p points at the '%' character. +********************************************************************/ + +static size_t expand_env_var(char *p, int len) +{ + fstring envname; + char *envval; + char *q, *r; + int copylen; + + if (p[1] != '$') + return 1; + + if (p[2] != '(') + return 2; + + /* + * Look for the terminating ')'. + */ + + if ((q = strchr(p,')')) == NULL) { + DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p)); + return 2; + } + + /* + * Extract the name from within the %$(NAME) string. + */ + + r = p+3; + copylen = MIN((q-r),(sizeof(envname)-1)); + strncpy(envname,r,copylen); + envname[copylen] = '\0'; + + if ((envval = getenv(envname)) == NULL) { + DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname)); + return 2; + } + + /* + * Copy the full %$(NAME) into envname so it + * can be replaced. + */ + + copylen = MIN((q+1-p),(sizeof(envname)-1)); + strncpy(envname,p,copylen); + envname[copylen] = '\0'; + string_sub(p,envname,envval,len); + return 0; /* Allow the environment contents to be parsed. */ +} /******************************************************************* -sub strings with useful parameters -Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and -Paul Rippin <pr3245@nopc.eurostat.cec.be> + Substitute strings with useful parameters. + Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and + Paul Rippin <pr3245@nopc.eurostat.cec.be>. ********************************************************************/ + void standard_sub_basic(char *str) { char *s, *p; char pidstr[10]; - const struct passwd *pass; + struct passwd *pass; char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user; for (s = str ; s && *s && (p = strchr(s,'%')); s = p ) { + int l = sizeof(pstring) - (int)(p-str); + + if (l < 0) { + DEBUG(0,("ERROR: string overflow by %d in standard_sub_basic(%.50s)\n", + -l, str)); + + return; + } + switch (*(p+1)) { case 'G' : { - if ((pass = Get_Pwnam(username,False))!=NULL) - { - string_sub(p,"%G",gidtoname(pass->pw_gid)); - } - else - { + if ((pass = Get_Pwnam(username,False))!=NULL) { + string_sub(p,"%G",gidtoname(pass->pw_gid),l); + } else { p += 2; } break; } - case 'N' : string_sub(p,"%N", automount_server(username)); 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(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 'N' : string_sub(p,"%N", automount_server(username),l); break; + case 'I' : string_sub(p,"%I", client_addr(Client),l); break; + case 'L' : string_sub(p,"%L", local_machine,l); break; + case 'M' : string_sub(p,"%M", client_name(Client),l); break; + case 'R' : string_sub(p,"%R", remote_proto,l); break; + case 'T' : string_sub(p,"%T", timestring(False),l); break; + case 'U' : string_sub(p,"%U", username,l); break; + case 'a' : string_sub(p,"%a", remote_arch,l); break; case 'd' : { 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); + string_sub(p,"%d", pidstr,l); break; } + case 'h' : string_sub(p,"%h", myhostname(),l); break; + case 'm' : string_sub(p,"%m", remote_machine,l); break; + case 'v' : string_sub(p,"%v", VERSION,l); break; + case '$' : p += expand_env_var(p,l); break; /* Expand environment variables */ case '\0': p++; break; /* don't run off end if last character is % */ default : p+=2; break; } @@ -2210,24 +2236,42 @@ void standard_sub_basic(char *str) /**************************************************************************** -do some standard substitutions in a string + 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_unixhome_dir(conn->user)) != NULL) { - string_sub(p,"%H",home); - } else { - p += 2; - } - break; - + for (s=str; (p=strchr(s, '%'));s=p) { + int l = sizeof(pstring) - (int)(p-str); + + switch (*(p+1)) { + case 'H': + if ((home = get_user_home_dir(conn->user))) { + string_sub(p,"%H",home,l); + } else { + p += 2; + } + break; + + case 'P': + string_sub(p,"%P",conn->connectpath,l); + break; + + case 'S': + string_sub(p,"%S", + lp_servicename(SNUM(conn)),l); + break; + + case 'g': + string_sub(p,"%g", + gidtoname(conn->gid),l); + break; + case 'u': + string_sub(p,"%u",conn->user,l); + 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 @@ -2235,14 +2279,17 @@ void standard_sub(connection_struct *conn,char *str) * 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 '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; - - case '\0': p++; break; /* don't run off the end of the string */ - default : p+=2; break; + case 'p': + string_sub(p,"%p", + automount_path(lp_servicename(SNUM(conn))),l); + break; + case '\0': + p++; + break; /* don't run off the end of the string + */ + + default: p+=2; + break; } } @@ -2331,131 +2378,24 @@ struct hostent *Get_Hostbyname(const char *name) check if a process exists. Does this work on all unixes? ****************************************************************************/ -BOOL process_exists(int pid) +BOOL process_exists(pid_t pid) { return(kill(pid,0) == 0 || errno != ESRCH); } -/**************************************************************************** -Setup the groups a user belongs to. -****************************************************************************/ -int get_unixgroups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups) +/******************************************************************* +turn a uid into a user name +********************************************************************/ +char *uidtoname(uid_t uid) { - int i,ngroups; - gid_t grp = 0; - gid_t *groups = NULL; - - if (-1 == initgroups(user,gid)) - { - if (getuid() == 0) - { - DEBUG(0,("Unable to initgroups!\n")); - if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000) - { - DEBUG(0,("This is probably a problem with the account %s\n", user)); - } - } - return -1; - } - - ngroups = sys_getgroups(0,&grp); - if (ngroups <= 0) - { - ngroups = 32; - } - - if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) - { - DEBUG(0,("get_unixgroups malloc fail !\n")); - return -1; - } - - ngroups = sys_getgroups(ngroups,groups); - - (*p_ngroups) = ngroups; - (*p_groups) = groups; - - DEBUG( 3, ( "%s is in %d groups: ", user, ngroups ) ); - for (i = 0; i < ngroups; i++ ) - { - DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) ); - } - DEBUG( 3, ( "\n" ) ); - - return 0; + static char name[40]; + struct passwd *pass = sys_getpwuid(uid); + if (pass) return(pass->pw_name); + slprintf(name, sizeof(name) - 1, "%d",(int)uid); + return(name); } -/**************************************************************************** -get all unix groups. copying group members is hideous on memory, so it's -NOT done here. however, names of unix groups _are_ string-allocated so -free_unix_grps() must be called. -****************************************************************************/ -BOOL get_unix_grps(int *p_ngroups, struct group **p_groups) -{ - struct group *grp; - - DEBUG(10,("get_unix_grps\n")); - - if (p_ngroups == NULL || p_groups == NULL) - { - return False; - } - - (*p_ngroups) = 0; - (*p_groups) = NULL; - - setgrent(); - - while ((grp = getgrent()) != NULL) - { - struct group *copy_grp; - - (*p_groups) = (struct group*)Realloc((*p_groups), (size_t)((*p_ngroups)+1) * sizeof(struct group)); - if ((*p_groups) == NULL) - { - (*p_ngroups) = 0; - endgrent(); - - return False; - } - - copy_grp = &(*p_groups)[*p_ngroups]; - memcpy(copy_grp, grp, sizeof(*grp)); - copy_grp->gr_name = strdup(copy_grp->gr_name); - copy_grp->gr_mem = NULL; - - (*p_ngroups)++; - } - - endgrent(); - - DEBUG(10,("get_unix_grps: %d groups\n", (*p_ngroups))); - return True; -} - -/**************************************************************************** -free memory associated with unix groups. -****************************************************************************/ -void free_unix_grps(int ngroups, struct group *p_groups) -{ - int i; - - if (p_groups == NULL) - { - return; - } - - for (i = 0; i < ngroups; i++) - { - if (p_groups[i].gr_name != NULL) - { - free(p_groups[i].gr_name); - } - } - - free(p_groups); -} /******************************************************************* turn a gid into a group name @@ -2471,48 +2411,37 @@ char *gidtoname(gid_t gid) } /******************************************************************* -turn a group name into a gid +turn a user name into a uid ********************************************************************/ - -BOOL nametogid(const char *name, gid_t *gid) +uid_t nametouid(const char *name) { - struct group *grp = getgrnam(name); - if (grp) - { - *gid = grp->gr_gid; - return True; - } - else if (isdigit(name[0])) - { - *gid = (gid_t)get_number(name); - return True; - } - else - { - return False; - } + struct passwd *pass; + char *p; + uid_t u; + + u = strtol(name, &p, 0); + if (p != name) return u; + + pass = sys_getpwnam(name); + if (pass) return(pass->pw_uid); + return (uid_t)-1; } /******************************************************************* -turn a user name into a uid +turn a group name into a gid ********************************************************************/ -BOOL nametouid(const char *name, uid_t *uid) +gid_t nametogid(const char *name) { - const struct passwd *pass = Get_Pwnam(name, False); - if (pass) - { - *uid = pass->pw_uid; - return True; - } - else if (isdigit(name[0])) - { - *uid = (uid_t)get_number(name); - return True; - } - else - { - return False; - } + struct group *grp; + char *p; + gid_t g; + + g = strtol(name, &p, 0); + if (p != name) return g; + + grp = getgrnam(name); + if (grp) return(grp->gr_gid); + return (gid_t)-1; } /******************************************************************* @@ -2535,12 +2464,12 @@ a readdir wrapper which just returns the file name ********************************************************************/ char *readdirname(DIR *p) { - struct dirent *ptr; + SMB_STRUCT_DIRENT *ptr; char *dname; if (!p) return(NULL); - ptr = (struct dirent *)readdir(p); + ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p); if (!ptr) return(NULL); dname = ptr->d_name; @@ -2731,13 +2660,55 @@ void free_namearray(name_compare_entry *name_array) } /**************************************************************************** + Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-). +****************************************************************************/ + +uint32 map_lock_offset(uint32 high, uint32 low) +{ + unsigned int i; + uint32 mask = 0; + uint32 highcopy = high; + + /* + * Try and find out how many significant bits there are in high. + */ + + for(i = 0; highcopy; i++) + highcopy >>= 1; + + /* + * We use 31 bits not 32 here as POSIX + * lock offsets may not be negative. + */ + + mask = (~0) << (31 - i); + + if(low & mask) + return 0; /* Fail. */ + + high <<= (31 - i); + + return (high|low); +} + +/**************************************************************************** routine to do file locking ****************************************************************************/ + BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { #if HAVE_FCNTL_LOCK SMB_STRUCT_FLOCK lock; int ret; +#if defined(LARGE_SMB_OFF_T) + /* + * In the 64 bit locking case we store the original + * values in case we have to map to a 32 bit lock on + * a filesystem that doesn't support 64 bit locks. + */ + SMB_OFF_T orig_offset = offset; + SMB_OFF_T orig_count = count; +#endif /* LARGE_SMB_OFF_T */ if(lp_ole_locking_compat()) { SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4); @@ -2794,7 +2765,7 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) } /* 32 bit NFS file system, retry with smaller offset */ errno = 0; - lock.l_len = count & 0xffffffff; + lock.l_len = count & 0x7fffffff; ret = fcntl(fd,op,&lock); } @@ -2826,8 +2797,38 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) /* perhaps it doesn't support this sort of locking?? */ if (errno == EINVAL) { + +#if defined(LARGE_SMB_OFF_T) + { + /* + * Ok - if we get here then we have a 64 bit lock request + * that has returned EINVAL. Try and map to 31 bits for offset + * and length and try again. This may happen if a filesystem + * doesn't support 64 bit offsets (efs/ufs) although the underlying + * OS does. + */ + uint32 off_low = (orig_offset & 0xFFFFFFFF); + uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF); + + lock.l_len = (orig_count & 0x7FFFFFFF); + lock.l_start = (SMB_OFF_T)map_lock_offset(off_high, off_low); + ret = fcntl(fd,op,&lock); + if (ret == -1) + { + if (errno == EINVAL) + { + DEBUG(3,("locking not supported? returning True\n")); + return(True); + } + return False; + } + DEBUG(3,("64 -> 32 bit modified lock call successful\n")); + return True; + } +#else /* LARGE_SMB_OFF_T */ DEBUG(3,("locking not supported? returning True\n")); return(True); +#endif /* LARGE_SMB_OFF_T */ } return(False); @@ -2879,6 +2880,9 @@ void set_remote_arch(enum remote_arch_types type) case RA_WINNT: fstrcpy(remote_arch, "WinNT"); return; + case RA_WIN2K: + fstrcpy(remote_arch, "Win2K"); + return; case RA_SAMBA: fstrcpy(remote_arch,"Samba"); return; @@ -2899,30 +2903,18 @@ enum remote_arch_types get_remote_arch(void) /******************************************************************* - align a pointer to a multiple of 4 bytes. - ********************************************************************/ -char *align4(char *q, char *base) -{ - int mod = PTR_DIFF(q, base) & 3; - if (mod != 0) - { - q += mod; - } - return q; -} -/******************************************************************* align a pointer to a multiple of 2 bytes ********************************************************************/ char *align2(char *q, char *base) { - if (PTR_DIFF(q, base) & 1) + if ((q - base) & 1) { q++; } return q; } -void out_ascii(FILE *f, const unsigned char *buf,int len) +void out_ascii(FILE *f, unsigned char *buf,int len) { int i; for (i=0;i<len;i++) @@ -2931,36 +2923,9 @@ void out_ascii(FILE *f, const unsigned char *buf,int len) } } -void out_struct(FILE *f, const char *buf1,int len, int per_line) -{ - const unsigned char *buf = (const unsigned char *)buf1; - int i; - - if (len<=0) - { - return; - } - - fprintf(f, "{\n\t"); - for (i=0;i<len;) - { - fprintf(f, "0x%02X",(int)buf[i]); - i++; - if (i != len) - { - fprintf(f, ", "); - } - if (i%per_line == 0 && i != len) - { - fprintf(f, "\n\t"); - } - } - fprintf(f, "\n};\n"); -} - -void out_data(FILE *f, const char *buf1,int len, int per_line) +void out_data(FILE *f,char *buf1,int len, int per_line) { - const unsigned char *buf = (const unsigned char *)buf1; + unsigned char *buf = (unsigned char *)buf1; int i=0; if (len<=0) { @@ -2999,55 +2964,44 @@ void out_data(FILE *f, const char *buf1,int len, int per_line) } } -void print_asc(int level, unsigned char const *buf,int len) +void print_asc(int level, unsigned char *buf,int len) { int i; for (i=0;i<len;i++) - { - DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.')); - } + DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.')); } -void dump_data(int level, const char *buf1, int len) +void dump_data(int level,char *buf1,int len) { - unsigned char const *buf = (unsigned char const *)buf1; - int i=0; - if (len<0) return; - if (len == 0) - { - DEBUG(level,("\n")); - return; - } - - DEBUG(level,("[%03X] ",i)); - for (i=0;i<len;) - { - DEBUGADD(level,("%02X ",(int)buf[i])); - i++; - if (i%8 == 0) DEBUGADD(level,(" ")); - if (i%16 == 0) - { - print_asc(level,&buf[i-16],8); DEBUGADD(level,(" ")); - print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n")); - if (i<len) DEBUGADD(level,("[%03X] ",i)); - } - } + unsigned char *buf = (unsigned char *)buf1; + int i=0; + if (len<=0) return; - if (i%16 != 0) /* finish off a non-16-char-length row */ - { - int n; - - n = 16 - (i%16); - DEBUGADD(level,(" ")); - if (n>8) DEBUGADD(level,(" ")); - while (n--) DEBUGADD(level,(" ")); - - n = MIN(8,i%16); - print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,(" ")); - n = (i%16) - n; - if (n>0) print_asc(level,&buf[i-n],n); - DEBUGADD(level,("\n")); - } + DEBUG(level,("[%03X] ",i)); + for (i=0;i<len;) { + DEBUG(level,("%02X ",(int)buf[i])); + i++; + if (i%8 == 0) DEBUG(level,(" ")); + if (i%16 == 0) { + print_asc(level,&buf[i-16],8); DEBUG(level,(" ")); + print_asc(level,&buf[i-8],8); DEBUG(level,("\n")); + if (i<len) DEBUG(level,("[%03X] ",i)); + } + } + if (i%16) { + int n; + + n = 16 - (i%16); + DEBUG(level,(" ")); + if (n>8) DEBUG(level,(" ")); + while (n--) DEBUG(level,(" ")); + + n = MIN(8,i%16); + print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" ")); + n = (i%16) - n; + if (n>0) print_asc(level,&buf[i-n],n); + DEBUG(level,("\n")); + } } char *tab_depth(int depth) @@ -3102,16 +3056,50 @@ int set_maxfiles(int requested_max) { #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)) struct rlimit rlp; - getrlimit(RLIMIT_NOFILE, &rlp); - /* Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to + int saved_current_limit; + + if(getrlimit(RLIMIT_NOFILE, &rlp)) { + DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n", + strerror(errno) )); + /* just guess... */ + return requested_max; + } + + /* + * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to * account for the extra fd we need * as well as the log files and standard - * handles etc. */ - rlp.rlim_cur = MIN(requested_max,rlp.rlim_max); - setrlimit(RLIMIT_NOFILE, &rlp); - getrlimit(RLIMIT_NOFILE, &rlp); + * handles etc. Save the limit we want to set in case + * we are running on an OS that doesn't support this limit (AIX) + * which always returns RLIM_INFINITY for rlp.rlim_max. + */ + + saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max); + + if(setrlimit(RLIMIT_NOFILE, &rlp)) { + DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", + (int)rlp.rlim_cur, strerror(errno) )); + /* just guess... */ + return saved_current_limit; + } + + if(getrlimit(RLIMIT_NOFILE, &rlp)) { + DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n", + strerror(errno) )); + /* just guess... */ + return saved_current_limit; + } + +#if defined(RLIM_INFINITY) + if(rlp.rlim_cur == RLIM_INFINITY) + return saved_current_limit; +#endif + + if((int)rlp.rlim_cur > saved_current_limit) + return saved_current_limit; + return rlp.rlim_cur; -#else +#else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */ /* * No way to know - just guess... */ @@ -3131,11 +3119,11 @@ void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name) /***************************************************************** splits out the start of the key (HKLM or HKU) and the rest of the key *****************************************************************/ -BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name) +BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name) { pstring tmp; - if (!next_token((char**)(&full_keyname), tmp, "\\", sizeof(tmp))) + if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp))) { return False; } @@ -3144,15 +3132,7 @@ BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name) DEBUG(10, ("reg_split_key: hive %s\n", tmp)); - if (strequal(tmp, "HKCR") || strequal(tmp, "HKEY_CLASSES_ROOT")) - { - (*reg_type) = HKEY_CLASSES_ROOT; - } - else if (strequal(tmp, "HKCU") || strequal(tmp, "HKEY_CURRENT_USER")) - { - (*reg_type) = HKEY_CURRENT_USER; - } - else if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE")) + if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE")) { (*reg_type) = HKEY_LOCAL_MACHINE; } @@ -3180,326 +3160,56 @@ BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name) return True; } -/**************************************************************************** - become the specified uid - permanently ! -****************************************************************************/ -BOOL become_user_permanently(uid_t uid, gid_t gid) -{ - /* now completely lose our privilages. This is a fairly paranoid - way of doing it, but it does work on all systems that I know of */ - -#ifdef HAVE_SETRESUID - /* - * Firstly ensure all our uids are set to root. - */ - setresgid(0,0,0); - setresuid(0,0,0); - - /* - * Now ensure we change all our gids. - */ - setresgid(gid,gid,gid); - - /* - * Now ensure all the uids are the user. - */ - setresuid(uid,uid,uid); -#else - /* - * Firstly ensure all our uids are set to root. - */ - setuid(0); - seteuid(0); - - /* - * Now ensure we change all our gids. - */ - setgid(gid); - setegid(gid); - - /* - * Now ensure all the uids are the user. - */ - setuid(uid); - seteuid(uid); -#endif - - if (getuid() != uid || geteuid() != uid || - getgid() != gid || getegid() != gid) { - /* We failed to lose our privilages. */ - return False; - } - - return(True); -} - -char *get_trusted_serverlist(const char* domain) -{ - pstring tmp; - static char *server_list = NULL; - static pstring srv_list; - char *trusted_list = lp_trusted_domains(); - if (strequal(lp_workgroup(), domain)) - { - DEBUG(10,("local domain server list: %s\n", server_list)); - pstrcpy(srv_list, lp_passwordserver()); - return srv_list; - } - - if (!next_token(&trusted_list, tmp, NULL, sizeof(tmp))) - { - return NULL; - } - - do - { - fstring trust_dom; - split_at_first_component(tmp, trust_dom, '=', srv_list); - - if (strequal(domain, trust_dom)) - { - return srv_list; - DEBUG(10,("trusted: %s\n", server_list)); - } - - } while (next_token(NULL, tmp, NULL, sizeof(tmp))); - - return NULL; -} - -/********************************************************** - Encode the account control bits into a string. - length = length of string to encode into (including terminating - null). length *MUST BE MORE THAN 2* ! - **********************************************************/ - -char *pwdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length) -{ - static fstring acct_str; - size_t i = 0; - - acct_str[i++] = '['; - - if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N'; - if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D'; - if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H'; - if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T'; - if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U'; - if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M'; - if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W'; - if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S'; - if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L'; - if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X'; - if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I'; - if (acct_ctrl & ACB_PWLOCK ) acct_str[i++] = 'P'; - - for ( ; i < length - 2 ; i++ ) - { - acct_str[i] = ' '; - } - - i = length - 2; - acct_str[i++] = ']'; - acct_str[i++] = '\0'; - - return acct_str; -} - -/********************************************************** - Decode the account control bits from a string. - - this function breaks coding standards minimum line width of 80 chars. - reason: vertical line-up code clarity - all case statements fit into - 15 lines, which is more important. - **********************************************************/ - -uint16 pwdb_decode_acct_ctrl(const char *p) +/***************************************************************** +like mktemp() but make sure that no % characters are used +% characters are bad for us because of the macro subs + *****************************************************************/ +char *smbd_mktemp(char *template) { - uint16 acct_ctrl = 0; - BOOL finished = False; - - /* - * Check if the account type bits have been encoded after the - * NT password (in the form [NDHTUWSLXI]). - */ + char *p = mktemp(template); + char *p2; + SMB_STRUCT_STAT st; - if (*p != '[') return 0; + if (!p) return NULL; - for (p++; *p && !finished; p++) - { - switch (*p) - { - case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ } - case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ } - case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ } - case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ } - case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ } - case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ } - case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ } - case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } - case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } - case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ } - case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ } - case 'P': { acct_ctrl |= ACB_PWLOCK ; break; /* 'P'assword cannot be changed remotely */ } - case ' ': { break; } - case ':': - case '\n': - case '\0': - case ']': - default: { finished = True; } + while ((p2=strchr(p,'%'))) { + p2[0] = 'A'; + while (sys_stat(p,&st) == 0 && p2[0] < 'Z') { + /* damn, it exists */ + p2[0]++; } - } - - return acct_ctrl; -} - -/******************************************************************* - gets password-database-format time from a string. - ********************************************************************/ - -static time_t get_time_from_string(const char *p) -{ - int i; - - for (i = 0; i < 8; i++) - { - if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF))) - { - break; + if (p2[0] == 'Z') { + /* oh well ... better return something */ + p2[0] = '%'; + return p; } } - if (i == 8) - { - /* - * p points at 8 characters of hex digits - - * read into a time_t as the seconds since - * 1970 that the password was last changed. - */ - return (time_t)strtol(p, NULL, 16); - } - return (time_t)-1; -} - -/******************************************************************* - gets password last set time - ********************************************************************/ - -time_t pwdb_get_last_set_time(const char *p) -{ - if (*p && !StrnCaseCmp(p, "LCT-", 4)) - { - return get_time_from_string(p + 4); - } - return (time_t)-1; -} - - -/******************************************************************* - sets password-database-format time in a string. - ********************************************************************/ -static void set_time_in_string(char *p, int max_len, char *type, time_t t) -{ - slprintf(p, max_len, ":%s-%08X:", type, (uint32)t); -} - -/******************************************************************* - sets logon time - ********************************************************************/ -void pwdb_set_logon_time(char *p, int max_len, time_t t) -{ - set_time_in_string(p, max_len, "LNT", t); -} -/******************************************************************* - sets logoff time - ********************************************************************/ -void pwdb_set_logoff_time(char *p, int max_len, time_t t) -{ - set_time_in_string(p, max_len, "LOT", t); -} - -/******************************************************************* - sets kickoff time - ********************************************************************/ -void pwdb_set_kickoff_time(char *p, int max_len, time_t t) -{ - set_time_in_string(p, max_len, "KOT", t); -} - -/******************************************************************* - sets password can change time - ********************************************************************/ -void pwdb_set_can_change_time(char *p, int max_len, time_t t) -{ - set_time_in_string(p, max_len, "CCT", t); + return p; } -/******************************************************************* - sets password last set time - ********************************************************************/ -void pwdb_set_must_change_time(char *p, int max_len, time_t t) -{ - set_time_in_string(p, max_len, "MCT", t); -} -/******************************************************************* - sets password last set time - ********************************************************************/ -void pwdb_set_last_set_time(char *p, int max_len, time_t t) +/***************************************************************** +like strdup but for memory + *****************************************************************/ +void *memdup(void *p, size_t size) { - set_time_in_string(p, max_len, "LCT", t); + void *p2; + p2 = malloc(size); + if (!p2) return NULL; + memcpy(p2, p, size); + return p2; } - -/************************************************************* - Routine to set 32 hex password characters from a 16 byte array. -**************************************************************/ -void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl) -{ - if (pwd != NULL) - { - int i; - for (i = 0; i < 16; i++) - { - slprintf(&p[i*2], 33, "%02X", pwd[i]); - } - } - else - { - if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ)) - { - safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33); - } - else - { - safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33); - } - } -} - -/************************************************************* - Routine to get the 32 hex characters and turn them - into a 16 byte array. -**************************************************************/ -BOOL pwdb_gethexpwd(const char *p, char *pwd, uint32 *acct_ctrl) +/***************************************************************** +get local hostname and cache result + *****************************************************************/ +char *myhostname(void) { - if (strnequal(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32)) - { - if (acct_ctrl != NULL) - { - *acct_ctrl |= ACB_PWNOTREQ; - } - pwd[0] = 0; - return True; - } - else if (strnequal(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32)) - { - pwd[0] = 0; - return True; - } - else - { - return strhex_to_str(pwd, 32, p) == 16; + static pstring ret; + if (ret[0] == 0) { + get_myname(ret); } + return ret; } diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c index f4325b813b..9eb38460d9 100644 --- a/source3/lib/util_file.c +++ b/source3/lib/util_file.c @@ -51,7 +51,7 @@ BOOL do_file_lock(int fd, int waitsecs, int type) lock.l_len = 1; lock.l_pid = 0; - alarm(5); + alarm(waitsecs); ret = fcntl(fd, SMB_F_SETLKW, &lock); alarm(0); CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL); @@ -113,22 +113,22 @@ BOOL file_unlock(int fd, int *plock_depth) update to be set = True if modification is required. ****************************************************************/ -void *startfileent(char *pfile, char *s_readbuf, int bufsize, +void *startfilepwent(char *pfile, char *s_readbuf, int bufsize, int *file_lock_depth, BOOL update) { FILE *fp = NULL; if (!*pfile) { - DEBUG(0, ("startfileent: No file set\n")); + DEBUG(0, ("startfilepwent: No file set\n")); return (NULL); } - DEBUG(10, ("startfileent: opening file %s\n", pfile)); + DEBUG(10, ("startfilepwent: opening file %s\n", pfile)); fp = sys_fopen(pfile, update ? "r+b" : "rb"); if (fp == NULL) { - DEBUG(0, ("startfileent: unable to open file %s\n", pfile)); + DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile)); return NULL; } @@ -137,7 +137,7 @@ void *startfileent(char *pfile, char *s_readbuf, int bufsize, if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth)) { - DEBUG(0, ("startfileent: unable to lock file %s\n", pfile)); + DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile)); fclose(fp); return NULL; } @@ -152,13 +152,13 @@ void *startfileent(char *pfile, char *s_readbuf, int bufsize, /*************************************************************** End enumeration of the file. ****************************************************************/ -void endfileent(void *vp, int *file_lock_depth) +void endfilepwent(void *vp, int *file_lock_depth) { FILE *fp = (FILE *)vp; file_unlock(fileno(fp), file_lock_depth); fclose(fp); - DEBUG(7, ("endfileent: closed file.\n")); + DEBUG(7, ("endfilepwent: closed file.\n")); } /************************************************************************* @@ -181,6 +181,7 @@ BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok) /************************************************************************* gets a line out of a file. + line is of format "xxxx:xxxxxx:xxxxx:". lines with "#" at the front are ignored. *************************************************************************/ int getfileline(void *vp, char *linebuf, int linebuf_size) @@ -188,6 +189,7 @@ int getfileline(void *vp, char *linebuf, int linebuf_size) /* Static buffers we will return. */ FILE *fp = (FILE *)vp; unsigned char c; + unsigned char *p; size_t linebuf_len; if (fp == NULL) @@ -247,6 +249,12 @@ int getfileline(void *vp, char *linebuf, int linebuf_size) continue; } + p = (unsigned char *) strchr(linebuf, ':'); + if (p == NULL) + { + DEBUG(0, ("getfileline: malformed line entry (no :)\n")); + continue; + } return linebuf_len; } return -1; @@ -319,49 +327,3 @@ char *fgets_slash(char *s2,int maxlen,FILE *f) return(s); } -/**************************************************************************** -checks if a file has changed since last read -****************************************************************************/ -BOOL file_modified(const char *filename, time_t *lastmodified) -{ - SMB_STRUCT_STAT st; - - if (sys_stat(filename, &st) != 0) - { - DEBUG(0, ("file_changed: Unable to stat file %s. Error was %s\n", - filename, strerror(errno) )); - return False; - } - - if(st.st_mtime <= *lastmodified) - { - DEBUG(20, ("file_modified: %s not modified\n", filename)); - return False; - } - - DEBUG(20, ("file_modified: %s modified\n", filename)); - *lastmodified = st.st_mtime; - return True; -} - -/*************************************************************************** -opens a file if modified otherwise returns NULL -***************************************************************************/ -void *open_file_if_modified(const char *filename, char *mode, time_t *lastmodified) -{ - FILE *f; - - if (!file_modified(filename, lastmodified)) - { - return NULL; - } - - if( (f = fopen(filename, mode)) == NULL) - { - DEBUG(0, ("open_file_if_modified: can't open file %s. Error was %s\n", - filename, strerror(errno))); - return NULL; - } - - return (void *)f; -} diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index a966484484..9e5154d259 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -3,6 +3,8 @@ Version 1.9. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Luke Kenneth Caseson Leighton 1998-1999 + Copyright (C) Jeremy Allison 1999 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 @@ -23,13 +25,206 @@ extern int DEBUGLEVEL; +DOM_SID global_sam_sid; +extern pstring global_myname; +extern fstring global_myworkgroup; + +/* + * Some useful sids + */ + +DOM_SID global_sid_S_1_5_0x20; /* local well-known domain */ +DOM_SID global_sid_World_Domain; /* everyone */ +DOM_SID global_sid_World; /* everyone */ +DOM_SID global_sid_Creator_Owner_Domain; /* Creator Owner */ +DOM_SID global_sid_Creator_Owner; /* Creator Owner */ +DOM_SID global_sid_NT_Authority; /* NT Authority */ + +typedef struct _known_sid_users { + uint32 rid; + uint8 sid_name_use; + char *known_user_name; +} known_sid_users; + +/* static known_sid_users no_users[] = {{0, 0, NULL}}; */ +static known_sid_users everyone_users[] = {{ 0, SID_NAME_WKN_GRP, "Everyone" }, {0, 0, NULL}}; +static known_sid_users creator_owner_users[] = {{ 0, SID_NAME_ALIAS, "Creator Owner" }, {0, 0, NULL}}; +static known_sid_users nt_authority_users[] = {{ 1, SID_NAME_ALIAS, "Dialup" }, + { 2, SID_NAME_ALIAS, "Network"}, + { 3, SID_NAME_ALIAS, "Batch"}, + { 4, SID_NAME_ALIAS, "Interactive"}, + { 6, SID_NAME_ALIAS, "Service"}, + { 7, SID_NAME_ALIAS, "AnonymousLogon"}, + { 8, SID_NAME_ALIAS, "Proxy"}, + { 9, SID_NAME_ALIAS, "ServerLogon"}, + {0, 0, NULL}}; + +static struct sid_name_map_info +{ + DOM_SID *sid; + char *name; + known_sid_users *known_users; +} +sid_name_map[] = +{ + { &global_sam_sid, global_myname, NULL}, + { &global_sam_sid, global_myworkgroup, NULL}, + { &global_sid_S_1_5_0x20, "BUILTIN", NULL}, + { &global_sid_World_Domain, "", &everyone_users[0] }, + { &global_sid_Creator_Owner_Domain, "", &creator_owner_users[0] }, + { &global_sid_NT_Authority, "NT Authority", &nt_authority_users[0] }, + { NULL, NULL, NULL} +}; + +/**************************************************************************** + Creates some useful well known sids +****************************************************************************/ + +void generate_wellknown_sids(void) +{ + string_to_sid(&global_sid_S_1_5_0x20, "S-1-5-32"); + string_to_sid(&global_sid_World_Domain, "S-1-1"); + string_to_sid(&global_sid_World, "S-1-1-0"); + string_to_sid(&global_sid_Creator_Owner_Domain, "S-1-3"); + string_to_sid(&global_sid_Creator_Owner, "S-1-3-0"); + string_to_sid(&global_sid_NT_Authority, "S-1-5"); +} + +/************************************************************************** + Turns a domain SID into a name, returned in the nt_domain argument. +***************************************************************************/ + +BOOL map_domain_sid_to_name(DOM_SID *sid, char *nt_domain) +{ + fstring sid_str; + int i = 0; + sid_to_string(sid_str, sid); + + DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str)); + + if (nt_domain == NULL) + return False; + + while (sid_name_map[i].sid != NULL) { + sid_to_string(sid_str, sid_name_map[i].sid); + DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str)); + if (sid_equal(sid_name_map[i].sid, sid)) { + fstrcpy(nt_domain, sid_name_map[i].name); + DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain)); + return True; + } + i++; + } + + DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str)); + + return False; +} + +/************************************************************************** + Looks up a known username from one of the known domains. +***************************************************************************/ + +BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, uint8 *psid_name_use) +{ + int i = 0; + struct sid_name_map_info *psnm; + + for(i = 0; sid_name_map[i].sid != NULL; i++) { + psnm = &sid_name_map[i]; + if(sid_equal(psnm->sid, sid)) { + int j; + for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) { + if(rid == psnm->known_users[j].rid) { + DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '%s'\n", + (unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name )); + fstrcpy( name, psnm->known_users[j].known_user_name); + *psid_name_use = psnm->known_users[j].sid_name_use; + return True; + } + } + } + } + + return False; +} + +/************************************************************************** + Turns a domain name into a SID. + *** side-effect: if the domain name is NULL, it is set to our domain *** +***************************************************************************/ + +BOOL map_domain_name_to_sid(DOM_SID *sid, char *nt_domain) +{ + int i = 0; + + if (nt_domain == NULL) { + DEBUG(5,("map_domain_name_to_sid: mapping NULL domain to our SID.\n")); + sid_copy(sid, &global_sam_sid); + return True; + } + + if (nt_domain[0] == 0) { + fstrcpy(nt_domain, global_myname); + DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n", nt_domain)); + sid_copy(sid, &global_sam_sid); + return True; + } + + DEBUG(5,("map_domain_name_to_sid: %s\n", nt_domain)); + + while (sid_name_map[i].name != NULL) { + DEBUG(5,("map_domain_name_to_sid: compare: %s\n", sid_name_map[i].name)); + if (strequal(sid_name_map[i].name, nt_domain)) { + fstring sid_str; + sid_copy(sid, sid_name_map[i].sid); + sid_to_string(sid_str, sid_name_map[i].sid); + DEBUG(5,("map_domain_name_to_sid: found %s\n", sid_str)); + return True; + } + i++; + } + + DEBUG(0,("map_domain_name_to_sid: mapping to %s not found.\n", nt_domain)); + return False; +} + +/************************************************************************** + Splits a name of format \DOMAIN\name or name into its two components. + Sets the DOMAIN name to global_myname if it has not been specified. +***************************************************************************/ + +void split_domain_name(const char *fullname, char *domain, char *name) +{ + pstring full_name; + char *p; + + *domain = *name = '\0'; + if (fullname[0] == '\\') + fullname++; + + pstrcpy(full_name, fullname); + p = strchr(full_name+1, '\\'); + + if (p != NULL) { + *p = 0; + fstrcpy(domain, full_name); + fstrcpy(name, p+1); + } else { + fstrcpy(domain, global_myname); + fstrcpy(name, full_name); + } + + DEBUG(10,("split_domain_name:name '%s' split into domain :'%s' and user :'%s'\n", + fullname, domain, name)); +} /***************************************************************** Convert a SID to an ascii string. *****************************************************************/ -char *sid_to_string(pstring sidstr_out, const DOM_SID *sid) +char *sid_to_string(fstring sidstr_out, DOM_SID *sid) { char subauth[16]; int i; @@ -39,12 +234,11 @@ char *sid_to_string(pstring sidstr_out, const DOM_SID *sid) (sid->id_auth[3] << 16) + (sid->id_auth[2] << 24); - slprintf(sidstr_out, sizeof(pstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia); + slprintf(sidstr_out, sizeof(fstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia); - for (i = 0; i < sid->num_auths; i++) - { + for (i = 0; i < sid->num_auths; i++) { slprintf(subauth, sizeof(subauth)-1, "-%lu", (unsigned long)sid->sub_auths[i]); - pstrcat(sidstr_out, subauth); + fstrcat(sidstr_out, subauth); } DEBUG(7,("sid_to_string returning %s\n", sidstr_out)); @@ -55,72 +249,68 @@ char *sid_to_string(pstring sidstr_out, const DOM_SID *sid) Convert a string to a SID. Returns True on success, False on fail. *****************************************************************/ -BOOL string_to_sid(DOM_SID *sidout, const char *sidstr) +BOOL string_to_sid(DOM_SID *sidout, char *sidstr) { - const char *p = sidstr; - /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ - uint32 ia; + 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)); + 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; - } + if (StrnCaseCmp( sidstr, "S-", 2)) { + DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr)); + return False; + } - if ((p = strchr(p, '-')) == NULL) - { - DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); - return False; - } + p += 2; + if (!next_token(&p, tok, "-", sizeof(tok))) { + DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); + return False; + } - p++; + /* Get the revision number. */ + sidout->sid_rev_num = (uint8)strtoul(tok, NULL, 10); - /* Get the revision number. */ - sidout->sid_rev_num = (uint8)strtoul(p,NULL,10); + if (!next_token(&p, tok, "-", sizeof(tok))) { + DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); + return False; + } - if ((p = strchr(p, '-')) == NULL) - { - 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 = (uint32)strtoul(tok, NULL, 10); + + /* 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, "-", sizeof(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. + */ + sid_append_rid(sidout, (uint32)strtoul(tok, NULL, 10)); + } - p++; - - /* identauth in decimal should be < 2^32 */ - ia = (uint32)strtoul(p,NULL,10); - - /* 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 (((p = strchr(p, '-')) != NULL) && sidout->num_auths < MAXSUBAUTHS) - { - p++; - /* - * NOTE - the subauths are in native machine-endian format. They - * are converted to little-endian when linearized onto the wire. - */ - sid_append_rid(sidout, (uint32)strtoul(p, NULL, 10)); - } + DEBUG(7,("string_to_sid: converted SID %s ok\n", sidstr)); - return True; + return True; } /***************************************************************** - add a rid to the end of a sid + Add a rid to the end of a sid *****************************************************************/ + BOOL sid_append_rid(DOM_SID *sid, uint32 rid) { - if (sid->num_auths < MAXSUBAUTHS) - { + if (sid->num_auths < MAXSUBAUTHS) { sid->sub_auths[sid->num_auths++] = rid; return True; } @@ -128,413 +318,109 @@ BOOL sid_append_rid(DOM_SID *sid, uint32 rid) } /***************************************************************** - removes the last rid from the end of a sid + Removes the last rid from the end of a sid *****************************************************************/ + BOOL sid_split_rid(DOM_SID *sid, uint32 *rid) { - if (sid->num_auths > 0) - { + if (sid->num_auths > 0) { sid->num_auths--; - if (rid != NULL) - { - (*rid) = sid->sub_auths[sid->num_auths]; - } + *rid = sid->sub_auths[sid->num_auths]; return True; } return False; } /***************************************************************** - copies a sid + Copies a sid *****************************************************************/ -void sid_copy(DOM_SID *sid1, const DOM_SID *sid2) -{ - int i; - - for (i = 0; i < 6; i++) - { - sid1->id_auth[i] = sid2->id_auth[i]; - } - - for (i = 0; i < sid2->num_auths; i++) - { - sid1->sub_auths[i] = sid2->sub_auths[i]; - } - sid1->num_auths = sid2->num_auths; - sid1->sid_rev_num = sid2->sid_rev_num; -} - -/***************************************************************** - compare two sids up to the auths of the first sid -*****************************************************************/ -BOOL sid_front_equal(const DOM_SID *sid1, const DOM_SID *sid2) +void sid_copy(DOM_SID *dst, DOM_SID *src) { int i; - /* compare most likely different rids, first: i.e start at end */ - for (i = sid1->num_auths-1; i >= 0; --i) - { - if (sid1->sub_auths[i] != sid2->sub_auths[i]) return False; - } - - if (sid1->num_auths > sid2->num_auths ) return False; - if (sid1->sid_rev_num != sid2->sid_rev_num) return False; + dst->sid_rev_num = src->sid_rev_num; + dst->num_auths = src->num_auths; - for (i = 0; i < 6; i++) - { - if (sid1->id_auth[i] != sid2->id_auth[i]) return False; - } + memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth)); - return True; + for (i = 0; i < src->num_auths; i++) + dst->sub_auths[i] = src->sub_auths[i]; } /***************************************************************** - compare two sids -*****************************************************************/ -BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2) -{ - int i; - - /* compare most likely different rids, first: i.e start at end */ - for (i = sid1->num_auths-1; i >= 0; --i) - { - if (sid1->sub_auths[i] != sid2->sub_auths[i]) return False; - } - - if (sid1->num_auths != sid2->num_auths ) return False; - if (sid1->sid_rev_num != sid2->sid_rev_num) return False; - - for (i = 0; i < 6; i++) - { - if (sid1->id_auth[i] != sid2->id_auth[i]) return False; - } - - return True; -} - - -/***************************************************************** - calculates size of a sid -*****************************************************************/ -int sid_size(const DOM_SID *sid) -{ - if (sid == NULL) - { - return 0; - } - return sid->num_auths * sizeof(uint32) + 8; -} - - -/***************************************************************** Duplicates a sid - mallocs the target. *****************************************************************/ -DOM_SID *sid_dup(const DOM_SID *src) +DOM_SID *sid_dup(DOM_SID *src) { DOM_SID *dst; if(!src) return NULL; - if((dst = (DOM_SID*)malloc(sizeof(DOM_SID))) != NULL) { - memset(dst, '\0', sizeof(DOM_SID)); - sid_copy( dst, src); + if((dst = malloc(sizeof(DOM_SID))) != NULL) { + memset(dst, '\0', sizeof(DOM_SID)); + sid_copy( dst, src); } return dst; } +/***************************************************************** + Write a sid out into on-the-wire format. +*****************************************************************/ -/**************************************************************************** - Read a SID from a file. -****************************************************************************/ - -static BOOL read_sid_from_file(int fd, char *sid_file, DOM_SID *sid) -{ - fstring fline; - fstring sid_str; - - memset(fline, '\0', sizeof(fline)); - - if (read(fd, fline, sizeof(fline) -1 ) < 0) { - DEBUG(0,("unable to read file %s. Error was %s\n", - sid_file, strerror(errno) )); - return False; - } - - /* - * Convert to the machine SID. - */ - - fline[sizeof(fline)-1] = '\0'; - if (!string_to_sid(sid, fline)) { - DEBUG(0,("unable to read sid.\n")); - return False; - } - - sid_to_string(sid_str, sid); - DEBUG(5,("read_sid_from_file: sid %s\n", sid_str)); - - return True; -} - -/**************************************************************************** - Generate the global machine sid. Look for the DOMAINNAME.SID file first, if - not found then look in smb.conf and use it to create the DOMAINNAME.SID file. -****************************************************************************/ -BOOL read_sid(char *domain_name, DOM_SID *sid) +BOOL sid_linearize(char *outbuf, size_t len, DOM_SID *sid) { - int fd; - char *p; - pstring sid_file; - fstring file_name; - SMB_STRUCT_STAT st; - - pstrcpy(sid_file, lp_smb_passwd_file()); - - DEBUG(10,("read_sid: Domain: %s\n", domain_name)); + size_t i; - if (sid_file[0] == 0) - { - DEBUG(0,("cannot find smb passwd file\n")); + if(len < sid_size(sid)) return False; - } - - p = strrchr(sid_file, '/'); - if (p != NULL) - { - *++p = '\0'; - } - if (!directory_exist(sid_file, NULL)) - { - if (mkdir(sid_file, 0700) != 0) - { - DEBUG(0,("can't create private directory %s : %s\n", - sid_file, strerror(errno))); - return False; - } - } + SCVAL(outbuf,0,sid->sid_rev_num); + SCVAL(outbuf,1,sid->num_auths); + memcpy(&outbuf[2], sid->id_auth, 6); + for(i = 0; i < sid->num_auths; i++) + SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]); - slprintf(file_name, sizeof(file_name)-1, "%s.SID", domain_name); - strupper(file_name); - pstrcat(sid_file, file_name); - - if ((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) { - DEBUG(0,("unable to open or create file %s. Error was %s\n", - sid_file, strerror(errno) )); - return False; - } - - /* - * Check if the file contains data. - */ - - if (sys_fstat(fd, &st) < 0) { - DEBUG(0,("unable to stat file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - if (st.st_size == 0) - { - close(fd); - return False; - } - - /* - * We have a valid SID - read it. - */ - - if (!read_sid_from_file(fd, sid_file, sid)) - { - DEBUG(0,("unable to read file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - close(fd); return True; -} +} +/***************************************************************** + Compare two sids. +*****************************************************************/ -/**************************************************************************** - Generate the global machine sid. Look for the DOMAINNAME.SID file first, if - not found then look in smb.conf and use it to create the DOMAINNAME.SID file. -****************************************************************************/ -BOOL write_sid(char *domain_name, DOM_SID *sid) +BOOL sid_equal(DOM_SID *sid1, DOM_SID *sid2) { - int fd; - char *p; - pstring sid_file; - fstring sid_string; - fstring file_name; - SMB_STRUCT_STAT st; - - pstrcpy(sid_file, lp_smb_passwd_file()); - sid_to_string(sid_string, sid); + int i; - DEBUG(10,("write_sid: Domain: %s SID: %s\n", domain_name, sid_string)); - fstrcat(sid_string, "\n"); + /* compare most likely different rids, first: i.e start at end */ + for (i = sid1->num_auths-1; i >= 0; --i) + if (sid1->sub_auths[i] != sid2->sub_auths[i]) + return False; - if (sid_file[0] == 0) - { - DEBUG(0,("cannot find smb passwd file\n")); + if (sid1->num_auths != sid2->num_auths) + return False; + if (sid1->sid_rev_num != sid2->sid_rev_num) return False; - } - - p = strrchr(sid_file, '/'); - if (p != NULL) - { - *++p = '\0'; - } - if (!directory_exist(sid_file, NULL)) { - if (mkdir(sid_file, 0700) != 0) { - DEBUG(0,("can't create private directory %s : %s\n", - sid_file, strerror(errno))); + for (i = 0; i < 6; i++) + if (sid1->id_auth[i] != sid2->id_auth[i]) return False; - } - } - slprintf(file_name, sizeof(file_name)-1, "%s.SID", domain_name); - strupper(file_name); - pstrcat(sid_file, file_name); - - if ((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) { - DEBUG(0,("unable to open or create file %s. Error was %s\n", - sid_file, strerror(errno) )); - return False; - } - - /* - * Check if the file contains data. - */ - - if (sys_fstat(fd, &st) < 0) { - DEBUG(0,("unable to stat file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - if (st.st_size > 0) - { - /* - * We have a valid SID already. - */ - close(fd); - DEBUG(0,("SID file %s already exists\n", sid_file)); - return False; - } - - if (!do_file_lock(fd, 60, F_WRLCK)) - { - DEBUG(0,("unable to lock file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - /* - * At this point we have a blocking lock on the SID - * file - check if in the meantime someone else wrote - * SID data into the file. If so - they were here first, - * use their data. - */ - - if (sys_fstat(fd, &st) < 0) - { - DEBUG(0,("unable to stat file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - if (st.st_size > 0) - { - /* - * Unlock as soon as possible to reduce - * contention on the exclusive lock. - */ - do_file_lock(fd, 60, F_UNLCK); - - /* - * We have a valid SID already. - */ - - DEBUG(0,("SID file %s already exists\n", sid_file)); - close(fd); - return False; - } - - /* - * The file is still empty and we have an exlusive lock on it. - * Write out out SID data into the file. - */ - - if (fchmod(fd, 0644) < 0) - { - DEBUG(0,("unable to set correct permissions on file %s. \ -Error was %s\n", sid_file, strerror(errno) )); - close(fd); - return False; - } - - if (write(fd, sid_string, strlen(sid_string)) != strlen(sid_string)) - { - DEBUG(0,("unable to write file %s. Error was %s\n", - sid_file, strerror(errno) )); - close(fd); - return False; - } - - /* - * Unlock & exit. - */ - - do_file_lock(fd, 60, F_UNLCK); - close(fd); return True; -} +} -/**************************************************************************** -create a random SID. -****************************************************************************/ -BOOL create_new_sid(DOM_SID *sid) -{ - uchar raw_sid_data[12]; - fstring sid_string; - int i; - /* - * Generate the new sid data & turn it into a string. - */ - generate_random_buffer(raw_sid_data, 12, True); - - fstrcpy(sid_string, "S-1-5-21"); - for(i = 0; i < 3; i++) - { - fstring tmp_string; - slprintf(tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4)); - fstrcat(sid_string, tmp_string); - } - - fstrcat(sid_string, "\n"); - - /* - * Ensure our new SID is valid. - */ - - if (!string_to_sid(sid, sid_string)) - { - DEBUG(0,("unable to generate machine SID.\n")); - return False; - } +/***************************************************************** + Calculates size of a sid. +*****************************************************************/ - return True; +size_t sid_size(DOM_SID *sid) +{ + if (sid == NULL) + return 0; + + return sid->num_auths * sizeof(uint32) + 8; } - diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index d9b0f97259..77ba4a7f4c 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -35,22 +35,18 @@ BOOL passive = False; /* the client file descriptor */ int Client = -1; -/* the port, where client connected */ -int ClientPort = 0; - /* the last IP received from */ struct in_addr lastip; /* the last port received from */ int lastport=0; - int smb_read_error = 0; - /**************************************************************************** -determine if a file descriptor is in fact a socket + Determine if a file descriptor is in fact a socket. ****************************************************************************/ + BOOL is_a_socket(int fd) { int v,l; @@ -58,7 +54,6 @@ BOOL is_a_socket(int fd) return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0); } - enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; struct @@ -101,69 +96,63 @@ struct #endif {NULL,0,0,0,0}}; - - /**************************************************************************** -set user socket options + Set user socket options. ****************************************************************************/ + void set_socket_options(int fd, char *options) { - fstring tok; - - while (next_token(&options,tok," \t,", sizeof(tok))) - { - 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; - } + fstring tok; + + while (next_token(&options,tok," \t,", sizeof(tok))) { + 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; + 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; - } + 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; - } + 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)); - } + if (ret != 0) + DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) )); + } } - - /**************************************************************************** - close the socket communication + Close the socket communication. ****************************************************************************/ + void close_sockets(void ) { #ifdef WITH_SSL @@ -174,31 +163,10 @@ void close_sockets(void ) Client = -1; } - - /**************************************************************************** -write to a socket + Read from a socket. ****************************************************************************/ -ssize_t write_socket(int fd,char *buf,size_t len) -{ - ssize_t 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)); - if(ret <= 0) - DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n", - len, fd, strerror(errno) )); - return(ret); -} - -/**************************************************************************** -read from a socket -****************************************************************************/ ssize_t read_udp_socket(int fd,char *buf,size_t len) { ssize_t ret; @@ -206,8 +174,8 @@ ssize_t read_udp_socket(int fd,char *buf,size_t len) int socklen; socklen = sizeof(sock); - bzero((char *)&sock,socklen); - bzero((char *)&lastip,sizeof(lastip)); + memset((char *)&sock,'\0',socklen); + memset((char *)&lastip,'\0',sizeof(lastip)); ret = (ssize_t)recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen); if (ret <= 0) { DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno))); @@ -224,13 +192,13 @@ ssize_t read_udp_socket(int fd,char *buf,size_t len) } /**************************************************************************** -read data from a device with a timout in msec. -mincount = if timeout, minimum to read before returning -maxcount = number to be read. -time_out = timeout in milliseconds + Read data from a socket with a timout in msec. + mincount = if timeout, minimum to read before returning + maxcount = number to be read. + time_out = timeout in milliseconds ****************************************************************************/ -ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out) +static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out) { fd_set fds; int selrtn; @@ -239,7 +207,8 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned struct timeval timeout; /* just checking .... */ - if (maxcnt <= 0) return(0); + if (maxcnt <= 0) + return(0); smb_read_error = 0; @@ -259,11 +228,13 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned #endif /* WITH_SSL */ if (readret == 0) { + DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { + DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } @@ -282,22 +253,23 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned timeout.tv_sec = (time_t)(time_out / 1000); timeout.tv_usec = (long)(1000 * (time_out % 1000)); - for (nread=0; nread < mincnt; ) - { + for (nread=0; nread < mincnt; ) { FD_ZERO(&fds); FD_SET(fd,&fds); - selrtn = sys_select(fd+1,&fds,NULL, &timeout); + selrtn = sys_select(fd+1,&fds,&timeout); /* Check if error */ if(selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ + DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } - + /* Did we timeout ? */ if (selrtn == 0) { + DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n")); smb_read_error = READ_TIMEOUT; return -1; } @@ -314,12 +286,14 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned if (readret == 0) { /* we got EOF on the file descriptor */ + DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { /* the descriptor is probably dead */ + DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } @@ -331,10 +305,91 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned return((ssize_t)nread); } +/**************************************************************************** + Read data from a fd with a timout in msec. + mincount = if timeout, minimum to read before returning + maxcount = number to be read. + time_out = timeout in milliseconds +****************************************************************************/ + +ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out) +{ + fd_set fds; + int selrtn; + ssize_t readret; + size_t nread = 0; + struct timeval timeout; + + /* just checking .... */ + if (maxcnt <= 0) + return(0); + + /* Blocking read */ + if (time_out <= 0) { + 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) + return readret; + + nread += readret; + } + return((ssize_t)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 returns true on disk files */ + + /* Set initial timeout */ + timeout.tv_sec = (time_t)(time_out / 1000); + timeout.tv_usec = (long)(1000 * (time_out % 1000)); + + for (nread=0; nread < mincnt; ) { + FD_ZERO(&fds); + FD_SET(fd,&fds); + + selrtn = sys_select(fd+1,&fds,&timeout); + + if(selrtn <= 0) + return selrtn; + +#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) + return readret; + + nread += readret; + } + + /* Return the number we got */ + return((ssize_t)nread); +} /**************************************************************************** send a keepalive packet (rfc1002) ****************************************************************************/ + BOOL send_keepalive(int client) { unsigned char buf[4]; @@ -342,14 +397,13 @@ BOOL send_keepalive(int client) buf[0] = 0x85; buf[1] = buf[2] = buf[3] = 0; - return(write_data(client,(char *)buf,4) == 4); + return(write_socket_data(client,(char *)buf,4) == 4); } - - /**************************************************************************** read data from the client, reading exactly N bytes. ****************************************************************************/ + ssize_t read_data(int fd,char *buffer,size_t N) { ssize_t ret; @@ -371,11 +425,13 @@ ssize_t read_data(int fd,char *buffer,size_t N) if (ret == 0) { + DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); smb_read_error = READ_EOF; return 0; } if (ret == -1) { + DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); smb_read_error = READ_ERROR; return -1; } @@ -384,10 +440,50 @@ ssize_t read_data(int fd,char *buffer,size_t N) return (ssize_t)total; } +/**************************************************************************** + Read data from a socket, reading exactly N bytes. +****************************************************************************/ + +static ssize_t read_socket_data(int fd,char *buffer,size_t N) +{ + ssize_t ret; + size_t total=0; + + 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); + } +#else /* WITH_SSL */ + ret = read(fd,buffer + total,N - total); +#endif /* WITH_SSL */ + + if (ret == 0) + { + DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); + smb_read_error = READ_EOF; + return 0; + } + if (ret == -1) + { + DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); + smb_read_error = READ_ERROR; + return -1; + } + total += ret; + } + return (ssize_t)total; +} /**************************************************************************** - write data to a fd + Write data to a fd. ****************************************************************************/ + ssize_t write_data(int fd,char *buffer,size_t N) { size_t total=0; @@ -405,7 +501,42 @@ ssize_t write_data(int fd,char *buffer,size_t N) ret = write(fd,buffer + total,N - total); #endif /* WITH_SSL */ - if (ret == -1) return -1; + if (ret == -1) { + DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) )); + return -1; + } + if (ret == 0) return total; + + total += ret; + } + return (ssize_t)total; +} + +/**************************************************************************** + Write data to a socket - use send rather than write. +****************************************************************************/ + +ssize_t write_socket_data(int fd,char *buffer,size_t N) +{ + size_t total=0; + ssize_t ret; + + while (total < N) + { +#ifdef WITH_SSL + if(fd == sslFd){ + ret = SSL_write(ssl,buffer + total,N - total); + }else{ + ret = send(fd,buffer + total,N - total, 0); + } +#else /* WITH_SSL */ + ret = send(fd,buffer + total,N - total,0); +#endif /* WITH_SSL */ + + if (ret == -1) { + DEBUG(0,("write_socket_data: write failure. Error = %s\n", strerror(errno) )); + return -1; + } if (ret == 0) return total; total += ret; @@ -413,7 +544,26 @@ ssize_t write_data(int fd,char *buffer,size_t N) return (ssize_t)total; } +/**************************************************************************** +write to a socket +****************************************************************************/ +ssize_t write_socket(int fd,char *buf,size_t len) +{ + ssize_t ret=0; + + if (passive) + return(len); + DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len)); + ret = write_socket_data(fd,buf,len); + + DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret)); + if(ret <= 0) + DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n", + (int)len, fd, strerror(errno) )); + + return(ret); +} /**************************************************************************** read 4 bytes of a smb packet and return the smb length of the packet @@ -422,6 +572,7 @@ This version of the function will return a length of zero on receiving a keepalive packet. timeout is in milliseconds. ****************************************************************************/ + static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout) { ssize_t len=0; @@ -431,9 +582,9 @@ static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int while (!ok) { if (timeout > 0) - ok = (read_with_timeout(fd,inbuf,4,4,timeout) == 4); + ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout) == 4); else - ok = (read_data(fd,inbuf,4) == 4); + ok = (read_socket_data(fd,inbuf,4) == 4); if (!ok) return(-1); @@ -456,6 +607,7 @@ store the result in the buffer. This version of the function will never return a session keepalive (length of zero). timeout is in milliseconds. ****************************************************************************/ + ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) { ssize_t len; @@ -472,6 +624,8 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) break; } + DEBUG(10,("read_smb_length: got smb length of %d\n",len)); + return len; } @@ -482,13 +636,14 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) This function will return on a receipt of a session keepalive packet. ****************************************************************************/ + BOOL receive_smb(int fd,char *buffer, unsigned int timeout) { ssize_t len,ret; smb_read_error = 0; - bzero(buffer,smb_size + 100); + memset(buffer,'\0',smb_size + 100); len = read_smb_length_return_keepalive(fd,buffer,timeout); if (len < 0) @@ -506,7 +661,7 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout) } if(len > 0) { - ret = read_data(fd,buffer+4,len); + ret = read_socket_data(fd,buffer+4,len); if (ret != len) { smb_read_error = READ_ERROR; return False; @@ -529,7 +684,6 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout) BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout) { BOOL ret; - uint8 msg_type; for(;;) { @@ -543,25 +697,45 @@ BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout) } /* Ignore session keepalive packets. */ - msg_type = CVAL(buffer,0); - if (msg_type != 0x85) + if(CVAL(buffer,0) != 0x85) break; } - if (msg_type == 0) - { - show_msg(buffer); - } - else - { - dump_data(10, buffer, smb_len(buffer) + 4); - } show_msg(buffer); return ret; } /**************************************************************************** + send an null session message to a fd +****************************************************************************/ + +BOOL send_null_session_msg(int fd) +{ + ssize_t ret; + uint32 blank = 0; + size_t len = 4; + size_t nwritten=0; + char *buffer = (char *)␣ + + while (nwritten < len) + { + ret = write_socket(fd,buffer+nwritten,len - nwritten); + if (ret <= 0) + { + DEBUG(0,("send_null_session_msg: Error writing %d bytes to client. %d. Exiting\n",(int)len,(int)ret)); + close_sockets(); + exit(1); + } + nwritten += ret; + } + + DEBUG(10,("send_null_session_msg: sent 4 null bytes to client.\n")); + return True; +} + +/**************************************************************************** send an smb to a fd ****************************************************************************/ + BOOL send_smb(int fd,char *buffer) { size_t len; @@ -574,7 +748,7 @@ BOOL send_smb(int fd,char *buffer) ret = write_socket(fd,buffer+nwritten,len - nwritten); if (ret <= 0) { - DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret)); + DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",(int)len,(int)ret)); close_sockets(); exit(1); } @@ -584,11 +758,10 @@ BOOL send_smb(int fd,char *buffer) return True; } - - /**************************************************************************** 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; @@ -607,7 +780,7 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type) } /* set the address and port */ - bzero((char *)&sock_out,sizeof(sock_out)); + memset((char *)&sock_out,'\0',sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)&ip); sock_out.sin_port = htons( port ); sock_out.sin_family = AF_INET; @@ -627,11 +800,11 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type) return(ret); } - /**************************************************************************** open a socket of the specified type, port and address for incoming data ****************************************************************************/ -int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) + +int open_socket_in(int type, int port, int dlevel,uint32 socket_addr, BOOL rebind) { struct hostent *hp; struct sockaddr_in sock; @@ -649,7 +822,7 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) return -1; } - bzero((char *)&sock,sizeof(sock)); + memset((char *)&sock,'\0',sizeof(sock)); memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length); #ifdef HAVE_SOCK_SIN_LEN @@ -663,8 +836,12 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) { DEBUG(0,("socket failed\n")); return -1; } { - int one=1; - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); + int val=1; + if(rebind) + val=1; + else + val=0; + setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); } /* now we've got a socket - we need to bind it */ @@ -680,7 +857,7 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) port = 7999; if (port >= 1000 && port < 9000) - return(open_socket_in(type,port+1,dlevel,socket_addr)); + return(open_socket_in(type,port+1,dlevel,socket_addr,rebind)); } return(-1); @@ -690,16 +867,16 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) return res; } - /**************************************************************************** - create an outgoing socket + create an outgoing socket. timeout is in milliseconds. **************************************************************************/ + int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) { struct sockaddr_in sock_out; int res,ret; int connect_loop = 250; /* 250 milliseconds */ - int loops = (timeout * 1000) / connect_loop; + int loops = (timeout) / connect_loop; /* create a socket to write to */ res = socket(PF_INET, type, 0); @@ -708,7 +885,7 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) if (type != SOCK_STREAM) return(res); - bzero((char *)&sock_out,sizeof(sock_out)); + memset((char *)&sock_out,'\0',sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)addr); sock_out.sin_port = htons( port ); @@ -786,6 +963,7 @@ void reset_globals_after_fork(void) /******************************************************************* return the DNS name of the client ******************************************************************/ + char *client_name(int fd) { struct sockaddr sa; @@ -832,6 +1010,7 @@ char *client_name(int fd) /******************************************************************* return the IP addr of the client as a string ******************************************************************/ + char *client_addr(int fd) { struct sockaddr sa; @@ -862,101 +1041,3 @@ char *client_addr(int fd) global_client_addr_done = True; return addr_buf; } - -/******************************************************************* - opens and connects to a unix pipe socket - ******************************************************************/ -int open_pipe_sock(char *path) -{ - int sock; - struct sockaddr_un sa; - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - - if (sock < 0) - { - DEBUG(0, ("unix socket open failed\n")); - return sock; - } - - ZERO_STRUCT(sa); - sa.sun_family = AF_UNIX; - safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1); - - DEBUG(10, ("socket open succeeded. file name: %s\n", sa.sun_path)); - - if (connect(sock, (struct sockaddr*) &sa, sizeof(sa)) < 0) - { - DEBUG(0,("socket connect to %s failed\n", sa.sun_path)); - close(sock); - return -1; - } - - return sock; -} - -int create_pipe_socket(char *dir, int dir_perms, - char *path, int path_perms) -{ - int s; - struct sockaddr_un sa; - - DEBUG(10,("create_pipe_socket: %s %d %s %d\n", - dir, dir_perms, path, path_perms)); - - mkdir(dir, dir_perms); - - if (chmod(dir, dir_perms) < 0) - { - DEBUG(0, ("chmod on %s failed\n", dir)); - return -1; - } - - if (!remove(path)) - { - DEBUG(0, ("remove on %s failed\n", path)); - } - - /* start listening on unix socket */ - s = socket(AF_UNIX, SOCK_STREAM, 0); - - if (s < 0) - { - DEBUG(0, ("socket open failed\n")); - return -1; - } - - ZERO_STRUCT(sa); - sa.sun_family = AF_UNIX; - safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1); - - if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) < 0) - { - DEBUG(0, ("socket bind to %s failed\n", sa.sun_path)); - close(s); - remove(path); - return -1; - } - - if (s == -1) - { - DEBUG(0,("bind failed\n")); - remove(path); - return -1; - } - - if (path_perms != 0) - { - chmod(path, path_perms); - } - - if (listen(s, 5) == -1) - { - DEBUG(0,("listen failed\n")); - return -1; - } - - DEBUG(5,("unix socket opened: %s\n", path)); - - return s; -} diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index a25043df78..58718f395a 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -462,7 +462,7 @@ char *skip_string(char *buf,size_t n) { while (n--) buf += strlen(buf) + 1; - return buf; + return(buf); } /******************************************************************* @@ -733,21 +733,69 @@ size_t count_chars(const char *s,char c) return(count); } +/******************************************************************* +Return True if a string consists only of one particular character. +********************************************************************/ +BOOL str_is_all(const char *s,char c) +{ + if(s == NULL) + return False; + if(!*s) + return False; + +#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 (is_shift_jis (*s)) + s += 2; + else + { + if (*s != c) + return False; + s++; + } + } + } + else +#endif /* KANJI_WIN95_COMPATIBILITY */ + { + while (*s) + { + size_t skip = skip_multibyte_char( *s ); + if( skip != 0 ) + s += skip; + else { + if (*s != c) + return False; + s++; + } + } + } + return True; +} /******************************************************************* safe string copy into a known length string. maxlength does not include the terminating zero. ********************************************************************/ + char *safe_strcpy(char *dest,const char *src, size_t maxlength) { size_t len; - if (maxlength == 0) - { - return dest; - } - if (!dest) { DEBUG(0,("ERROR: NULL dest in safe_strcpy\n")); return NULL; @@ -762,7 +810,7 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength) if (len > maxlength) { DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n", - len-maxlength, src)); + (int)(len-maxlength), src)); len = maxlength; } @@ -775,6 +823,7 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength) safe string cat into a string. maxlength does not include the terminating zero. ********************************************************************/ + char *safe_strcat(char *dest, const char *src, size_t maxlength) { size_t src_len, dest_len; @@ -793,7 +842,7 @@ char *safe_strcat(char *dest, const char *src, size_t maxlength) if (src_len + dest_len > maxlength) { DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n", - src_len + dest_len - maxlength, src)); + (int)(src_len + dest_len - maxlength), src)); src_len = maxlength - dest_len; } @@ -802,28 +851,48 @@ char *safe_strcat(char *dest, const char *src, size_t maxlength) return dest; } -/**************************************************************************** -this is a safer strcpy(), meant to prevent core dumps when nasty things happen -****************************************************************************/ -char *StrCpy(char *dest,const char *src) +/******************************************************************* + Paranoid strcpy into a buffer of given length (includes terminating + zero. Strips out all but 'a-Z0-9' and replaces with '_'. Deliberately + does *NOT* check for multibyte characters. Don't change it ! +********************************************************************/ + +char *alpha_strcpy(char *dest, const char *src, size_t maxlength) { - char *d = dest; + size_t len, i; - /* I don't want to get lazy with these ... */ - SMB_ASSERT(dest && src); + if (!dest) { + DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n")); + return NULL; + } - if (!dest) return(NULL); - if (!src) { - *dest = 0; - return(dest); - } - while ((*d++ = *src++)) ; - return(dest); + if (!src) { + *dest = 0; + return dest; + } + + len = strlen(src); + if (len >= maxlength) + len = maxlength - 1; + + for(i = 0; i < len; i++) { + int val = (src[i] & 0xff); + if(isupper(val) ||islower(val) || isdigit(val)) + dest[i] = src[i]; + else + dest[i] = '_'; + } + + dest[i] = '\0'; + + return dest; } /**************************************************************************** -like strncpy but always null terminates. Make sure there is room! + Like strncpy but always null terminates. Make sure there is room! + The variable n should always be one less than the available size. ****************************************************************************/ + char *StrnCpy(char *dest,const char *src,size_t n) { char *d = dest; @@ -837,12 +906,11 @@ char *StrnCpy(char *dest,const char *src,size_t n) return(dest); } - /**************************************************************************** like strncpy but copies up to the character marker. always null terminates. returns a pointer to the character marker in the source string (src). ****************************************************************************/ -char *strncpyn(char *dest, char *src,size_t n, char c) +char *strncpyn(char *dest, const char *src,size_t n, char c) { char *p; size_t str_len; @@ -1003,29 +1071,42 @@ enough room! This routine looks for pattern in s and replaces it with insert. It may do multiple replacements. -any of " ; ' or ` in the insert string are replaced with _ +any of " ; ' $ or ` in the insert string are replaced with _ +if len==0 then no length check is performed ****************************************************************************/ -void string_sub(char *s,const char *pattern,const char *insert) +void string_sub(char *s,const char *pattern,const char *insert, size_t len) { char *p; - size_t ls,lp,li, i; + ssize_t ls,lp,li, i; if (!insert || !pattern || !s) return; - ls = strlen(s); - lp = strlen(pattern); - li = strlen(insert); + ls = (ssize_t)strlen(s); + lp = (ssize_t)strlen(pattern); + li = (ssize_t)strlen(insert); if (!*pattern) return; while (lp <= ls && (p = strstr(s,pattern))) { - memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp)); + if (len && (ls + (li-lp) >= len)) { + DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", + (int)(ls + (li-lp) - len), + pattern, (int)len)); + break; + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } for (i=0;i<li;i++) { switch (insert[i]) { case '`': case '"': case '\'': case ';': + case '$': + case '%': + case '\r': + case '\n': p[i] = '_'; break; default: @@ -1037,26 +1118,44 @@ void string_sub(char *s,const char *pattern,const char *insert) } } +void fstring_sub(char *s,const char *pattern,const char *insert) +{ + string_sub(s, pattern, insert, sizeof(fstring)); +} + +void pstring_sub(char *s,const char *pattern,const char *insert) +{ + string_sub(s, pattern, insert, sizeof(pstring)); +} /**************************************************************************** similar to string_sub() but allows for any character to be substituted. Use with caution! +if len==0 then no length check is performed ****************************************************************************/ -void all_string_sub(char *s,const char *pattern,const char *insert) +void all_string_sub(char *s,const char *pattern,const char *insert, size_t len) { char *p; - size_t ls,lp,li; + ssize_t ls,lp,li; if (!insert || !pattern || !s) return; - ls = strlen(s); - lp = strlen(pattern); - li = strlen(insert); + ls = (ssize_t)strlen(s); + lp = (ssize_t)strlen(pattern); + li = (ssize_t)strlen(insert); if (!*pattern) return; while (lp <= ls && (p = strstr(s,pattern))) { - memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp)); + if (len && (ls + (li-lp) >= len)) { + DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", + (int)(ls + (li-lp) - len), + pattern, (int)len)); + break; + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } memcpy(p, insert, li); s = p + li; ls += (li-lp); @@ -1066,38 +1165,6 @@ void all_string_sub(char *s,const char *pattern,const char *insert) /**************************************************************************** splits out the front and back at a separator. ****************************************************************************/ -void split_at_first_component(char *path, char *front, char sep, char *back) -{ - char *p = strchr(path, sep); - - if (p != NULL) - { - *p = 0; - } - if (front != NULL) - { - pstrcpy(front, path); - } - if (p != NULL) - { - if (back != NULL) - { - pstrcpy(back, p+1); - } - *p = sep; - } - else - { - if (back != NULL) - { - back[0] = 0; - } - } -} - -/**************************************************************************** - splits out the front and back at a separator. -****************************************************************************/ void split_at_last_component(char *path, char *front, char sep, char *back) { char *p = strrchr(path, sep); @@ -1116,7 +1183,7 @@ void split_at_last_component(char *path, char *front, char sep, char *back) { pstrcpy(back, p+1); } - *p = sep; + *p = '\\'; } else { @@ -1127,72 +1194,28 @@ void split_at_last_component(char *path, char *front, char sep, char *back) } } -/**************************************************************************** -convert a bit field to a string. if you want multiple bits to be detected -set them first, e.g SV_TYPE_ALL to be "All" or "Full Control" for ACB_INFOs. - -strings are expected to contain their own separators, although the code -below only assumes that separators are spaces. +/**************************************************************************** +write an octal as a string ****************************************************************************/ -char *bit_field_to_str(uint32 type, struct field_info *bs) +char *octal_string(int i) { - static fstring typestr; - int i = 0; - - typestr[0] = 0; - - if (type == 0 || bs == NULL) - { - return NULL; - } - - while (bs[i].str != NULL && type != 0) - { - if (IS_BITS_SET_ALL(bs[i].bits, type)) - { - fstrcat(typestr, bs[i].str); - type &= ~bs[i].bits; - } - i++; - } - - i = strlen(typestr)-1; - if (i > 0 && typestr[i] == ' ') - { - typestr[i] = 0; + static char ret[64]; + if (i == -1) { + return "-1"; } - - return typestr; + slprintf(ret, sizeof(ret), "0%o", i); + return ret; } + /**************************************************************************** -convert an enumeration to a string. first item is the default. +truncate a string at a specified length ****************************************************************************/ -char *enum_field_to_str(uint32 type, struct field_info *bs, BOOL first_default) +char *string_truncate(char *s, int length) { - int i = 0; - - if (bs == NULL) - { - return NULL; + if (s && strlen(s) > length) { + s[length] = 0; } - - while (bs[i].str != NULL && type != 0) - { - if (bs[i].bits == type) - { - return bs[i].str; - } - i++; - } - - /* oops - none found */ - - if (first_default) - { - return bs[0].str; - } - - return NULL; + return s; } diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index 6f90528bf4..aee2a21fc0 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -21,287 +21,538 @@ #include "includes.h" -/******************************************************************* - Put an ASCII string into a UNICODE buffer (little endian). - ********************************************************************/ +extern int DEBUGLEVEL; -char *ascii_to_unibuf(char *dest, const char *src, int maxlen) -{ - char *destend = dest + maxlen; - register char c; - - while (dest < destend) - { - c = *(src++); - if (c == 0) - { - break; - } +/* + * The following are the codepage to ucs2 and vica versa maps. + * These are dynamically loaded from a unicode translation file. + */ - *(dest++) = c; - *(dest++) = 0; - } +static smb_ucs2_t *doscp_to_ucs2; +static uint16 *ucs2_to_doscp; - *dest++ = 0; - *dest++ = 0; - return dest; -} +static smb_ucs2_t *unixcp_to_ucs2; +static uint16 *ucs2_to_unixcp; +#ifndef MAXUNI +#define MAXUNI 1024 +#endif /******************************************************************* - Pull an ASCII string out of a UNICODE buffer (little endian). - ********************************************************************/ + Write a string in (little-endian) unicode format. src is in + the current DOS codepage. len is the length in bytes of the + string pointed to by dst. -const char* unibuf_to_ascii(char *dest, const char *src, int maxlen) -{ - char *destend = dest + maxlen; - register char c; - - while (dest < destend) - { - c = *(src++); - if ((c == 0) && (*src == 0)) - { - break; - } + the return value is the length of the string *without* the trailing + two bytes of zero +********************************************************************/ - *dest++ = c; - src++; +int dos_PutUniCode(char *dst,const char *src, ssize_t len) +{ + int ret = 0; + while (*src && (len > 2)) { + size_t skip = skip_multibyte_char(*src); + smb_ucs2_t val = (*src & 0xff); + + /* + * If this is a multibyte character (and all DOS/Windows + * codepages have at maximum 2 byte multibyte characters) + * then work out the index value for the unicode conversion. + */ + + if (skip == 2) + val = ((val << 8) | src[1]); + + SSVAL(dst,ret,doscp_to_ucs2[val]); + ret += 2; + len -= 2; + if (skip) + src += skip; + else + src++; } + SSVAL(dst,ret,0); + return(ret); +} - *dest = 0; +/******************************************************************* + Skip past some unicode strings in a buffer. +********************************************************************/ - return src; +char *skip_unicode_string(char *buf,int n) +{ + while (n--) { + while (*buf) + buf += 2; + buf += 2; + } + return(buf); } - /******************************************************************* - Put an ASCII string into a UNICODE array (uint16's). - ********************************************************************/ + Return a DOS codepage version of a little-endian unicode string. + Hack alert: uses fixed buffer(s). +********************************************************************/ -void ascii_to_unistr(uint16 *dest, const char *src, int maxlen) +char *dos_unistrn2(uint16 *src, int len) { - uint16 *destend = dest + maxlen; - register char c; - - while (dest < destend) - { - c = *(src++); - if (c == 0) - { - break; + static char lbufs[8][MAXUNI]; + static int nexti; + char *lbuf = lbufs[nexti]; + char *p; + + nexti = (nexti+1)%8; + + for (p = lbuf; (len > 0) && (p-lbuf < MAXUNI-3) && *src; len--, src++) { + uint16 ucs2_val = SVAL(src,0); + uint16 cp_val = ucs2_to_doscp[ucs2_val]; + + if (cp_val < 256) + *p++ = (char)cp_val; + else { + *p++ = (cp_val >> 8) & 0xff; + *p++ = (cp_val & 0xff); } - - *(dest++) = (uint16)c; } - *dest = 0; + *p = 0; + return lbuf; } +static char lbufs[8][MAXUNI]; +static int nexti; /******************************************************************* - Pull an ASCII string out of a UNICODE array (uint16's). - ********************************************************************/ + Return a DOS codepage version of a little-endian unicode string. + Hack alert: uses fixed buffer(s). +********************************************************************/ -void unistr_to_ascii(char *dest, const uint16 *src, int len) +char *dos_unistr2(uint16 *src) { - char *destend = dest + len; - register uint16 c; - - while (dest < destend) - { - c = *(src++); - if (c == 0) - { - break; - } + char *lbuf = lbufs[nexti]; + char *p; + + nexti = (nexti+1)%8; + + for (p = lbuf; *src && (p-lbuf < MAXUNI-3); src++) { + uint16 ucs2_val = SVAL(src,0); + uint16 cp_val = ucs2_to_doscp[ucs2_val]; - *(dest++) = (char)c; + if (cp_val < 256) + *p++ = (char)cp_val; + else { + *p++ = (cp_val >> 8) & 0xff; + *p++ = (cp_val & 0xff); + } } - *dest = 0; + *p = 0; + return lbuf; } - /******************************************************************* - Convert a UNISTR2 structure to an ASCII string - ********************************************************************/ +Return a DOS codepage version of a little-endian unicode string +********************************************************************/ -void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen) +char *dos_unistr2_to_str(UNISTR2 *str) { - char *destend; - const uint16 *src; - size_t len; - register uint16 c; - - src = str->buffer; - len = MIN(str->uni_str_len, maxlen); - destend = dest + len; - - while (dest < destend) - { - c = *(src++); - if (c == 0) - { - break; + char *lbuf = lbufs[nexti]; + char *p; + uint16 *src = str->buffer; + int max_size = MIN(sizeof(str->buffer)-3, str->uni_str_len); + + nexti = (nexti+1)%8; + + for (p = lbuf; *src && p-lbuf < max_size; src++) { + uint16 ucs2_val = SVAL(src,0); + uint16 cp_val = ucs2_to_doscp[ucs2_val]; + + if (cp_val < 256) + *p++ = (char)cp_val; + else { + *p++ = (cp_val >> 8) & 0xff; + *p++ = (cp_val & 0xff); } - - *(dest++) = (char)c; } - *dest = 0; + *p = 0; + return lbuf; } - /******************************************************************* - Skip a UNICODE string in a little endian buffer. - ********************************************************************/ +Return a number stored in a buffer +********************************************************************/ -char *skip_unibuf(char *srcbuf, int len) +uint32 buffer2_to_uint32(BUFFER2 *str) { - uint16 *src = (uint16 *)srcbuf; - uint16 *srcend = src + len/2; + if (str->buf_len == 4) + return IVAL(str->buffer, 0); + else + return 0; +} - while ((src < srcend) && (*(src++) != 0)) - { +/******************************************************************* +Return a DOS codepage version of a NOTunicode string +********************************************************************/ + +char *dos_buffer2_to_str(BUFFER2 *str) +{ + char *lbuf = lbufs[nexti]; + char *p; + uint16 *src = str->buffer; + int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2); + + nexti = (nexti+1)%8; + + for (p = lbuf; *src && p-lbuf < max_size; src++) { + uint16 ucs2_val = SVAL(src,0); + uint16 cp_val = ucs2_to_doscp[ucs2_val]; + + if (cp_val < 256) + *p++ = (char)cp_val; + else { + *p++ = (cp_val >> 8) & 0xff; + *p++ = (cp_val & 0xff); + } } - return (char *)src; + *p = 0; + return lbuf; } - /******************************************************************* - UNICODE strcpy between buffers. - ********************************************************************/ + Return a dos codepage version of a NOTunicode string +********************************************************************/ -char *uni_strncpy(char *destbuf, const char *srcbuf, int len) +char *dos_buffer2_to_multistr(BUFFER2 *str) { - const uint16 *src = (const uint16 *)srcbuf; - uint16 *dest = (uint16 *)destbuf; - uint16 *destend = dest + len/2; - register uint16 c; - - while (dest < destend) - { - c = *(src++); - if (c == 0) - { - break; + char *lbuf = lbufs[nexti]; + char *p; + uint16 *src = str->buffer; + int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2); + + nexti = (nexti+1)%8; + + for (p = lbuf; p-lbuf < max_size; src++) { + if (*src == 0) { + *p++ = ' '; + } else { + uint16 ucs2_val = SVAL(src,0); + uint16 cp_val = ucs2_to_doscp[ucs2_val]; + + if (cp_val < 256) + *p++ = (char)cp_val; + else { + *p++ = (cp_val >> 8) & 0xff; + *p++ = (cp_val & 0xff); + } } - - *(dest++) = c; } - *dest++ = 0; - return (char *)dest; + *p = 0; + return lbuf; } - /******************************************************************* - Return a number stored in a buffer - ********************************************************************/ + Create a null-terminated unicode string from a null-terminated DOS + codepage string. + Return number of unicode chars copied, excluding the null character. + Unicode strings created are in little-endian format. +********************************************************************/ -uint32 buffer2_to_uint32(const BUFFER2 *str) +size_t dos_struni2(char *dst, const char *src, size_t max_len) { - if (str->buf_len == 4) - { - const uchar *src = str->buffer; - return IVAL(src, 0); - } - else - { + size_t len = 0; + + if (dst == NULL) return 0; + + if (src != NULL) { + for (; *src && len < max_len-2; len++, dst +=2) { + size_t skip = skip_multibyte_char(*src); + smb_ucs2_t val = (*src & 0xff); + + /* + * If this is a multibyte character (and all DOS/Windows + * codepages have at maximum 2 byte multibyte characters) + * then work out the index value for the unicode conversion. + */ + + if (skip == 2) + val = ((val << 8) | src[1]); + + SSVAL(dst,0,doscp_to_ucs2[val]); + if (skip) + src += skip; + else + src++; + } } -} + SSVAL(dst,0,0); + + return len; +} /******************************************************************* - Convert a 'multi-string' buffer to space-separated ASCII. - ********************************************************************/ -void buffer2_to_multistr(char *dest, const BUFFER2 *str, size_t maxlen) + Return a DOS codepage version of a little-endian unicode string. + Hack alert: uses fixed buffer(s). +********************************************************************/ + +char *dos_unistr(char *buf) { - char *destend; - const uchar *src; - size_t len; - register uint16 c; - - src = str->buffer; - len = MIN(str->buf_len/2, maxlen); - destend = dest + len; - - while (dest < destend) - { - c = *(src++); - *(dest++) = (c == 0) ? ' ' : (char)c; - src++; + char *lbuf = lbufs[nexti]; + uint16 *src = (uint16 *)buf; + char *p; + + nexti = (nexti+1)%8; + + for (p = lbuf; *src && p-lbuf < MAXUNI-3; src++) { + uint16 ucs2_val = SVAL(src,0); + uint16 cp_val = ucs2_to_doscp[ucs2_val]; + + if (cp_val < 256) + *p++ = (char)cp_val; + else { + *p++ = (cp_val >> 8) & 0xff; + *p++ = (cp_val & 0xff); + } } - *dest = 0; + *p = 0; + return lbuf; } /******************************************************************* - Convert a buffer4 to space-separated ASCII. - ********************************************************************/ -void buffer4_to_str(char *dest, const BUFFER4 *str, size_t maxlen) + Strcpy for unicode strings. returns length (in num of wide chars) +********************************************************************/ + +int unistrcpy(char *dst, char *src) { - char *destend; - const uchar *src; - size_t len; - register uint16 c; - - src = str->buffer; - len = MIN(str->buf_len, maxlen); - destend = dest + len; - - while (dest < destend) - { - c = *(src++); - *(dest++) = (char)c; + int num_wchars = 0; + uint16 *wsrc = (uint16 *)src; + uint16 *wdst = (uint16 *)dst; + + while (*wsrc) { + *wdst++ = *wsrc++; + num_wchars++; } + *wdst = 0; - *dest = 0; + return num_wchars; } + + /******************************************************************* -copies a UNISTR2 structure. + free any existing maps ********************************************************************/ -BOOL copy_unistr2(UNISTR2 *str, const UNISTR2 *from) +static void free_maps(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp) { - if (from != NULL) - { - /* set up string lengths. add one if string is not null-terminated */ - str->uni_max_len = from->uni_max_len; - str->undoc = from->undoc; - str->uni_str_len = from->uni_str_len; - - /* copy the string */ - memcpy(str->buffer, from->buffer, sizeof(from->buffer)); + /* this handles identity mappings where we share the pointer */ + if (*pp_ucs2_to_cp == *pp_cp_to_ucs2) { + *pp_ucs2_to_cp = NULL; } - else - { - str->uni_max_len = 1; - str->undoc = 0; - str->uni_str_len = 1; - str->buffer[0] = 0; + + if (*pp_cp_to_ucs2) { + free(*pp_cp_to_ucs2); + *pp_cp_to_ucs2 = NULL; } - return True; + if (*pp_ucs2_to_cp) { + free(*pp_ucs2_to_cp); + *pp_ucs2_to_cp = NULL; + } } + /******************************************************************* -duplicates a UNISTR2 structure. + Build a default (null) codepage to unicode map. ********************************************************************/ -UNISTR2 *unistr2_dup(const UNISTR2 *name) + +void default_unicode_map(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp) { - UNISTR2 *copy = (UNISTR2*)malloc(sizeof(*copy)); - copy_unistr2(copy, name); - return copy; + int i; + + free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp); + + if ((*pp_ucs2_to_cp = (uint16 *)malloc(2*65536)) == NULL) { + DEBUG(0,("default_unicode_map: malloc fail for ucs2_to_cp size %u.\n", 2*65536)); + abort(); + } + + *pp_cp_to_ucs2 = *pp_ucs2_to_cp; /* Default map is an identity. */ + for (i = 0; i < 65536; i++) + (*pp_cp_to_ucs2)[i] = i; } /******************************************************************* -frees a UNISTR2 structure. + Load a codepage to unicode and vica-versa map. ********************************************************************/ -void unistr2_free(UNISTR2 *name) + +BOOL load_unicode_map(const char *codepage, smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp) { - free(name); + pstring unicode_map_file_name; + FILE *fp = NULL; + SMB_STRUCT_STAT st; + smb_ucs2_t *cp_to_ucs2 = *pp_cp_to_ucs2; + uint16 *ucs2_to_cp = *pp_ucs2_to_cp; + size_t cp_to_ucs2_size; + size_t ucs2_to_cp_size; + size_t i; + size_t size; + char buf[UNICODE_MAP_HEADER_SIZE]; + + DEBUG(5, ("load_unicode_map: loading unicode map for codepage %s.\n", codepage)); + + if (*codepage == '\0') + goto clean_and_exit; + + if(strlen(CODEPAGEDIR) + 13 + strlen(codepage) > sizeof(unicode_map_file_name)) { + DEBUG(0,("load_unicode_map: filename too long to load\n")); + goto clean_and_exit; + } + + pstrcpy(unicode_map_file_name, CODEPAGEDIR); + pstrcat(unicode_map_file_name, "/"); + pstrcat(unicode_map_file_name, "unicode_map."); + pstrcat(unicode_map_file_name, codepage); + + if(sys_stat(unicode_map_file_name,&st)!=0) { + DEBUG(0,("load_unicode_map: filename %s does not exist.\n", + unicode_map_file_name)); + goto clean_and_exit; + } + + size = st.st_size; + + if ((size != UNICODE_MAP_HEADER_SIZE + 4*65536) && (size != UNICODE_MAP_HEADER_SIZE +(2*256 + 2*65536))) { + DEBUG(0,("load_unicode_map: file %s is an incorrect size for a \ +unicode map file (size=%d).\n", unicode_map_file_name, (int)size)); + goto clean_and_exit; + } + + if((fp = sys_fopen( unicode_map_file_name, "r")) == NULL) { + DEBUG(0,("load_unicode_map: cannot open file %s. Error was %s\n", + unicode_map_file_name, strerror(errno))); + goto clean_and_exit; + } + + if(fread( buf, 1, UNICODE_MAP_HEADER_SIZE, fp)!=UNICODE_MAP_HEADER_SIZE) { + DEBUG(0,("load_unicode_map: cannot read header from file %s. Error was %s\n", + unicode_map_file_name, strerror(errno))); + goto clean_and_exit; + } + + /* Check the version value */ + if(SVAL(buf,UNICODE_MAP_VERSION_OFFSET) != UNICODE_MAP_FILE_VERSION_ID) { + DEBUG(0,("load_unicode_map: filename %s has incorrect version id. \ +Needed %hu, got %hu.\n", + unicode_map_file_name, (uint16)UNICODE_MAP_FILE_VERSION_ID, + SVAL(buf,UNICODE_MAP_VERSION_OFFSET))); + goto clean_and_exit; + } + + /* Check the codepage value */ + if(!strequal(&buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], codepage)) { + DEBUG(0,("load_unicode_map: codepage %s in file %s is not the same as that \ +requested (%s).\n", &buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], unicode_map_file_name, codepage )); + goto clean_and_exit; + } + + ucs2_to_cp_size = 2*65536; + if (size == UNICODE_MAP_HEADER_SIZE + 4*65536) { + /* + * This is a multibyte code page. + */ + cp_to_ucs2_size = 2*65536; + } else { + /* + * Single byte code page. + */ + cp_to_ucs2_size = 2*256; + } + + /* + * Free any old translation tables. + */ + + free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp); + + if ((cp_to_ucs2 = (smb_ucs2_t *)malloc(cp_to_ucs2_size)) == NULL) { + DEBUG(0,("load_unicode_map: malloc fail for cp_to_ucs2 size %u.\n", cp_to_ucs2_size )); + goto clean_and_exit; + } + + if ((ucs2_to_cp = (uint16 *)malloc(ucs2_to_cp_size)) == NULL) { + DEBUG(0,("load_unicode_map: malloc fail for ucs2_to_cp size %u.\n", ucs2_to_cp_size )); + goto clean_and_exit; + } + + if(fread( (char *)cp_to_ucs2, 1, cp_to_ucs2_size, fp)!=cp_to_ucs2_size) { + DEBUG(0,("load_unicode_map: cannot read cp_to_ucs2 from file %s. Error was %s\n", + unicode_map_file_name, strerror(errno))); + goto clean_and_exit; + } + + if(fread( (char *)ucs2_to_cp, 1, ucs2_to_cp_size, fp)!=ucs2_to_cp_size) { + DEBUG(0,("load_unicode_map: cannot read ucs2_to_cp from file %s. Error was %s\n", + unicode_map_file_name, strerror(errno))); + goto clean_and_exit; + } + + /* + * Now ensure the 16 bit values are in the correct endianness. + */ + + for (i = 0; i < cp_to_ucs2_size/2; i++) + cp_to_ucs2[i] = SVAL(cp_to_ucs2,i*2); + + for (i = 0; i < ucs2_to_cp_size/2; i++) + ucs2_to_cp[i] = SVAL(ucs2_to_cp,i*2); + + fclose(fp); + + *pp_cp_to_ucs2 = cp_to_ucs2; + *pp_ucs2_to_cp = ucs2_to_cp; + + return True; + +clean_and_exit: + + /* pseudo destructor :-) */ + + if(fp != NULL) + fclose(fp); + + free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp); + + default_unicode_map(pp_cp_to_ucs2, pp_ucs2_to_cp); + + return False; +} + +/******************************************************************* + Load a dos codepage to unicode and vica-versa map. +********************************************************************/ + +BOOL load_dos_unicode_map(int codepage) +{ + fstring codepage_str; + + slprintf(codepage_str, sizeof(fstring)-1, "%03d", codepage); + return load_unicode_map(codepage_str, &doscp_to_ucs2, &ucs2_to_doscp); +} + +/******************************************************************* + Load a UNIX codepage to unicode and vica-versa map. +********************************************************************/ + +BOOL load_unix_unicode_map(const char *unix_char_set) +{ + fstring upper_unix_char_set; + + fstrcpy(upper_unix_char_set, unix_char_set); + strupper(upper_unix_char_set); + return load_unicode_map(upper_unix_char_set, &unixcp_to_ucs2, &ucs2_to_unixcp); } |