Skip to content

Commit

Permalink
Add substitutions %t, %j, and %J as path-safe variants of %T, %i, and…
Browse files Browse the repository at this point in the history
… %I.

Rationale: Using the existing substitutions in construction of paths
(dynamic shares, created on client connect) results in directory names with
colons and dots in them. Those can be hard to use when accessed from a
different share, as Windows does not allow : in paths and has some ideas about
dots.

Signed-off-by: Dr. Thomas Orgis <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
Reviewed-by: Garming Sam <[email protected]>
  • Loading branch information
drhpc authored and abartlet committed Jan 8, 2018
1 parent d39664f commit ca66efc
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 0 deletions.
19 changes: 19 additions & 0 deletions docs-xml/manpages/smb.conf.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,13 @@ chmod 1770 /usr/local/samba/lib/usershares
</listitem>
</varlistentry>

<varlistentry>
<term>%J</term>
<listitem><para>the IP address of the client machine,
colons/dots replaced by underscores.</para>
</listitem>
</varlistentry>

<varlistentry>
<term>%i</term>
<listitem><para>the local IP address to which a client connected.</para>
Expand All @@ -519,11 +526,23 @@ chmod 1770 /usr/local/samba/lib/usershares
</listitem>
</varlistentry>

<varlistentry>
<term>%j</term>
<listitem><para>the local IP address to which a client connected,
colons/dots replaced by underscores.</para>
</listitem>
</varlistentry>

<varlistentry>
<term>%T</term>
<listitem><para>the current date and time.</para></listitem>
</varlistentry>

<varlistentry>
<term>%t</term>
<listitem><para>the current date and time in a minimal format without colons (YYYYYmmdd_HHMMSS).</para></listitem>
</varlistentry>

<varlistentry>
<term>%D</term>
<listitem><para>name of the domain or workgroup of the current user.</para></listitem>
Expand Down
51 changes: 51 additions & 0 deletions lib/util/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,57 @@ char *current_timestring(TALLOC_CTX *ctx, bool hires)
return timeval_string(ctx, &tv, hires);
}

/*
* Return date and time as a minimal string avoiding funny characters
* that may cause trouble in file names. We only use digits and
* underscore ... or a minus/hyphen if we got negative time.
*/
char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
{
time_t t;
struct tm *tm;

t = (time_t)tp->tv_sec;
tm = localtime(&t);
if (!tm) {
if (hires) {
return talloc_asprintf(ctx, "%ld_%06ld",
(long)tp->tv_sec,
(long)tp->tv_usec);
} else {
return talloc_asprintf(ctx, "%ld", (long)t);
}
} else {
if (hires) {
return talloc_asprintf(ctx,
"%04d%02d%02d_%02d%02d%02d_%06ld",
tm->tm_year+1900,
tm->tm_mon+1,
tm->tm_mday,
tm->tm_hour,
tm->tm_min,
tm->tm_sec,
(long)tp->tv_usec);
} else {
return talloc_asprintf(ctx,
"%04d%02d%02d_%02d%02d%02d",
tm->tm_year+1900,
tm->tm_mon+1,
tm->tm_mday,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
}
}
}

char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires)
{
struct timeval tv;

GetTimeOfDay(&tv);
return minimal_timeval_string(ctx, &tv, hires);
}

/**
return a HTTP/1.0 time string
Expand Down
15 changes: 15 additions & 0 deletions lib/util/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,21 @@ char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires);
**/
char *current_timestring(TALLOC_CTX *ctx, bool hires);

/**
Return a date and time as a string (optionally with microseconds)
format is %Y%m%d_%H%M%S or %Y%m%d_%H%M%S_%us
**/

char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires);

/**
Return the current date and time as a string (optionally with microseconds)
format is %Y%m%d_%H%M%S or %Y%m%d_%H%M%S_%us
**/
char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires);

/**
return a HTTP/1.0 time string
**/
Expand Down
32 changes: 32 additions & 0 deletions source3/lib/substitute.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,20 @@ void standard_sub_basic(const char *smb_name, const char *domain_name,
TALLOC_FREE( s );
}

/*
* Limit addresses to hexalpha charactes and underscore, safe for path
* components for Windows clients.
*/
static void make_address_pathsafe(char *addr)
{
while(addr && *addr) {
if(!isxdigit(*addr)) {
*addr = '_';
}
++addr;
}
}

/****************************************************************************
Do some standard substitutions in a string.
This function will return a talloced string that has to be freed.
Expand Down Expand Up @@ -550,11 +564,25 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx,
sub_peeraddr[0] ? sub_peeraddr : "0.0.0.0");
break;
}
case 'J' : {
r = talloc_strdup(tmp_ctx,
sub_peeraddr[0] ? sub_peeraddr : "0.0.0.0");
make_address_pathsafe(r);
a_string = realloc_string_sub(a_string, "%J", r);
break;
}
case 'i':
a_string = realloc_string_sub(
a_string, "%i",
sub_sockaddr[0] ? sub_sockaddr : "0.0.0.0");
break;
case 'j' : {
r = talloc_strdup(tmp_ctx,
sub_sockaddr[0] ? sub_sockaddr : "0.0.0.0");
make_address_pathsafe(r);
a_string = realloc_string_sub(a_string, "%j", r);
break;
}
case 'L' :
if ( strncasecmp_m(p, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) {
break;
Expand All @@ -578,6 +606,10 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx,
case 'T' :
a_string = realloc_string_sub(a_string, "%T", current_timestring(tmp_ctx, False));
break;
case 't' :
a_string = realloc_string_sub(a_string, "%t",
current_minimal_timestring(tmp_ctx, False));
break;
case 'a' :
a_string = realloc_string_sub(a_string, "%a",
get_remote_arch_str());
Expand Down
53 changes: 53 additions & 0 deletions source3/torture/torture.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "../libcli/smb/smbXcli_base.h"
#include "lib/util/sys_rw_data.h"
#include "lib/util/base64.h"
#include "lib/util/time.h"

extern char *optarg;
extern int optind;
Expand Down Expand Up @@ -9906,6 +9907,54 @@ static bool run_symlink_open_test(int dummy)
return correct;
}

/*
* Only testing minimal time strings, as the others
* need (locale-dependent) guessing at what strftime does and
* even may differ in builds.
*/
static bool timesubst_test(void)
{
TALLOC_CTX *ctx = NULL;
/* Sa 23. Dez 04:33:20 CET 2017 */
const struct timeval tv = { 1514000000, 123 };
const char* expect_minimal = "20171223_033320";
const char* expect_minus = "20171223_033320_000123";
char *s;
char *env_tz, *orig_tz = NULL;
bool result = true;

ctx = talloc_new(NULL);

env_tz = getenv("TZ");
if(env_tz) {
orig_tz = talloc_strdup(ctx, env_tz);
}
setenv("TZ", "UTC", 1);

s = minimal_timeval_string(ctx, &tv, false);

if(!s || strcmp(s, expect_minimal)) {
printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
"[%s]\n", s ? s : "<nil>", expect_minimal);
result = false;
}
TALLOC_FREE(s);
s = minimal_timeval_string(ctx, &tv, true);
if(!s || strcmp(s, expect_minus)) {
printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
"[%s]\n", s ? s : "<nil>", expect_minus);
result = false;
}
TALLOC_FREE(s);

if(orig_tz) {
setenv("TZ", orig_tz, 1);
}

TALLOC_FREE(ctx);
return result;
}

static bool run_local_substitute(int dummy)
{
bool ok = true;
Expand All @@ -9918,6 +9967,10 @@ static bool run_local_substitute(int dummy)
ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
/* Substitution depends on current time, so better test the underlying
formatting function. At least covers %t. */
ok &= timesubst_test();

/* Different captialization rules in sub_basic... */

Expand Down

0 comments on commit ca66efc

Please sign in to comment.